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

[v3.0] Keep dynamic imports in CommonJS output #4647

Merged
merged 4 commits into from
Oct 7, 2022
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
1 change: 1 addition & 0 deletions cli/help.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Basic options:
--chunkFileNames <pattern> Name pattern for emitted secondary chunks
--compact Minify wrapper code
--context <variable> Specify top-level `this` value
--no-dynamicImportInCjs Write external dynamic CommonJS imports as require
--entryFileNames <pattern> Name pattern for emitted entry chunks
--environment <values> Settings passed to config file (see example)
--no-esModule Do not add __esModule property
Expand Down
1 change: 1 addition & 0 deletions docs/01-command-line-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ Many options have command line equivalents. In those cases, any arguments passed
--chunkFileNames <pattern> Name pattern for emitted secondary chunks
--compact Minify wrapper code
--context <variable> Specify top-level `this` value
--no-dynamicImportInCjs Write external dynamic CommonJS imports as require
--entryFileNames <pattern> Name pattern for emitted entry chunks
--environment <values> Settings passed to config file (see example)
--no-esModule Do not add __esModule property
Expand Down
46 changes: 46 additions & 0 deletions docs/999-big-list-of-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,52 @@ Type: `boolean`<br> CLI: `--compact`/`--no-compact`<br> Default: `false`

This will minify the wrapper code generated by rollup. Note that this does not affect code written by the user. This option is useful when bundling pre-minified code.

#### output.dynamicImportInCjs

Type: `boolean`<br> CLI: `--dynamicImportInCjs`/`--no-dynamicImportInCjs`<br> Default: `true`

While CommonJS output originally supported only `require(…)` to import dependencies, recent Node versions also started to support `import(…)`, which is the only way to import ES modules from CommonJS files. If this option is `true`, which is the default, Rollup will keep external dynamic imports as `import(…)` expressions in CommonJS output. Set this to `false` to rewrite dynamic imports using `require(…)` syntax.

```js
// input
import('external').then(console.log);

// cjs output with dynamicImportInCjs: true or not set
import('external').then(console.log);

// cjs output with dynamicImportInCjs: false
function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(
n,
k,
d.get
? d
: {
enumerable: true,
get: function () {
return e[k];
}
}
);
}
});
}
n.default = e;
return Object.freeze(n);
}

Promise.resolve()
.then(function () {
return /*#__PURE__*/ _interopNamespaceDefault(require('external'));
})
.then(console.log);
```

#### output.entryFileNames

Type: `string | ((chunkInfo: ChunkInfo) => string)`<br> CLI: `--entryFileNames <pattern>`<br> Default: `"[name].js"`
Expand Down
9 changes: 8 additions & 1 deletion src/ast/nodes/ImportExpression.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type MagicString from 'magic-string';
import ExternalModule from '../../ExternalModule';
import type Module from '../../Module';
import Module from '../../Module';
import type { GetInterop, NormalizedOutputOptions } from '../../rollup/types';
import type { PluginDriver } from '../../utils/PluginDriver';
import type { GenerateCodeSnippets } from '../../utils/generateCodeSnippets';
Expand Down Expand Up @@ -134,6 +134,7 @@ export default class ImportExpression extends NodeBase {
{
compact,
dynamicImportFunction,
dynamicImportInCjs,
format,
generatedCode: { arrowFunctions },
interop
Expand All @@ -156,6 +157,12 @@ export default class ImportExpression extends NodeBase {
const hasDynamicTarget = !this.resolution || typeof this.resolution === 'string';
switch (format) {
case 'cjs': {
if (
dynamicImportInCjs &&
(!resolution || typeof resolution === 'string' || resolution instanceof ExternalModule)
) {
return { helper: null, mechanism: null };
}
const helper = getInteropHelper(resolution, exportMode, interop);
let left = `require(`;
let right = `)`;
Expand Down
2 changes: 2 additions & 0 deletions src/rollup/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,7 @@ export interface OutputOptions {
dir?: string;
/** @deprecated Use the "renderDynamicImport" plugin hook instead. */
dynamicImportFunction?: string;
dynamicImportInCjs?: boolean;
entryFileNames?: string | ((chunkInfo: PreRenderedChunk) => string);
esModule?: boolean | 'if-default-prop';
exports?: 'default' | 'named' | 'none' | 'auto';
Expand Down Expand Up @@ -663,6 +664,7 @@ export interface NormalizedOutputOptions {
dir: string | undefined;
/** @deprecated Use the "renderDynamicImport" plugin hook instead. */
dynamicImportFunction: string | undefined;
dynamicImportInCjs: boolean;
entryFileNames: string | ((chunkInfo: PreRenderedChunk) => string);
esModule: boolean | 'if-default-prop';
exports: 'default' | 'named' | 'none' | 'auto';
Expand Down
1 change: 1 addition & 0 deletions src/utils/options/mergeOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ function mergeOutputOptions(
compact: getOption('compact'),
dir: getOption('dir'),
dynamicImportFunction: getOption('dynamicImportFunction'),
dynamicImportInCjs: getOption('dynamicImportInCjs'),
entryFileNames: getOption('entryFileNames'),
esModule: getOption('esModule'),
exports: getOption('exports'),
Expand Down
1 change: 1 addition & 0 deletions src/utils/options/normalizeOutputOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export function normalizeOutputOptions(
compact,
dir: getDir(config, file),
dynamicImportFunction: getDynamicImportFunction(config, inputOptions, format),
dynamicImportInCjs: config.dynamicImportInCjs ?? true,
entryFileNames: getEntryFileNames(config, unsetOptions),
esModule: config.esModule ?? 'if-default-prop',
exports: getExports(config, unsetOptions),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,5 @@
'use strict';

function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}

Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespaceDefault(require(
import /* () should not break */ (
/* webpackChunkName: "chunk-name" */
'./foo.js'/*suffix*/)); });
'./foo.js'/*suffix*/);
Original file line number Diff line number Diff line change
@@ -1,20 +1,3 @@
'use strict';

function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}

Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespaceDefault(require('./foo.js')); }).then(result => console.log(result));
import('./foo.js').then(result => console.log(result));
Original file line number Diff line number Diff line change
@@ -1,22 +1,5 @@
'use strict';

function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}

var dep = 'dep';

(function (t) { return Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespaceDefault(require(t)); }); })(dep);
import(dep);
Original file line number Diff line number Diff line change
@@ -1,20 +1,3 @@
'use strict';

