diff --git a/src/Chunk.ts b/src/Chunk.ts index b9ee6619f57..7085a2942d4 100644 --- a/src/Chunk.ts +++ b/src/Chunk.ts @@ -659,7 +659,8 @@ export default class Chunk { freeze: options.freeze !== false, indent: this.indentString, namespaceToStringTag: options.namespaceToStringTag === true, - varOrConst: options.preferConst ? 'const' : 'var' + varOrConst: options.preferConst ? 'const' : 'var', + dynamicImportFunction: options.dynamicImportFunction || 'import' }; // Make sure the direct dependencies of a chunk are present to maintain execution order diff --git a/src/ast/nodes/Import.ts b/src/ast/nodes/Import.ts index 37164af3578..c2a7ffea870 100644 --- a/src/ast/nodes/Import.ts +++ b/src/ast/nodes/Import.ts @@ -11,10 +11,10 @@ interface DynamicImportMechanism { interopRight?: string; } -const getDynamicImportMechanism = (format: string, compact: boolean): DynamicImportMechanism => { - switch (format) { +const getDynamicImportMechanism = (options: RenderOptions): DynamicImportMechanism => { + switch (options.format) { case 'cjs': { - const _ = compact ? '' : ' '; + const _ = options.compact ? '' : ' '; return { left: 'Promise.resolve(require(', right: '))', @@ -23,9 +23,9 @@ const getDynamicImportMechanism = (format: string, compact: boolean): DynamicImp }; } case 'amd': { - const _ = compact ? '' : ' '; - const resolve = compact ? 'c' : 'resolve'; - const reject = compact ? 'e' : 'reject'; + const _ = options.compact ? '' : ' '; + const resolve = options.compact ? 'c' : 'resolve'; + const reject = options.compact ? 'e' : 'reject'; return { left: `new Promise(function${_}(${resolve},${_}${reject})${_}{${_}require([`, right: `],${_}${resolve},${_}${reject})${_}})`, @@ -38,6 +38,11 @@ const getDynamicImportMechanism = (format: string, compact: boolean): DynamicImp left: 'module.import(', right: ')' }; + case 'es': + return { + left: `${options.dynamicImportFunction}(`, + right: ')' + }; } }; @@ -78,7 +83,7 @@ export default class Import extends NodeBase { return; } - const importMechanism = getDynamicImportMechanism(options.format, options.compact); + const importMechanism = getDynamicImportMechanism(options); if (importMechanism) { const leftMechanism = (this.resolutionInterop && importMechanism.interopLeft) || importMechanism.left; diff --git a/src/rollup/types.d.ts b/src/rollup/types.d.ts index 8489f31d6f6..d0a80077ea1 100644 --- a/src/rollup/types.d.ts +++ b/src/rollup/types.d.ts @@ -321,6 +321,7 @@ export interface OutputOptions { sourcemapFile?: string; sourcemapPathTransform?: (sourcePath: string) => string; strict?: boolean; + dynamicImportFunction?: string; } export type WarningHandler = (warning: string | RollupWarning) => void; diff --git a/src/utils/mergeOptions.ts b/src/utils/mergeOptions.ts index 30abada9b8f..6dccbdb0cdf 100644 --- a/src/utils/mergeOptions.ts +++ b/src/utils/mergeOptions.ts @@ -260,6 +260,7 @@ function getOutputOptions( sourcemapExcludeSources: getOption('sourcemapExcludeSources'), sourcemapFile: getOption('sourcemapFile'), sourcemapPathTransform: getOption('sourcemapPathTransform'), - strict: getOption('strict', true) + strict: getOption('strict', true), + dynamicImportFunction: getOption('dynamicImportFunction', 'import') }; } diff --git a/src/utils/renderHelpers.ts b/src/utils/renderHelpers.ts index dc11da21357..c8c8fdb2b05 100644 --- a/src/utils/renderHelpers.ts +++ b/src/utils/renderHelpers.ts @@ -9,6 +9,7 @@ export interface RenderOptions { indent: string; namespaceToStringTag: boolean; varOrConst: 'var' | 'const'; + dynamicImportFunction: string; } export interface NodeRenderOptions { diff --git a/test/chunking-form/samples/dynamic-import-name/_config.js b/test/chunking-form/samples/dynamic-import-name/_config.js new file mode 100644 index 00000000000..ca14189518e --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-name/_config.js @@ -0,0 +1,14 @@ +module.exports = { + description: 'marks dynamic imports as external when resolveDynamicImport returns false', + options: { + input: 'main.js', + plugins: { + resolveDynamicImport(specifier) { + return false; + } + }, + output: { + dynamicImportFunction: 'foobar' + } + } +}; diff --git a/test/chunking-form/samples/dynamic-import-name/_expected/amd/main.js b/test/chunking-form/samples/dynamic-import-name/_expected/amd/main.js new file mode 100644 index 00000000000..b81e4d74b05 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-name/_expected/amd/main.js @@ -0,0 +1,5 @@ +define(['require'], function (require) { 'use strict'; + + new Promise(function (resolve, reject) { require(['./foo.js'], resolve, reject) }); + +}); diff --git a/test/chunking-form/samples/dynamic-import-name/_expected/cjs/main.js b/test/chunking-form/samples/dynamic-import-name/_expected/cjs/main.js new file mode 100644 index 00000000000..b1acd589703 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-name/_expected/cjs/main.js @@ -0,0 +1,3 @@ +'use strict'; + +Promise.resolve(require('./foo.js')); diff --git a/test/chunking-form/samples/dynamic-import-name/_expected/es/main.js b/test/chunking-form/samples/dynamic-import-name/_expected/es/main.js new file mode 100644 index 00000000000..51e216a3931 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-name/_expected/es/main.js @@ -0,0 +1 @@ +foobar('./foo.js'); diff --git a/test/chunking-form/samples/dynamic-import-name/_expected/system/main.js b/test/chunking-form/samples/dynamic-import-name/_expected/system/main.js new file mode 100644 index 00000000000..0824bad8d3f --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-name/_expected/system/main.js @@ -0,0 +1,10 @@ +System.register([], function (exports, module) { + 'use strict'; + return { + execute: function () { + + module.import('./foo.js'); + + } + }; +}); diff --git a/test/chunking-form/samples/dynamic-import-name/foo.js b/test/chunking-form/samples/dynamic-import-name/foo.js new file mode 100644 index 00000000000..81afa3157c1 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-name/foo.js @@ -0,0 +1 @@ +console.log('foo'); diff --git a/test/chunking-form/samples/dynamic-import-name/main.js b/test/chunking-form/samples/dynamic-import-name/main.js new file mode 100644 index 00000000000..bbe4a5cc219 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-name/main.js @@ -0,0 +1 @@ +import('./foo.js'); diff --git a/test/misc/optionList.js b/test/misc/optionList.js index 50080676ae6..93204262061 100644 --- a/test/misc/optionList.js +++ b/test/misc/optionList.js @@ -1,3 +1,3 @@ exports.input = 'acorn, acornInjectPlugins, cache, chunkGroupingSize, context, experimentalCacheExpiry, experimentalOptimizeChunks, experimentalTopLevelAwait, external, inlineDynamicImports, input, manualChunks, moduleContext, onwarn, perf, plugins, preserveModules, preserveSymlinks, shimMissingExports, treeshake, watch'; exports.flags = 'acorn, acornInjectPlugins, amd, assetFileNames, banner, c, cache, chunkFileNames, chunkGroupingSize, compact, config, context, d, dir, e, entryFileNames, environment, esModule, experimentalCacheExpiry, experimentalOptimizeChunks, experimentalTopLevelAwait, exports, extend, external, f, file, footer, format, freeze, g, globals, h, i, indent, inlineDynamicImports, input, interop, intro, m, manualChunks, moduleContext, n, name, namespaceToStringTag, noConflict, o, onwarn, outro, paths, perf, plugins, preferConst, preserveModules, preserveSymlinks, shimMissingExports, silent, sourcemap, sourcemapExcludeSources, sourcemapFile, strict, treeshake, v, w, watch'; -exports.output = 'amd, assetFileNames, banner, dir, chunkFileNames, compact, entryFileNames, esModule, exports, extend, file, footer, format, freeze, globals, indent, interop, intro, name, namespaceToStringTag, noConflict, outro, paths, preferConst, sourcemap, sourcemapExcludeSources, sourcemapFile, sourcemapPathTransform, strict'; +exports.output = 'amd, assetFileNames, banner, dir, chunkFileNames, compact, entryFileNames, esModule, exports, extend, file, footer, format, freeze, globals, indent, interop, intro, name, namespaceToStringTag, noConflict, outro, paths, preferConst, sourcemap, sourcemapExcludeSources, sourcemapFile, sourcemapPathTransform, strict, dynamicImportFunction';