Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add "exports-only" option to preserveSignature #3823

Merged
merged 1 commit into from Oct 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/05-plugin-development.md
Expand Up @@ -524,7 +524,7 @@ Emits a new file that is included in the build output and returns a `referenceId
fileName?: string,
implicitlyLoadedAfterOneOf?: string[],
importer?: string,
preserveSignature?: 'strict' | 'allow-extension' | false,
preserveSignature?: 'strict' | 'allow-extension' | 'exports-only' | false,
}

// EmittedAsset
Expand Down
3 changes: 2 additions & 1 deletion docs/999-big-list-of-options.md
Expand Up @@ -925,14 +925,15 @@ export default ({
```

#### preserveEntrySignatures
Type: `"strict" | "allow-extension" | false`<br>
Type: `"strict" | "allow-extension" | "exports-only" | false`<br>
CLI: `--preserveEntrySignatures <strict|allow-extension>`/`--no-preserveEntrySignatures`<br>
Default: `"strict"`

Controls if Rollup tries to ensure that entry chunks have the same exports as the underlying entry module.

- If set to `"strict"`, Rollup will create exactly the same exports in the entry chunk as there are in the corresponding entry module. If this is not possible because additional internal exports need to be added to a chunk, Rollup will instead create a "facade" entry chunk that reexports just the necessary bindings from other chunks but contains no code otherwise. This is the recommended setting for libraries.
- `"allow-extension"` will create all exports of the entry module in the entry chunk but may also add additional exports if necessary, avoiding a "facade" entry chunk. This setting makes sense for libraries where a strict signature is not required.
- `"exports-only"` behaves like `"strict"` if the entry module has exports, otherwise it behaves like `"allow-extension"`.
- `false` will not add any exports of an entry module to the corresponding chunk and does not even include the corresponding code unless those exports are used elsewhere in the bundle. Internal exports may be added to entry chunks, though. This is the recommended setting for web apps where the entry chunks are to be placed in script tags as it may reduce both the number of chunks and possibly the bundle size.

