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

feat: add new external type "module-import" #18620

Merged
merged 7 commits into from
Aug 6, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions declarations/WebpackOptions.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 219,7 @@ export type ExternalsType =
| "system"
| "promise"
| "import"
| "module-import"
| "script"
| "node-commonjs";
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 27,7 @@ export type ExternalsType =
| "system"
| "promise"
| "import"
| "module-import"
| "script"
| "node-commonjs";
/**
Expand Down
1 change: 1 addition & 0 deletions declarations/plugins/container/ModuleFederationPlugin.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 84,7 @@ export type ExternalsType =
| "system"
| "promise"
| "import"
| "module-import"
| "script"
| "node-commonjs";
/**
Expand Down
147 changes: 90 additions & 57 deletions lib/ExternalModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 53,7 @@ const { register } = require("./util/serialization");
/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
/** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */

/** @typedef {{ attributes?: ImportAttributes }} ImportDependencyMeta */
/** @typedef {{ attributes?: ImportAttributes, externalType: "import" | "module" | undefined }} ImportDependencyMeta */
/** @typedef {{ layer?: string, supports?: string, media?: string }} CssImportDependencyMeta */

/** @typedef {ImportDependencyMeta | CssImportDependencyMeta} DependencyMeta */
Expand Down Expand Up @@ -164,7 164,10 @@ const getSourceForImportExternal = (
dependencyMeta
) => {
const importName = runtimeTemplate.outputOptions.importFunctionName;
if (!runtimeTemplate.supportsDynamicImport() && importName === "import") {
if (
!runtimeTemplate.supportsDynamicImport() &&
(importName === "import" || importName !== "module-import")
) {
throw new Error(
"The target environment doesn't support 'import()' so it's not possible to use external type 'import'"
);
Expand Down Expand Up @@ -575,25 578,6 @@ class ExternalModule extends Module {
canMangle = true;
}
break;
case "module":
if (this.buildInfo.module) {
if (!Array.isArray(request) || request.length === 1) {
this.buildMeta.exportsType = "namespace";
canMangle = true;
}
} else {
this.buildMeta.async = true;
EnvironmentNotSupportAsyncWarning.check(
this,
compilation.runtimeTemplate,
"external module"
);
if (!Array.isArray(request) || request.length === 1) {
this.buildMeta.exportsType = "namespace";
canMangle = false;
}
}
break;
case "script":
this.buildMeta.async = true;
EnvironmentNotSupportAsyncWarning.check(
Expand All @@ -610,18 863,52 @@ class ExternalModule extends Module {
"external promise"
);
break;
case "module":
case "import":
this.buildMeta.async = true;
EnvironmentNotSupportAsyncWarning.check(
this,
compilation.runtimeTemplate,
"external import"
);
if (!Array.isArray(request) || request.length === 1) {
this.buildMeta.exportsType = "namespace";
canMangle = false;
case "module-import": {
const type =
externalType === "module-import" &&
this.dependencyMeta &&
/** @type {ImportDependencyMeta} */ (this.dependencyMeta).externalType
? /** @type {ImportDependencyMeta} */ (this.dependencyMeta)
.externalType
: externalType;

if (type === "module") {
if (this.buildInfo.module) {
if (!Array.isArray(request) || request.length === 1) {
this.buildMeta.exportsType = "namespace";
canMangle = true;
}
} else {
this.buildMeta.async = true;
EnvironmentNotSupportAsyncWarning.check(
this,
compilation.runtimeTemplate,
"external module"
);
if (!Array.isArray(request) || request.length === 1) {
this.buildMeta.exportsType = "namespace";
canMangle = false;
}
}
}

if (type === "import") {
this.buildMeta.async = true;
EnvironmentNotSupportAsyncWarning.check(
this,
compilation.runtimeTemplate,
"external import"
);
if (!Array.isArray(request) || request.length === 1) {
this.buildMeta.exportsType = "namespace";
canMangle = false;
}
}

break;
}
}
this.addDependency(new StaticExportsDependency(true, canMangle));
callback();
Expand Down Expand Up @@ -718,43 736,58 @@ class ExternalModule extends Module {
runtimeTemplate
);
}
case "import":
return getSourceForImportExternal(
request,
runtimeTemplate,
/** @type {ImportDependencyMeta} */ (dependencyMeta)
);
case "script":
return getSourceForScriptExternal(request, runtimeTemplate);
case "module": {
if (!(/** @type {BuildInfo} */ (this.buildInfo).module)) {
if (!runtimeTemplate.supportsDynamicImport()) {
throw new Error(
`The target environment doesn't support dynamic import() syntax so it's not possible to use external type 'module' within a script${
runtimeTemplate.supportsEcmaScriptModuleSyntax()
? "\nDid you mean to build a EcmaScript Module ('output.module: true')?"
: ""
}`
);
}
case "module":
case "import":
case "module-import": {
const type =
externalType === "module-import" &&
dependencyMeta &&
/** @type {ImportDependencyMeta} */ (dependencyMeta).externalType
? /** @type {ImportDependencyMeta} */ (dependencyMeta).externalType
: externalType;

if (type === "import") {
return getSourceForImportExternal(
request,
runtimeTemplate,
/** @type {ImportDependencyMeta} */ (dependencyMeta)
);
}
if (!runtimeTemplate.supportsEcmaScriptModuleSyntax()) {
throw new Error(
"The target environment doesn't support EcmaScriptModule syntax so it's not possible to use external type 'module'"

if (type === "module") {
if (!(/** @type {BuildInfo} */ (this.buildInfo).module)) {
if (!runtimeTemplate.supportsDynamicImport()) {
throw new Error(
`The target environment doesn't support dynamic import() syntax so it's not possible to use external type 'module' within a script${
runtimeTemplate.supportsEcmaScriptModuleSyntax()
? "\nDid you mean to build a EcmaScript Module ('output.module: true')?"
: ""
}`
);
}
return getSourceForImportExternal(
request,
runtimeTemplate,
/** @type {ImportDependencyMeta} */ (dependencyMeta)
);
}
if (!runtimeTemplate.supportsEcmaScriptModuleSyntax()) {
throw new Error(
"The target environment doesn't support EcmaScriptModule syntax so it's not possible to use external type 'module'"
);
}
return getSourceForModuleExternal(
request,
moduleGraph.getExportsInfo(this),
runtime,
runtimeTemplate,
/** @type {ImportDependencyMeta} */ (dependencyMeta)
);
}
return getSourceForModuleExternal(
request,
moduleGraph.getExportsInfo(this),
runtime,
runtimeTemplate,
/** @type {ImportDependencyMeta} */ (dependencyMeta)
);

break;
}
case "var":
case "promise":
Expand Down
10 changes: 9 additions & 1 deletion lib/ExternalModuleFactoryPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 118,16 @@ class ExternalModuleFactoryPlugin {
dependency instanceof ImportDependency ||
dependency instanceof ContextElementDependency
) {
const externalType =
dependency instanceof HarmonyImportDependency
? "module"
: dependency instanceof ImportDependency
? "import"
: undefined;

dependencyMeta = {
attributes: dependency.assertions
attributes: dependency.assertions,
externalType
};
} else if (dependency instanceof CssImportDependency) {
dependencyMeta = {
Expand Down
5 changes: 4 additions & 1 deletion lib/WebpackOptionsApply.js
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 286,10 @@ class WebpackOptionsApply extends OptionsApply {
"library type \"modern-module\" is only allowed when 'experiments.outputModule' is enabled"
);
}
if (options.externalsType === "module") {
if (
options.externalsType === "module" ||
options.externalsType === "module-import"
) {
throw new Error(
"'externalsType: \"module\"' is only allowed when 'experiments.outputModule' is enabled"
);
Expand Down
2 changes: 1 addition & 1 deletion lib/config/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 275,7 @@ const applyWebpackOptionsDefaults = (options, compilerIndex) => {
validExternalTypes.includes(options.output.library.type)
? /** @type {ExternalsType} */ (options.output.library.type)
: options.output.module
? "module"
? "module-import"
: "var";
});

Expand Down
2 changes: 1 addition & 1 deletion schemas/WebpackOptions.check.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions schemas/WebpackOptions.json
Original file line number Diff line number Diff line change
Expand Up @@ -1285,6 1285,7 @@
"system",
"promise",
"import",
"module-import",
"script",
"node-commonjs"
]
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions schemas/plugins/container/ContainerReferencePlugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 22,7 @@
"system",
"promise",
"import",
"module-import",
"script",
"node-commonjs"
]
Expand Down
2 changes: 1 addition & 1 deletion schemas/plugins/container/ExternalsType.check.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 3,4 @@
* DO NOT MODIFY BY HAND.
* Run `yarn special-lint-fix` to update
*/
"use strict";function o(r,{instancePath:s="",parentData:m,parentDataProperty:t,rootData:e=r}={}){return"var"!==r&&"module"!==r&&"assign"!==r&&"this"!==r&&"window"!==r&&"self"!==r&&"global"!==r&&"commonjs"!==r&&"commonjs2"!==r&&"commonjs-module"!==r&&"commonjs-static"!==r&&"amd"!==r&&"amd-require"!==r&&"umd"!==r&&"umd2"!==r&&"jsonp"!==r&&"system"!==r&&"promise"!==r&&"import"!==r&&"script"!==r&&"node-commonjs"!==r?(o.errors=[{params:{}}],!1):(o.errors=null,!0)}module.exports=o,module.exports.default=o;
"use strict";function o(m,{instancePath:r="",parentData:s,parentDataProperty:t,rootData:e=m}={}){return"var"!==m&&"module"!==m&&"assign"!==m&&"this"!==m&&"window"!==m&&"self"!==m&&"global"!==m&&"commonjs"!==m&&"commonjs2"!==m&&"commonjs-module"!==m&&"commonjs-static"!==m&&"amd"!==m&&"amd-require"!==m&&"umd"!==m&&"umd2"!==m&&"jsonp"!==m&&"system"!==m&&"promise"!==m&&"import"!==m&&"module-import"!==m&&"script"!==m&&"node-commonjs"!==m?(o.errors=[{params:{}}],!1):(o.errors=null,!0)}module.exports=o,module.exports.default=o;
Loading
Loading