mirror of https://github.com/webpack/webpack.git
add support for async externals
add `promise` external add `import` external (uses import()) add `output.importFunctionName` option to change the `import()` function name allow for inline external type when using arrays fix some typings fix namespace object behavior when using system external and accessing nested property fix interop behavior for async dynamic modules
This commit is contained in:
parent
3c7f6a6616
commit
a66290a15f
|
|
@ -127,8 +127,7 @@ export type ExternalItem =
|
|||
};
|
||||
}
|
||||
| ((
|
||||
context: string,
|
||||
request: string,
|
||||
data: {context: string; request: string},
|
||||
callback: (err?: Error, result?: string) => void
|
||||
) => void);
|
||||
/**
|
||||
|
|
@ -150,7 +149,9 @@ export type ExternalsType =
|
|||
| "umd"
|
||||
| "umd2"
|
||||
| "jsonp"
|
||||
| "system";
|
||||
| "system"
|
||||
| "promise"
|
||||
| "import";
|
||||
/**
|
||||
* Filtering values.
|
||||
*/
|
||||
|
|
@ -397,6 +398,10 @@ export type HotUpdateMainFilename = string;
|
|||
* Wrap javascript code into IIFE's to avoid leaking into global scope.
|
||||
*/
|
||||
export type Iife = boolean;
|
||||
/**
|
||||
* The name of the native import() function (can be exchanged for a polyfill).
|
||||
*/
|
||||
export type ImportFunctionName = string;
|
||||
/**
|
||||
* The JSONP function used by webpack for async loading of chunks.
|
||||
*/
|
||||
|
|
@ -1586,6 +1591,10 @@ export interface Output {
|
|||
* Wrap javascript code into IIFE's to avoid leaking into global scope.
|
||||
*/
|
||||
iife?: Iife;
|
||||
/**
|
||||
* The name of the native import() function (can be exchanged for a polyfill).
|
||||
*/
|
||||
importFunctionName?: ImportFunctionName;
|
||||
/**
|
||||
* The JSONP function used by webpack for async loading of chunks.
|
||||
*/
|
||||
|
|
@ -2043,6 +2052,10 @@ export interface OutputNormalized {
|
|||
* Wrap javascript code into IIFE's to avoid leaking into global scope.
|
||||
*/
|
||||
iife?: Iife;
|
||||
/**
|
||||
* The name of the native import() function (can be exchanged for a polyfill).
|
||||
*/
|
||||
importFunctionName?: ImportFunctionName;
|
||||
/**
|
||||
* The JSONP function used by webpack for async loading of chunks.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ export type Overrides = (OverridesItem | OverridesObject)[] | OverridesObject;
|
|||
*/
|
||||
export type OverridesItem = string;
|
||||
/**
|
||||
* Type of library.
|
||||
* Specifies the default type of externals ('amd*', 'umd*', 'system' and 'jsonp' depend on output.libraryTarget set to the same value).
|
||||
*/
|
||||
export type LibraryType =
|
||||
export type ExternalsType =
|
||||
| "var"
|
||||
| "module"
|
||||
| "assign"
|
||||
|
|
@ -31,7 +31,9 @@ export type LibraryType =
|
|||
| "umd"
|
||||
| "umd2"
|
||||
| "jsonp"
|
||||
| "system";
|
||||
| "system"
|
||||
| "promise"
|
||||
| "import";
|
||||
/**
|
||||
* Container locations and request scopes from which modules should be resolved and loaded at runtime. When provided, property name is used as request scope, otherwise request scope is automatically inferred from container location.
|
||||
*/
|
||||
|
|
@ -53,7 +55,7 @@ export interface ContainerReferencePluginOptions {
|
|||
/**
|
||||
* The external type of the remote containers.
|
||||
*/
|
||||
remoteType: LibraryType;
|
||||
remoteType: ExternalsType;
|
||||
/**
|
||||
* Container locations and request scopes from which modules should be resolved and loaded at runtime. When provided, property name is used as request scope, otherwise request scope is automatically inferred from container location.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -74,6 +74,28 @@ export type Overrides = (OverridesItem | OverridesObject)[] | OverridesObject;
|
|||
* Request to a module in this container that should override overridable modules in the remote container.
|
||||
*/
|
||||
export type OverridesItem = string;
|
||||
/**
|
||||
* Specifies the default type of externals ('amd*', 'umd*', 'system' and 'jsonp' depend on output.libraryTarget set to the same value).
|
||||
*/
|
||||
export type ExternalsType =
|
||||
| "var"
|
||||
| "module"
|
||||
| "assign"
|
||||
| "this"
|
||||
| "window"
|
||||
| "self"
|
||||
| "global"
|
||||
| "commonjs"
|
||||
| "commonjs2"
|
||||
| "commonjs-module"
|
||||
| "amd"
|
||||
| "amd-require"
|
||||
| "umd"
|
||||
| "umd2"
|
||||
| "jsonp"
|
||||
| "system"
|
||||
| "promise"
|
||||
| "import";
|
||||
/**
|
||||
* Container locations and request scopes from which modules should be resolved and loaded at runtime. When provided, property name is used as request scope, otherwise request scope is automatically inferred from container location.
|
||||
*/
|
||||
|
|
@ -123,7 +145,7 @@ export interface ModuleFederationPluginOptions {
|
|||
/**
|
||||
* The external type of the remote containers.
|
||||
*/
|
||||
remoteType?: LibraryType;
|
||||
remoteType?: ExternalsType;
|
||||
/**
|
||||
* Container locations and request scopes from which modules should be resolved and loaded at runtime. When provided, property name is used as request scope, otherwise request scope is automatically inferred from container location.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ const makePathsRelative = require("./util/identifier").makePathsRelative;
|
|||
const validateOptions = require("schema-utils");
|
||||
const schema = require("../schemas/plugins/DllReferencePlugin.json");
|
||||
|
||||
/** @typedef {import("../declarations/WebpackOptions").Externals} Externals */
|
||||
/** @typedef {import("../declarations/plugins/DllReferencePlugin").DllReferencePluginOptions} DllReferencePluginOptions */
|
||||
/** @typedef {import("../declarations/plugins/DllReferencePlugin").DllReferencePluginOptionsManifest} DllReferencePluginOptionsManifest */
|
||||
|
||||
|
|
@ -106,6 +107,7 @@ class DllReferencePlugin {
|
|||
if (!content) content = manifest.content;
|
||||
}
|
||||
}
|
||||
/** @type {Externals} */
|
||||
const externals = {};
|
||||
const source = "dll-reference " + name;
|
||||
externals[source] = name;
|
||||
|
|
|
|||
|
|
@ -55,13 +55,35 @@ const getSourceForCommonJsExternal = moduleAndSpecifiers => {
|
|||
return `module.exports = require(${JSON.stringify(moduleAndSpecifiers)});`;
|
||||
}
|
||||
const moduleName = moduleAndSpecifiers[0];
|
||||
const objectLookup = moduleAndSpecifiers
|
||||
.slice(1)
|
||||
.map(r => `[${JSON.stringify(r)}]`)
|
||||
.join("");
|
||||
return `module.exports = require(${JSON.stringify(
|
||||
moduleName
|
||||
)})${objectLookup};`;
|
||||
)})${propertyAccess(moduleAndSpecifiers, 1)};`;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string|string[]} moduleAndSpecifiers the module request
|
||||
* @param {RuntimeTemplate} runtimeTemplate the runtime template
|
||||
* @returns {string} the generated source
|
||||
*/
|
||||
const getSourceForImportExternal = (moduleAndSpecifiers, runtimeTemplate) => {
|
||||
const importName = runtimeTemplate.outputOptions.importFunctionName;
|
||||
if (!Array.isArray(moduleAndSpecifiers)) {
|
||||
return `module.exports = ${importName}(${JSON.stringify(
|
||||
moduleAndSpecifiers
|
||||
)});`;
|
||||
}
|
||||
if (moduleAndSpecifiers.length === 1) {
|
||||
return `module.exports = ${importName}(${JSON.stringify(
|
||||
moduleAndSpecifiers[0]
|
||||
)});`;
|
||||
}
|
||||
const moduleName = moduleAndSpecifiers[0];
|
||||
return `module.exports = ${importName}(${JSON.stringify(
|
||||
moduleName
|
||||
)}).then(${runtimeTemplate.returningFunction(
|
||||
`module${propertyAccess(moduleAndSpecifiers, 1)}`,
|
||||
"module"
|
||||
)});`;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -196,15 +218,27 @@ class ExternalModule extends Module {
|
|||
*/
|
||||
build(options, compilation, resolver, fs, callback) {
|
||||
this.buildMeta = {
|
||||
async: false,
|
||||
exportsType: undefined
|
||||
};
|
||||
this.buildInfo = {
|
||||
strict: true
|
||||
};
|
||||
this.clearDependenciesAndBlocks();
|
||||
if (this.externalType === "system") {
|
||||
this.buildMeta.exportsType = "namespace";
|
||||
this.addDependency(new StaticExportsDependency(true, true));
|
||||
switch (this.externalType) {
|
||||
case "system":
|
||||
if (!Array.isArray(this.request) || this.request.length === 1)
|
||||
this.buildMeta.exportsType = "namespace";
|
||||
this.addDependency(new StaticExportsDependency(true, true));
|
||||
break;
|
||||
case "promise":
|
||||
this.buildMeta.async = true;
|
||||
break;
|
||||
case "import":
|
||||
this.buildMeta.async = true;
|
||||
if (!Array.isArray(this.request) || this.request.length === 1)
|
||||
this.buildMeta.exportsType = "namespace";
|
||||
break;
|
||||
}
|
||||
callback();
|
||||
}
|
||||
|
|
@ -240,9 +274,12 @@ class ExternalModule extends Module {
|
|||
request,
|
||||
runtimeTemplate
|
||||
);
|
||||
case "import":
|
||||
return getSourceForImportExternal(request, runtimeTemplate);
|
||||
case "module":
|
||||
throw new Error("Module external type is not implemented yet");
|
||||
case "var":
|
||||
case "promise":
|
||||
case "const":
|
||||
case "let":
|
||||
case "assign":
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@
|
|||
|
||||
const util = require("util");
|
||||
const ExternalModule = require("./ExternalModule");
|
||||
|
||||
/** @typedef {import("../declarations/WebpackOptions").Externals} Externals */
|
||||
/** @typedef {import("./NormalModuleFactory")} NormalModuleFactory */
|
||||
|
||||
const UNSPECIFIED_EXTERNAL_TYPE_REGEXP = /^[a-z0-9]+ /;
|
||||
|
||||
// TODO webpack 6 remove this
|
||||
|
|
@ -19,11 +23,19 @@ const callDeprecatedExternals = util.deprecate(
|
|||
);
|
||||
|
||||
class ExternalModuleFactoryPlugin {
|
||||
/**
|
||||
* @param {string | undefined} type default external type
|
||||
* @param {Externals} externals externals config
|
||||
*/
|
||||
constructor(type, externals) {
|
||||
this.type = type;
|
||||
this.externals = externals;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {NormalModuleFactory} normalModuleFactory the normal module factory
|
||||
* @returns {void}
|
||||
*/
|
||||
apply(normalModuleFactory) {
|
||||
const globalType = this.type;
|
||||
normalModuleFactory.hooks.factorize.tapAsync(
|
||||
|
|
@ -33,7 +45,7 @@ class ExternalModuleFactoryPlugin {
|
|||
const dependency = data.dependencies[0];
|
||||
|
||||
/**
|
||||
* @param {string|boolean} value the external config
|
||||
* @param {string|string[]|boolean|Record<string, string|string[]>} value the external config
|
||||
* @param {string|undefined} type type of external
|
||||
* @param {function(Error=, ExternalModule=): void} callback callback
|
||||
* @returns {void}
|
||||
|
|
@ -43,7 +55,7 @@ class ExternalModuleFactoryPlugin {
|
|||
// Not externals, fallback to original factory
|
||||
return callback();
|
||||
}
|
||||
/** @type {string} */
|
||||
/** @type {string | string[] | Record<string, string|string[]>} */
|
||||
let externalConfig;
|
||||
if (value === true) {
|
||||
externalConfig = dependency.request;
|
||||
|
|
@ -51,13 +63,27 @@ class ExternalModuleFactoryPlugin {
|
|||
externalConfig = value;
|
||||
}
|
||||
// When no explicit type is specified, extract it from the externalConfig
|
||||
if (
|
||||
type === undefined &&
|
||||
UNSPECIFIED_EXTERNAL_TYPE_REGEXP.test(externalConfig)
|
||||
) {
|
||||
const idx = externalConfig.indexOf(" ");
|
||||
type = externalConfig.substr(0, idx);
|
||||
externalConfig = externalConfig.substr(idx + 1);
|
||||
if (type === undefined) {
|
||||
if (
|
||||
typeof externalConfig === "string" &&
|
||||
UNSPECIFIED_EXTERNAL_TYPE_REGEXP.test(externalConfig)
|
||||
) {
|
||||
const idx = externalConfig.indexOf(" ");
|
||||
type = externalConfig.substr(0, idx);
|
||||
externalConfig = externalConfig.substr(idx + 1);
|
||||
} else if (
|
||||
Array.isArray(externalConfig) &&
|
||||
externalConfig.length > 0 &&
|
||||
UNSPECIFIED_EXTERNAL_TYPE_REGEXP.test(externalConfig[0])
|
||||
) {
|
||||
const firstItem = externalConfig[0];
|
||||
const idx = firstItem.indexOf(" ");
|
||||
type = firstItem.substr(0, idx);
|
||||
externalConfig = [
|
||||
firstItem.substr(idx + 1),
|
||||
...externalConfig.slice(1)
|
||||
];
|
||||
}
|
||||
}
|
||||
callback(
|
||||
null,
|
||||
|
|
@ -69,6 +95,11 @@ class ExternalModuleFactoryPlugin {
|
|||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Externals} externals externals config
|
||||
* @param {function(Error=, ExternalModule=): void} callback callback
|
||||
* @returns {void}
|
||||
*/
|
||||
const handleExternals = (externals, callback) => {
|
||||
if (typeof externals === "string") {
|
||||
if (externals === dependency.request) {
|
||||
|
|
|
|||
|
|
@ -7,9 +7,14 @@
|
|||
|
||||
const ExternalModuleFactoryPlugin = require("./ExternalModuleFactoryPlugin");
|
||||
|
||||
/** @typedef {import("../declarations/WebpackOptions").Externals} Externals */
|
||||
/** @typedef {import("./Compiler")} Compiler */
|
||||
|
||||
class ExternalsPlugin {
|
||||
/**
|
||||
* @param {string | undefined} type default external type
|
||||
* @param {Externals} externals externals config
|
||||
*/
|
||||
constructor(type, externals) {
|
||||
this.type = type;
|
||||
this.externals = externals;
|
||||
|
|
|
|||
|
|
@ -115,5 +115,6 @@ InitFragment.STAGE_HARMONY_EXPORTS = 30;
|
|||
InitFragment.STAGE_HARMONY_IMPORTS = 40;
|
||||
InitFragment.STAGE_PROVIDES = 50;
|
||||
InitFragment.STAGE_ASYNC_DEPENDENCIES = 60;
|
||||
InitFragment.STAGE_ASYNC_HARMONY_IMPORTS = 70;
|
||||
|
||||
module.exports = InitFragment;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const RuntimeGlobals = require("./RuntimeGlobals");
|
|||
const Template = require("./Template");
|
||||
const propertyAccess = require("./util/propertyAccess");
|
||||
|
||||
/** @typedef {import("../declarations/WebpackOptions").Output} OutputOptions */
|
||||
/** @typedef {import("../declarations/WebpackOptions").OutputNormalized} OutputOptions */
|
||||
/** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */
|
||||
/** @typedef {import("./ChunkGraph")} ChunkGraph */
|
||||
/** @typedef {import("./InitFragment")} InitFragment */
|
||||
|
|
@ -398,7 +398,7 @@ class RuntimeTemplate {
|
|||
runtimeRequirements
|
||||
});
|
||||
|
||||
let getModuleFunction;
|
||||
let appending;
|
||||
let idExpr = JSON.stringify(chunkGraph.getModuleId(module));
|
||||
const comment = this.comment({
|
||||
request
|
||||
|
|
@ -439,13 +439,13 @@ class RuntimeTemplate {
|
|||
weak,
|
||||
runtimeRequirements
|
||||
});
|
||||
getModuleFunction = this.basicFunction(
|
||||
appending = `.then(${this.basicFunction(
|
||||
"",
|
||||
`${header}return ${rawModule};`
|
||||
);
|
||||
)})`;
|
||||
} else {
|
||||
runtimeRequirements.add(RuntimeGlobals.require);
|
||||
getModuleFunction = `__webpack_require__.bind(__webpack_require__, ${comment}${idExpr})`;
|
||||
appending = `.then(__webpack_require__.bind(__webpack_require__, ${comment}${idExpr}))`;
|
||||
}
|
||||
break;
|
||||
case "dynamic":
|
||||
|
|
@ -457,18 +457,42 @@ class RuntimeTemplate {
|
|||
case "default-only":
|
||||
fakeType |= 1;
|
||||
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
|
||||
if (header) {
|
||||
const returnExpression = `${RuntimeGlobals.createFakeNamespaceObject}(${moduleIdExpr}, ${fakeType})`;
|
||||
getModuleFunction = header
|
||||
? this.basicFunction("", `${header}return ${returnExpression};`)
|
||||
: this.returningFunction(returnExpression);
|
||||
if (chunkGraph.moduleGraph.isAsync(module)) {
|
||||
if (header) {
|
||||
const rawModule = this.moduleRaw({
|
||||
module,
|
||||
chunkGraph,
|
||||
request,
|
||||
weak,
|
||||
runtimeRequirements
|
||||
});
|
||||
appending = `.then(${this.basicFunction(
|
||||
"",
|
||||
`${header}return ${rawModule};`
|
||||
)})`;
|
||||
} else {
|
||||
runtimeRequirements.add(RuntimeGlobals.require);
|
||||
appending = `.then(__webpack_require__.bind(__webpack_require__, ${comment}${idExpr}))`;
|
||||
}
|
||||
appending += `.then(${this.returningFunction(
|
||||
`${RuntimeGlobals.createFakeNamespaceObject}(m, ${fakeType})`,
|
||||
"m"
|
||||
)})`;
|
||||
} else {
|
||||
getModuleFunction = `${RuntimeGlobals.createFakeNamespaceObject}.bind(__webpack_require__, ${comment}${idExpr}, ${fakeType})`;
|
||||
if (header) {
|
||||
const returnExpression = `${RuntimeGlobals.createFakeNamespaceObject}(${moduleIdExpr}, ${fakeType})`;
|
||||
appending = `.then(${this.basicFunction(
|
||||
"",
|
||||
`${header}return ${returnExpression};`
|
||||
)})`;
|
||||
} else {
|
||||
appending = `.then(${RuntimeGlobals.createFakeNamespaceObject}.bind(__webpack_require__, ${comment}${idExpr}, ${fakeType}))`;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return `${promise || "Promise.resolve()"}.then(${getModuleFunction})`;
|
||||
return `${promise || "Promise.resolve()"}${appending}`;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -482,7 +506,7 @@ class RuntimeTemplate {
|
|||
* @param {Module} options.originModule module in which the statement is emitted
|
||||
* @param {boolean=} options.weak true, if this is a weak dependency
|
||||
* @param {Set<string>} options.runtimeRequirements if set, will be filled with runtime requirements
|
||||
* @returns {string} the import statement
|
||||
* @returns {[string, string]} the import statement and the compat statement
|
||||
*/
|
||||
importStatement({
|
||||
update,
|
||||
|
|
@ -495,20 +519,26 @@ class RuntimeTemplate {
|
|||
runtimeRequirements
|
||||
}) {
|
||||
if (!module) {
|
||||
return this.missingModuleStatement({
|
||||
request
|
||||
});
|
||||
return [
|
||||
this.missingModuleStatement({
|
||||
request
|
||||
}),
|
||||
""
|
||||
];
|
||||
}
|
||||
if (chunkGraph.getModuleId(module) === null) {
|
||||
if (weak) {
|
||||
// only weak referenced modules don't get an id
|
||||
// we can always emit an error emitting code here
|
||||
return this.weakError({
|
||||
module,
|
||||
chunkGraph,
|
||||
request,
|
||||
type: "statements"
|
||||
});
|
||||
return [
|
||||
this.weakError({
|
||||
module,
|
||||
chunkGraph,
|
||||
request,
|
||||
type: "statements"
|
||||
}),
|
||||
""
|
||||
];
|
||||
}
|
||||
throw new Error(
|
||||
`RuntimeTemplate.importStatement(): Module ${module.identifier()} has no id. This should not happen.`
|
||||
|
|
@ -522,15 +552,20 @@ class RuntimeTemplate {
|
|||
});
|
||||
const optDeclaration = update ? "" : "var ";
|
||||
|
||||
const exportsType = module.buildMeta && module.buildMeta.exportsType;
|
||||
const exportsType = module.getExportsType(
|
||||
originModule.buildMeta.strictHarmonyModule
|
||||
);
|
||||
runtimeRequirements.add(RuntimeGlobals.require);
|
||||
let content = `/* harmony import */ ${optDeclaration}${importVar} = __webpack_require__(${moduleId});\n`;
|
||||
const importContent = `/* harmony import */ ${optDeclaration}${importVar} = __webpack_require__(${moduleId});\n`;
|
||||
|
||||
if (!exportsType && !originModule.buildMeta.strictHarmonyModule) {
|
||||
if (exportsType === "dynamic") {
|
||||
runtimeRequirements.add(RuntimeGlobals.compatGetDefaultExport);
|
||||
content += `/* harmony import */ ${optDeclaration}${importVar}_default = /*#__PURE__*/${RuntimeGlobals.compatGetDefaultExport}(${importVar});\n`;
|
||||
return [
|
||||
importContent,
|
||||
`/* harmony import */ ${optDeclaration}${importVar}_default = /*#__PURE__*/${RuntimeGlobals.compatGetDefaultExport}(${importVar});\n`
|
||||
];
|
||||
}
|
||||
return content;
|
||||
return [importContent, ""];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -379,6 +379,7 @@ const applyOutputDefaults = (
|
|||
F(output, "module", () => !!outputModule);
|
||||
F(output, "iife", () => !output.module);
|
||||
D(output, "ecmaVersion", 6);
|
||||
D(output, "importFunctionName", "import");
|
||||
F(output, "chunkFilename", () => {
|
||||
const filename = output.filename;
|
||||
if (typeof filename !== "function") {
|
||||
|
|
|
|||
|
|
@ -202,6 +202,7 @@ const getNormalizedWebpackOptions = config => {
|
|||
hotUpdateFunction: output.hotUpdateFunction,
|
||||
hotUpdateMainFilename: output.hotUpdateMainFilename,
|
||||
iife: output.iife,
|
||||
importFunctionName: output.importFunctionName,
|
||||
jsonpFunction: output.jsonpFunction,
|
||||
jsonpScriptType: output.jsonpScriptType,
|
||||
library: libraryBase && {
|
||||
|
|
|
|||
|
|
@ -67,7 +67,10 @@ HarmonyAcceptDependency.Template = class HarmonyAcceptDependencyTemplate extends
|
|||
.filter(dependency =>
|
||||
HarmonyImportDependency.Template.isImportEmitted(dependency, module)
|
||||
)
|
||||
.map(dependency => dependency.getImportStatement(true, templateContext))
|
||||
.map(dependency => {
|
||||
const s = dependency.getImportStatement(true, templateContext);
|
||||
return s[0] + s[1];
|
||||
})
|
||||
.join("");
|
||||
|
||||
if (dep.hasCallback) {
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ class HarmonyImportDependency extends ModuleDependency {
|
|||
/**
|
||||
* @param {boolean} update create new variables or update existing one
|
||||
* @param {DependencyTemplateContext} templateContext the template context
|
||||
* @returns {string} name of the variable for the import
|
||||
* @returns {[string, string]} the import statement and the compat statement
|
||||
*/
|
||||
getImportStatement(
|
||||
update,
|
||||
|
|
@ -253,20 +253,38 @@ HarmonyImportDependency.Template = class HarmonyImportDependencyTemplate extends
|
|||
emittedModules.add(module);
|
||||
}
|
||||
|
||||
templateContext.initFragments.push(
|
||||
new InitFragment(
|
||||
dep.getImportStatement(false, templateContext),
|
||||
InitFragment.STAGE_HARMONY_IMPORTS,
|
||||
dep.sourceOrder,
|
||||
key
|
||||
)
|
||||
);
|
||||
const importStatement = dep.getImportStatement(false, templateContext);
|
||||
if (templateContext.moduleGraph.isAsync(referencedModule)) {
|
||||
templateContext.initFragments.push(
|
||||
new InitFragment(
|
||||
importStatement[0],
|
||||
InitFragment.STAGE_HARMONY_IMPORTS,
|
||||
dep.sourceOrder,
|
||||
key
|
||||
)
|
||||
);
|
||||
templateContext.initFragments.push(
|
||||
new AwaitDependenciesInitFragment(
|
||||
new Set([dep.getImportVar(templateContext.moduleGraph)])
|
||||
)
|
||||
);
|
||||
templateContext.initFragments.push(
|
||||
new InitFragment(
|
||||
importStatement[1],
|
||||
InitFragment.STAGE_ASYNC_HARMONY_IMPORTS,
|
||||
dep.sourceOrder,
|
||||
key + " compat"
|
||||
)
|
||||
);
|
||||
} else {
|
||||
templateContext.initFragments.push(
|
||||
new InitFragment(
|
||||
importStatement[0] + importStatement[1],
|
||||
InitFragment.STAGE_HARMONY_IMPORTS,
|
||||
dep.sourceOrder,
|
||||
key
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -139,9 +139,14 @@ class SystemLibraryPlugin extends AbstractLibraryPlugin {
|
|||
}
|
||||
}
|
||||
if (!otherUnused) {
|
||||
externalVarInitialization.push(
|
||||
`Object.defineProperty(${external}, "__esModule", { value: true });`
|
||||
);
|
||||
if (
|
||||
!Array.isArray(module.request) ||
|
||||
module.request.length === 1
|
||||
) {
|
||||
externalVarInitialization.push(
|
||||
`Object.defineProperty(${external}, "__esModule", { value: true });`
|
||||
);
|
||||
}
|
||||
if (handledNames.length > 0) {
|
||||
const name = `${external}handledNames`;
|
||||
externalVarInitialization.push(
|
||||
|
|
|
|||
|
|
@ -103,6 +103,8 @@ class AsyncWebAssemblyJavascriptGenerator extends Generator {
|
|||
});
|
||||
}
|
||||
);
|
||||
const importsCode = importStatements.map(([x]) => x).join("");
|
||||
const importsCompatCode = importStatements.map(([_, x]) => x).join("");
|
||||
|
||||
const importObjRequestItems = Array.from(
|
||||
wasmDepsByRequest,
|
||||
|
|
@ -149,18 +151,28 @@ class AsyncWebAssemblyJavascriptGenerator extends Generator {
|
|||
(importsObj ? `, ${importsObj})` : `)`);
|
||||
|
||||
const source = new RawSource(
|
||||
Template.asString([
|
||||
...importStatements,
|
||||
`${importsCode}${
|
||||
promises.length > 1
|
||||
? `${module.moduleArgument}.exports = Promise.all([${promises.join(
|
||||
", "
|
||||
)}]).then(function([${promises.join(
|
||||
", "
|
||||
)}]) { return ${instantiateCall}; })`
|
||||
? Template.asString([
|
||||
`${module.moduleArgument}.exports = Promise.all([${promises.join(
|
||||
", "
|
||||
)}]).then(${runtimeTemplate.basicFunction(
|
||||
`[${promises.join(", ")}]`,
|
||||
`${importsCompatCode}return ${instantiateCall};`
|
||||
)})`
|
||||
])
|
||||
: promises.length === 1
|
||||
? `${module.moduleArgument}.exports = Promise.resolve(${promises[0]}).then(function(${promises[0]}) { return ${instantiateCall}; })`
|
||||
: `${module.moduleArgument}.exports = ${instantiateCall}`
|
||||
])
|
||||
? Template.asString([
|
||||
`${module.moduleArgument}.exports = Promise.resolve(${
|
||||
promises[0]
|
||||
}).then(${runtimeTemplate.basicFunction(
|
||||
promises[0],
|
||||
|
||||
`${importsCompatCode}return ${instantiateCall};`
|
||||
)})`
|
||||
])
|
||||
: `${importsCompatCode}${module.moduleArgument}.exports = ${instantiateCall}`
|
||||
}`
|
||||
);
|
||||
return InitFragment.addToSource(source, initFragments, generateContext);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ class WebAssemblyJavascriptGenerator extends Generator {
|
|||
originModule: module,
|
||||
runtimeRequirements
|
||||
});
|
||||
return importStatement + reexports.join("\n");
|
||||
return importStatement[0] + importStatement[1] + reexports.join("\n");
|
||||
}
|
||||
)
|
||||
);
|
||||
|
|
|
|||
|
|
@ -429,7 +429,7 @@
|
|||
{
|
||||
"description": "The function is called on each dependency (`function(context, request, callback(err, result))`).",
|
||||
"instanceof": "Function",
|
||||
"tsType": "((context: string, request: string, callback: (err?: Error, result?: string) => void) => void)"
|
||||
"tsType": "((data: { context: string, request: string }, callback: (err?: Error, result?: string) => void) => void)"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -465,7 +465,9 @@
|
|||
"umd",
|
||||
"umd2",
|
||||
"jsonp",
|
||||
"system"
|
||||
"system",
|
||||
"promise",
|
||||
"import"
|
||||
]
|
||||
},
|
||||
"FileCacheOptions": {
|
||||
|
|
@ -658,6 +660,10 @@
|
|||
"description": "Wrap javascript code into IIFE's to avoid leaking into global scope.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"ImportFunctionName": {
|
||||
"description": "The name of the native import() function (can be exchanged for a polyfill).",
|
||||
"type": "string"
|
||||
},
|
||||
"InfrastructureLogging": {
|
||||
"description": "Options for infrastructure level logging.",
|
||||
"type": "object",
|
||||
|
|
@ -1694,6 +1700,9 @@
|
|||
"iife": {
|
||||
"$ref": "#/definitions/Iife"
|
||||
},
|
||||
"importFunctionName": {
|
||||
"$ref": "#/definitions/ImportFunctionName"
|
||||
},
|
||||
"jsonpFunction": {
|
||||
"$ref": "#/definitions/JsonpFunction"
|
||||
},
|
||||
|
|
@ -1834,6 +1843,9 @@
|
|||
"iife": {
|
||||
"$ref": "#/definitions/Iife"
|
||||
},
|
||||
"importFunctionName": {
|
||||
"$ref": "#/definitions/ImportFunctionName"
|
||||
},
|
||||
"jsonpFunction": {
|
||||
"$ref": "#/definitions/JsonpFunction"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"definitions": {
|
||||
"LibraryType": {
|
||||
"description": "Type of library.",
|
||||
"ExternalsType": {
|
||||
"description": "Specifies the default type of externals ('amd*', 'umd*', 'system' and 'jsonp' depend on output.libraryTarget set to the same value).",
|
||||
"enum": [
|
||||
"var",
|
||||
"module",
|
||||
|
|
@ -18,7 +18,9 @@
|
|||
"umd",
|
||||
"umd2",
|
||||
"jsonp",
|
||||
"system"
|
||||
"system",
|
||||
"promise",
|
||||
"import"
|
||||
]
|
||||
},
|
||||
"Overrides": {
|
||||
|
|
@ -157,7 +159,7 @@
|
|||
"description": "The external type of the remote containers.",
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/LibraryType"
|
||||
"$ref": "#/definitions/ExternalsType"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -83,6 +83,29 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
"ExternalsType": {
|
||||
"description": "Specifies the default type of externals ('amd*', 'umd*', 'system' and 'jsonp' depend on output.libraryTarget set to the same value).",
|
||||
"enum": [
|
||||
"var",
|
||||
"module",
|
||||
"assign",
|
||||
"this",
|
||||
"window",
|
||||
"self",
|
||||
"global",
|
||||
"commonjs",
|
||||
"commonjs2",
|
||||
"commonjs-module",
|
||||
"amd",
|
||||
"amd-require",
|
||||
"umd",
|
||||
"umd2",
|
||||
"jsonp",
|
||||
"system",
|
||||
"promise",
|
||||
"import"
|
||||
]
|
||||
},
|
||||
"LibraryCustomUmdCommentObject": {
|
||||
"description": "Set explicit comments for `commonjs`, `commonjs2`, `amd`, and `root`.",
|
||||
"type": "object",
|
||||
|
|
@ -503,7 +526,7 @@
|
|||
"description": "The external type of the remote containers.",
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/LibraryType"
|
||||
"$ref": "#/definitions/ExternalsType"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -3917,7 +3917,7 @@ Built at: 1970-04-20 12:42:42
|
|||
256e72dd8b9a83a6e45b.module.wasm 120 bytes [emitted] [immutable]
|
||||
325.bundle.js 3.74 KiB [emitted]
|
||||
526.bundle.js 368 bytes [emitted] [id hint: vendors]
|
||||
780.bundle.js 526 bytes [emitted]
|
||||
780.bundle.js 525 bytes [emitted]
|
||||
99.bundle.js 220 bytes [emitted]
|
||||
a0e9dd97d7ced35a5b2c.module.wasm 154 bytes [emitted] [immutable]
|
||||
bundle.js 11 KiB [emitted] [name: main-1df31ce3]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
import value from "promise-external";
|
||||
import request from "import-external";
|
||||
|
||||
it("should allow async externals", () => {
|
||||
expect(value).toBe(42);
|
||||
expect(request).toBe("/hello/world.js");
|
||||
});
|
||||
|
||||
it("should allow to catch errors of async externals", () => {
|
||||
return expect(() => import("failing-promise-external")).rejects.toEqual(
|
||||
expect.objectContaining({
|
||||
message: "external reject"
|
||||
})
|
||||
);
|
||||
});
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
module.exports = {
|
||||
output: {
|
||||
libraryTarget: "commonjs-module",
|
||||
importFunctionName: "((name) => Promise.resolve({ request: name }))"
|
||||
},
|
||||
externals: {
|
||||
"promise-external":
|
||||
"promise new Promise(resolve => setTimeout(() => resolve(42), 100))",
|
||||
"failing-promise-external":
|
||||
"promise new Promise((resolve, reject) => setTimeout(() => reject(new Error('external reject')), 100))",
|
||||
"import-external": ["import /hello/world.js", "request"]
|
||||
},
|
||||
experiments: {
|
||||
importAsync: true
|
||||
}
|
||||
};
|
||||
|
|
@ -1337,7 +1337,7 @@ declare interface Configuration {
|
|||
/**
|
||||
* Specifies the default type of externals ('amd*', 'umd*', 'system' and 'jsonp' depend on output.libraryTarget set to the same value).
|
||||
*/
|
||||
externalsType?: LibraryType;
|
||||
externalsType?: ExternalsType;
|
||||
|
||||
/**
|
||||
* Options for infrastructure level logging.
|
||||
|
|
@ -1498,7 +1498,7 @@ declare interface ContainerReferencePluginOptions {
|
|||
/**
|
||||
* The external type of the remote containers.
|
||||
*/
|
||||
remoteType: LibraryType;
|
||||
remoteType: ExternalsType;
|
||||
|
||||
/**
|
||||
* Container locations and request scopes from which modules should be resolved and loaded at runtime. When provided, property name is used as request scope, otherwise request scope is automatically inferred from container location.
|
||||
|
|
@ -2310,8 +2310,7 @@ type ExternalItem =
|
|||
| RegExp
|
||||
| { [index: string]: string | boolean | string[] | { [index: string]: any } }
|
||||
| ((
|
||||
context: string,
|
||||
request: string,
|
||||
data: { context: string; request: string },
|
||||
callback: (err: Error, result: string) => void
|
||||
) => void);
|
||||
declare class ExternalModule extends Module {
|
||||
|
|
@ -2331,20 +2330,38 @@ type Externals =
|
|||
| ExternalItem[]
|
||||
| { [index: string]: string | boolean | string[] | { [index: string]: any } }
|
||||
| ((
|
||||
context: string,
|
||||
request: string,
|
||||
data: { context: string; request: string },
|
||||
callback: (err: Error, result: string) => void
|
||||
) => void);
|
||||
declare class ExternalsPlugin {
|
||||
constructor(type?: any, externals?: any);
|
||||
type: any;
|
||||
externals: any;
|
||||
constructor(type: string, externals: Externals);
|
||||
type: string;
|
||||
externals: Externals;
|
||||
|
||||
/**
|
||||
* Apply the plugin
|
||||
*/
|
||||
apply(compiler: Compiler): void;
|
||||
}
|
||||
type ExternalsType =
|
||||
| "var"
|
||||
| "module"
|
||||
| "assign"
|
||||
| "this"
|
||||
| "window"
|
||||
| "self"
|
||||
| "global"
|
||||
| "commonjs"
|
||||
| "commonjs2"
|
||||
| "commonjs-module"
|
||||
| "amd"
|
||||
| "amd-require"
|
||||
| "umd"
|
||||
| "umd2"
|
||||
| "jsonp"
|
||||
| "system"
|
||||
| "promise"
|
||||
| "import";
|
||||
declare interface FactorizeModuleOptions {
|
||||
currentProfile: ModuleProfile;
|
||||
factory: ModuleFactory;
|
||||
|
|
@ -3748,7 +3765,7 @@ declare interface ModuleFederationPluginOptions {
|
|||
/**
|
||||
* The external type of the remote containers.
|
||||
*/
|
||||
remoteType?: LibraryType;
|
||||
remoteType?: ExternalsType;
|
||||
|
||||
/**
|
||||
* Container locations and request scopes from which modules should be resolved and loaded at runtime. When provided, property name is used as request scope, otherwise request scope is automatically inferred from container location.
|
||||
|
|
@ -4767,6 +4784,11 @@ declare interface Output {
|
|||
*/
|
||||
iife?: boolean;
|
||||
|
||||
/**
|
||||
* The name of the native import() function (can be exchanged for a polyfill).
|
||||
*/
|
||||
importFunctionName?: string;
|
||||
|
||||
/**
|
||||
* The JSONP function used by webpack for async loading of chunks.
|
||||
*/
|
||||
|
|
@ -4971,6 +4993,11 @@ declare interface OutputNormalized {
|
|||
*/
|
||||
iife?: boolean;
|
||||
|
||||
/**
|
||||
* The name of the native import() function (can be exchanged for a polyfill).
|
||||
*/
|
||||
importFunctionName?: string;
|
||||
|
||||
/**
|
||||
* The JSONP function used by webpack for async loading of chunks.
|
||||
*/
|
||||
|
|
@ -5875,7 +5902,7 @@ declare class RuntimeModule extends Module {
|
|||
getGeneratedCode(): string;
|
||||
}
|
||||
declare abstract class RuntimeTemplate {
|
||||
outputOptions: Output;
|
||||
outputOptions: OutputNormalized;
|
||||
requestShortener: RequestShortener;
|
||||
isIIFE(): boolean;
|
||||
supportsConst(): boolean;
|
||||
|
|
@ -5961,7 +5988,7 @@ declare abstract class RuntimeTemplate {
|
|||
/**
|
||||
* which kind of code should be returned
|
||||
*/
|
||||
type: "expression" | "promise" | "statements";
|
||||
type: "promise" | "expression" | "statements";
|
||||
}): string;
|
||||
moduleId(__0: {
|
||||
/**
|
||||
|
|
@ -6118,7 +6145,7 @@ declare abstract class RuntimeTemplate {
|
|||
* if set, will be filled with runtime requirements
|
||||
*/
|
||||
runtimeRequirements: Set<string>;
|
||||
}): string;
|
||||
}): [string, string];
|
||||
exportFromImport(__0: {
|
||||
/**
|
||||
* the module graph
|
||||
|
|
@ -7075,7 +7102,7 @@ declare interface WebpackOptionsNormalized {
|
|||
/**
|
||||
* Specifies the default type of externals ('amd*', 'umd*', 'system' and 'jsonp' depend on output.libraryTarget set to the same value).
|
||||
*/
|
||||
externalsType?: LibraryType;
|
||||
externalsType?: ExternalsType;
|
||||
|
||||
/**
|
||||
* Options for infrastructure level logging.
|
||||
|
|
|
|||
Loading…
Reference in New Issue