function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}

Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespaceDefault(require('./foo.js')); });
import('./foo.js');
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,6 @@

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

function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}

Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespaceDefault(require('./ext\'ernal')); });
import('./ext\'ernal');

console.log('main', dep.value);
19 changes: 1 addition & 18 deletions test/chunking-form/samples/nested-chunks/_expected/cjs/main1.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,7 @@

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

function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}

console.log('main1', dep.value);

Promise.resolve().then(function () { return require('./generated-dynamic.js'); }).then(result => console.log(result));
Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespaceDefault(require('./external.js')); }).then(result => console.log(result));
import('./external.js').then(result => console.log(result));
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,7 @@

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

function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}

console.log('main2', dep.value);

Promise.resolve().then(function () { return require('../generated-dynamic.js'); }).then(result => console.log(result));
Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespaceDefault(require('../external.js')); }).then(result => console.log(result));
import('../external.js').then(result => console.log(result));
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,12 @@ require('to-indirect-relative-external');
require('direct-absolute-external');
require('to-indirect-absolute-external');

function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}

// nested
Promise.resolve().then(function () { return existing; });
Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespaceDefault(require('./direct-relative-external')); });
Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespaceDefault(require('to-indirect-relative-external')); });
Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespaceDefault(require('direct-absolute-external')); });
Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespaceDefault(require('to-indirect-absolute-external')); });
import('./direct-relative-external');
import('to-indirect-relative-external');
import('direct-absolute-external');
import('to-indirect-absolute-external');

const value = 'existing';
console.log('existing');
Expand All @@ -39,12 +22,12 @@ var existing = /*#__PURE__*/Object.freeze({

//main
Promise.resolve().then(function () { return existing; });
Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespaceDefault(require('./direct-relative-external')); });
Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespaceDefault(require('to-indirect-relative-external')); });
Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespaceDefault(require('direct-absolute-external')); });
Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespaceDefault(require('to-indirect-absolute-external')); });
import('./direct-relative-external');
import('to-indirect-relative-external');
import('direct-absolute-external');
import('to-indirect-absolute-external');

(function (t) { return Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespaceDefault(require(t)); }); })('dynamic-direct-external' + unknown);
Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespaceDefault(require('to-dynamic-indirect-external')); });
import('dynamic-direct-external' + unknown);
import('to-dynamic-indirect-external');
Promise.resolve().then(function () { return existing; });
(function (t) { return Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespaceDefault(require(t)); }); })('my' + 'replacement');
import('my' + 'replacement');
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ module.exports = {
output: {
globals: { external: 'external' },
name: 'bundle',
interop: 'auto'
interop: 'auto',
dynamicImportInCjs: false
}
}
};
3 changes: 2 additions & 1 deletion test/form/samples/dynamic-import-this-arrow/_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ module.exports = {
external: ['input', 'output'],
output: {
generatedCode: { arrowFunctions: true },
name: 'bundle'
name: 'bundle',
dynamicImportInCjs: false
}
}
};
3 changes: 2 additions & 1 deletion test/form/samples/dynamic-import-this-function/_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ module.exports = {
external: ['input', 'output'],
output: {
generatedCode: { arrowFunctions: false },
name: 'bundle'
name: 'bundle',
dynamicImportInCjs: false
}
}
};