**Example**<br>
Expand Down
29 changes: 17 additions & 12 deletions src/Chunk.ts
Expand Up @@ -341,19 +341,24 @@ export default class Chunk {
if (requiredFacades.length === 0) {
requiredFacades.push({});
}
if (
!this.facadeModule &&
(this.outputOptions.preserveModules ||
module.preserveSignature !== 'strict' ||
this.canModuleBeFacade(module, exposedVariables))
) {
this.facadeModule = module;
this.facadeChunkByModule.set(module, this);
if (module.preserveSignature) {
this.strictFacade = module.preserveSignature === 'strict';
this.ensureReexportsAreAvailableForModule(module);
if (!this.facadeModule) {
const needsStrictFacade =
module.preserveSignature === 'strict' ||
(module.preserveSignature === 'exports-only' &&
module.getExportNamesByVariable().size !== 0);
if (
!needsStrictFacade ||
this.outputOptions.preserveModules ||
this.canModuleBeFacade(module, exposedVariables)
) {
this.facadeModule = module;
this.facadeChunkByModule.set(module, this);
if (module.preserveSignature) {
this.strictFacade = needsStrictFacade;
this.ensureReexportsAreAvailableForModule(module);
}
this.assignFacadeName(requiredFacades.shift()!, module);
}
this.assignFacadeName(requiredFacades.shift()!, module);
}

for (const facadeName of requiredFacades) {
Expand Down
2 changes: 1 addition & 1 deletion src/rollup/types.d.ts
Expand Up @@ -494,7 +494,7 @@ export type GlobalsOption = { [name: string]: string } | ((name: string) => stri
export type InputOption = string | string[] | { [entryAlias: string]: string };
export type ManualChunksOption = { [chunkAlias: string]: string[] } | GetManualChunk;
export type ModuleSideEffectsOption = boolean | 'no-external' | string[] | HasModuleSideEffects;
export type PreserveEntrySignaturesOption = false | 'strict' | 'allow-extension';
export type PreserveEntrySignaturesOption = false | 'strict' | 'allow-extension' | 'exports-only';
export type SourcemapPathTransformOption = (
relativeSourcePath: string,
sourcemapPath: string
Expand Down
@@ -1,5 +1,5 @@
module.exports = {
description: 'Creates a facade if necessary for strict entry signatures',
description: 'Never creates facades for allow-extension',
options: {
preserveEntrySignatures: 'allow-extension'
}
Expand Down
@@ -0,0 +1,6 @@
module.exports = {
description: 'Does not create a facade for exports-only if there are no exports',
options: {
preserveEntrySignatures: 'exports-only'
}
};
@@ -0,0 +1,5 @@
define(['./main'], function (main) { 'use strict';

globalThis.sharedDynamic = main.shared;

});
@@ -0,0 +1,13 @@
define(['require', 'exports'], function (require, exports) { 'use strict';

const shared = 'shared';

new Promise(function (resolve, reject) { require(['./generated-dynamic'], resolve, reject) });

globalThis.sharedStatic = shared;

exports.shared = shared;

Object.defineProperty(exports, '__esModule', { value: true });

});
@@ -0,0 +1,5 @@
'use strict';

var main = require('./main.js');

globalThis.sharedDynamic = main.shared;
@@ -0,0 +1,11 @@
'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

const shared = 'shared';

Promise.resolve().then(function () { return require('./generated-dynamic.js'); });

globalThis.sharedStatic = shared;

exports.shared = shared;
@@ -0,0 +1,3 @@
import { s as shared } from './main.js';

globalThis.sharedDynamic = shared;
@@ -0,0 +1,7 @@
const shared = 'shared';

import('./generated-dynamic.js');

globalThis.sharedStatic = shared;

export { shared as s };
@@ -0,0 +1,14 @@
System.register(['./main.js'], function () {
'use strict';
var shared;
return {
setters: [function (module) {
shared = module.s;
}],
execute: function () {

globalThis.sharedDynamic = shared;

}
};
});
@@ -0,0 +1,14 @@
System.register([], function (exports, module) {
'use strict';
return {
execute: function () {

const shared = exports('s', 'shared');

module.import('./generated-dynamic.js');

globalThis.sharedStatic = shared;

}
};
});
@@ -0,0 +1,3 @@
import { shared } from './lib.js';

globalThis.sharedDynamic = shared;
@@ -0,0 +1 @@
export const shared = 'shared';
@@ -0,0 +1,5 @@
import { shared } from './lib.js';

import('./dynamic.js');

globalThis.sharedStatic = shared;
@@ -0,0 +1,6 @@
module.exports = {
description: 'Creates a facade if necessary for exports-only if there are exports',
options: {
preserveEntrySignatures: 'exports-only'
}
};
@@ -0,0 +1,5 @@
define(['./generated-main'], function (main) { 'use strict';

globalThis.sharedDynamic = main.shared;

});
@@ -0,0 +1,14 @@
define(['require', 'exports'], function (require, exports) { 'use strict';

const shared = 'shared';

const unused = 'unused';
const dynamic = new Promise(function (resolve, reject) { require(['./generated-dynamic'], resolve, reject) });

globalThis.sharedStatic = shared;

exports.dynamic = dynamic;
exports.shared = shared;
exports.unused = unused;

});
@@ -0,0 +1,10 @@
define(['exports', './generated-main'], function (exports, main) { 'use strict';



exports.dynamic = main.dynamic;
exports.unused = main.unused;

Object.defineProperty(exports, '__esModule', { value: true });

});
@@ -0,0 +1,5 @@
'use strict';

var main = require('./generated-main.js');

globalThis.sharedDynamic = main.shared;
@@ -0,0 +1,12 @@
'use strict';

const shared = 'shared';

const unused = 'unused';
const dynamic = Promise.resolve().then(function () { return require('./generated-dynamic.js'); });

globalThis.sharedStatic = shared;

exports.dynamic = dynamic;
exports.shared = shared;
exports.unused = unused;
@@ -0,0 +1,10 @@
'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var main = require('./generated-main.js');



exports.dynamic = main.dynamic;
exports.unused = main.unused;
@@ -0,0 +1,3 @@
import { s as shared } from './generated-main.js';

globalThis.sharedDynamic = shared;
@@ -0,0 +1,8 @@
const shared = 'shared';

const unused = 'unused';
const dynamic = import('./generated-dynamic.js');

globalThis.sharedStatic = shared;

export { dynamic as d, shared as s, unused as u };
@@ -0,0 +1 @@
export { d as dynamic, u as unused } from './generated-main.js';
@@ -0,0 +1,14 @@
System.register(['./generated-main.js'], function () {
'use strict';
var shared;
return {
setters: [function (module) {
shared = module.s;
}],
execute: function () {

globalThis.sharedDynamic = shared;

}
};
});
@@ -0,0 +1,15 @@
System.register([], function (exports, module) {
'use strict';
return {
execute: function () {

const shared = exports('s', 'shared');

const unused = exports('u', 'unused');
const dynamic = exports('d', module.import('./generated-dynamic.js'));

globalThis.sharedStatic = shared;

}
};
});
@@ -0,0 +1,16 @@
System.register(['./generated-main.js'], function (exports) {
'use strict';
return {
setters: [function (module) {
var _setter = {};
_setter.dynamic = module.d;
_setter.unused = module.u;
exports(_setter);
}],
execute: function () {



}
};
});
@@ -0,0 +1,3 @@
import { shared } from './lib.js';

globalThis.sharedDynamic = shared;
@@ -0,0 +1 @@
export const shared = 'shared';
@@ -0,0 +1,6 @@
import { shared } from './lib.js';

export const unused = 'unused';
export const dynamic = import('./dynamic.js');

globalThis.sharedStatic = shared;