mirror of https://github.com/webpack/webpack.git
feat: add new external type "module-import" and use it by default for modules
This commit is contained in:
commit
740ec9e462
|
@ -219,6 +219,7 @@ export type ExternalsType =
|
|||
| "system"
|
||||
| "promise"
|
||||
| "import"
|
||||
| "module-import"
|
||||
| "script"
|
||||
| "node-commonjs";
|
||||
/**
|
||||
|
|
|
@ -27,6 +27,7 @@ export type ExternalsType =
|
|||
| "system"
|
||||
| "promise"
|
||||
| "import"
|
||||
| "module-import"
|
||||
| "script"
|
||||
| "node-commonjs";
|
||||
/**
|
||||
|
|
|
@ -84,6 +84,7 @@ export type ExternalsType =
|
|||
| "system"
|
||||
| "promise"
|
||||
| "import"
|
||||
| "module-import"
|
||||
| "script"
|
||||
| "node-commonjs";
|
||||
/**
|
||||
|
|
|
@ -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 */
|
||||
|
@ -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'"
|
||||
);
|
||||
|
@ -575,7 +578,34 @@ class ExternalModule extends Module {
|
|||
canMangle = true;
|
||||
}
|
||||
break;
|
||||
case "script":
|
||||
this.buildMeta.async = true;
|
||||
EnvironmentNotSupportAsyncWarning.check(
|
||||
this,
|
||||
compilation.runtimeTemplate,
|
||||
"external script"
|
||||
);
|
||||
break;
|
||||
case "promise":
|
||||
this.buildMeta.async = true;
|
||||
EnvironmentNotSupportAsyncWarning.check(
|
||||
this,
|
||||
compilation.runtimeTemplate,
|
||||
"external promise"
|
||||
);
|
||||
break;
|
||||
case "module":
|
||||
case "import":
|
||||
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";
|
||||
|
@ -593,24 +623,9 @@ class ExternalModule extends Module {
|
|||
canMangle = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "script":
|
||||
this.buildMeta.async = true;
|
||||
EnvironmentNotSupportAsyncWarning.check(
|
||||
this,
|
||||
compilation.runtimeTemplate,
|
||||
"external script"
|
||||
);
|
||||
break;
|
||||
case "promise":
|
||||
this.buildMeta.async = true;
|
||||
EnvironmentNotSupportAsyncWarning.check(
|
||||
this,
|
||||
compilation.runtimeTemplate,
|
||||
"external promise"
|
||||
);
|
||||
break;
|
||||
case "import":
|
||||
}
|
||||
|
||||
if (type === "import") {
|
||||
this.buildMeta.async = true;
|
||||
EnvironmentNotSupportAsyncWarning.check(
|
||||
this,
|
||||
|
@ -621,8 +636,11 @@ class ExternalModule extends Module {
|
|||
this.buildMeta.exportsType = "namespace";
|
||||
canMangle = false;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.addDependency(new StaticExportsDependency(true, canMangle));
|
||||
callback();
|
||||
}
|
||||
|
@ -718,15 +736,27 @@ class ExternalModule extends Module {
|
|||
runtimeTemplate
|
||||
);
|
||||
}
|
||||
case "script":
|
||||
return getSourceForScriptExternal(request, runtimeTemplate);
|
||||
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)
|
||||
);
|
||||
case "script":
|
||||
return getSourceForScriptExternal(request, runtimeTemplate);
|
||||
case "module": {
|
||||
}
|
||||
|
||||
if (type === "module") {
|
||||
if (!(/** @type {BuildInfo} */ (this.buildInfo).module)) {
|
||||
if (!runtimeTemplate.supportsDynamicImport()) {
|
||||
throw new Error(
|
||||
|
@ -756,6 +786,9 @@ class ExternalModule extends Module {
|
|||
/** @type {ImportDependencyMeta} */ (dependencyMeta)
|
||||
);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case "var":
|
||||
case "promise":
|
||||
case "const":
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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"
|
||||
);
|
||||
|
|
|
@ -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";
|
||||
});
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1285,6 +1285,7 @@
|
|||
"system",
|
||||
"promise",
|
||||
"import",
|
||||
"module-import",
|
||||
"script",
|
||||
"node-commonjs"
|
||||
]
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -22,6 +22,7 @@
|
|||
"system",
|
||||
"promise",
|
||||
"import",
|
||||
"module-import",
|
||||
"script",
|
||||
"node-commonjs"
|
||||
]
|
||||
|
|
|
@ -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;
|
File diff suppressed because one or more lines are too long
|
@ -126,6 +126,7 @@
|
|||
"system",
|
||||
"promise",
|
||||
"import",
|
||||
"module-import",
|
||||
"script",
|
||||
"node-commonjs"
|
||||
]
|
||||
|
|
|
@ -920,7 +920,7 @@ describe("snapshots", () => {
|
|||
+ "outputModule": true,
|
||||
@@ ... @@
|
||||
- "externalsType": "var",
|
||||
+ "externalsType": "module",
|
||||
+ "externalsType": "module-import",
|
||||
@@ ... @@
|
||||
- "dynamicImport": undefined,
|
||||
- "dynamicImportInWorker": undefined,
|
||||
|
|
|
@ -1030,6 +1030,7 @@ Object {
|
|||
"system",
|
||||
"promise",
|
||||
"import",
|
||||
"module-import",
|
||||
"script",
|
||||
"node-commonjs",
|
||||
],
|
||||
|
|
|
@ -2,6 +2,7 @@ import value from "promise-external";
|
|||
import value2 from "module-promise-external";
|
||||
import value3 from "object-promise-external";
|
||||
import request from "import-external";
|
||||
import request2 from "module-import-external";
|
||||
import "./module.mjs";
|
||||
|
||||
it("should allow async externals", () => {
|
||||
|
@ -9,6 +10,7 @@ it("should allow async externals", () => {
|
|||
expect(value2).toBe(42);
|
||||
expect(value3).toEqual({ default: 42, named: true });
|
||||
expect(request).toBe("/hello/world.js");
|
||||
expect(request2).toBe("/hello/world.js");
|
||||
});
|
||||
|
||||
it("should allow to catch errors of async externals", () => {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
module.exports = {
|
||||
target: ["web", "es2020"],
|
||||
output: {
|
||||
libraryTarget: "commonjs-module",
|
||||
importFunctionName: "((name) => Promise.resolve({ request: name }))"
|
||||
|
@ -12,6 +13,7 @@ module.exports = {
|
|||
"promise new Promise(resolve => setTimeout(() => resolve({ default: 42, named: true }), 100))",
|
||||
"failing-promise-external":
|
||||
"promise new Promise((resolve, reject) => setTimeout(() => reject(new Error('external reject')), 100))",
|
||||
"import-external": ["import /hello/world.js", "request"]
|
||||
"import-external": ["import /hello/world.js", "request"],
|
||||
"module-import-external": ["module-import /hello/world.js", "request"]
|
||||
}
|
||||
};
|
||||
|
|
|
@ -4,9 +4,12 @@ import fsPromises1 from "fs-promises";
|
|||
import fsPromises2 from "module-fs-promises";
|
||||
import path1 from "path";
|
||||
import path2 from "module-path";
|
||||
import url1 from "url";
|
||||
import url2 from "module-import-url";
|
||||
|
||||
it("should be possible to import multiple module externals", () => {
|
||||
expect(fs2).toBe(fs1);
|
||||
expect(path2).toBe(path1);
|
||||
expect(fsPromises2).toBe(fsPromises1);
|
||||
expect(url1).toBe(url2);
|
||||
});
|
||||
|
|
|
@ -8,7 +8,9 @@ const config = o => ({
|
|||
? ["node-commonjs fs", "promises"]
|
||||
: "node-commonjs fs/promises",
|
||||
"module-path": "module path",
|
||||
path: "node-commonjs path"
|
||||
path: "node-commonjs path",
|
||||
"module-import-url": "module-import url",
|
||||
url: "node-commonjs url"
|
||||
},
|
||||
optimization: {
|
||||
concatenateModules: true,
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import * as staticPkg from "./static-package.json" assert { type: "json" };
|
||||
import * as staticPkgStr from "./static-package-str.json" assert { "type": "json" };
|
||||
import * as staticPkgModuleImport from "./static-package-module-import.json" assert { type: "json" };
|
||||
|
||||
it("should allow async externals", async () => {
|
||||
expect(staticPkg.default.foo).toBe("static");
|
||||
expect(staticPkgStr.default.foo).toBe("static-str");
|
||||
expect(staticPkgModuleImport.default.foo).toBe("static");
|
||||
|
||||
const dynamicPkg = await import("./dynamic-package.json", {
|
||||
assert: { type: "json" }
|
||||
|
@ -42,6 +44,12 @@ it("should allow async externals", async () => {
|
|||
const reExportPkg = await import("./re-export.js");
|
||||
|
||||
expect(reExportPkg.foo).toBe("re-export");
|
||||
|
||||
const dynamicPkgModuleImport = await import("./dynamic-package-module-import.json", {
|
||||
assert: { type: "json" }
|
||||
})
|
||||
|
||||
expect(dynamicPkgModuleImport.default.foo).toBe("dynamic");
|
||||
});
|
||||
|
||||
export * from "./re-export-directly.json" assert { type: "json" }
|
||||
|
|
|
@ -60,6 +60,10 @@ module.exports = {
|
|||
"./pkg.json": "import ./pkg.json",
|
||||
"./pkg": "import ./pkg",
|
||||
"./re-export.json": "module ./re-export.json",
|
||||
"./re-export-directly.json": "module ./re-export-directly.json"
|
||||
"./re-export-directly.json": "module ./re-export-directly.json",
|
||||
"./static-package-module-import.json":
|
||||
"module-import ./static-package.json",
|
||||
"./dynamic-package-module-import.json":
|
||||
"module-import ./dynamic-package.json"
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import * as staticPkg from "./static-package.json" with { type: "json" };
|
||||
import * as staticPkgStr from "./static-package-str.json" with { "type": "json" };
|
||||
import * as staticPkgModuleImport from "./static-package-module-import.json" with { "type": "json" };
|
||||
|
||||
it("should allow async externals", async () => {
|
||||
expect(staticPkg.default.foo).toBe("static");
|
||||
expect(staticPkgStr.default.foo).toBe("static-str");
|
||||
expect(staticPkgModuleImport.default.foo).toBe("static");
|
||||
|
||||
const dynamicPkg = await import("./dynamic-package.json", {
|
||||
with: { type: "json" }
|
||||
|
@ -42,6 +44,12 @@ it("should allow async externals", async () => {
|
|||
const reExportPkg = await import("./re-export.js");
|
||||
|
||||
expect(reExportPkg.foo).toBe("re-export");
|
||||
|
||||
const dynamicPkgModuleImport = await import("./dynamic-package-module-import.json", {
|
||||
with: { type: "json" }
|
||||
})
|
||||
|
||||
expect(dynamicPkgModuleImport.default.foo).toBe("dynamic");
|
||||
});
|
||||
|
||||
export * from "./re-export-directly.json" with { type: "json" }
|
||||
|
|
|
@ -60,6 +60,10 @@ module.exports = {
|
|||
"./pkg.json": "import ./pkg.json",
|
||||
"./pkg": "import ./pkg",
|
||||
"./re-export.json": "module ./re-export.json",
|
||||
"./re-export-directly.json": "module ./re-export-directly.json"
|
||||
"./re-export-directly.json": "module ./re-export-directly.json",
|
||||
"./static-package-module-import.json":
|
||||
"module-import ./static-package.json",
|
||||
"./dynamic-package-module-import.json":
|
||||
"module-import ./dynamic-package.json"
|
||||
}
|
||||
};
|
||||
|
|
|
@ -2515,6 +2515,7 @@ declare interface Configuration {
|
|||
| "jsonp"
|
||||
| "system"
|
||||
| "promise"
|
||||
| "module-import"
|
||||
| "script"
|
||||
| "node-commonjs";
|
||||
|
||||
|
@ -4631,6 +4632,7 @@ type ExternalsType =
|
|||
| "jsonp"
|
||||
| "system"
|
||||
| "promise"
|
||||
| "module-import"
|
||||
| "script"
|
||||
| "node-commonjs";
|
||||
declare interface FSImplementation {
|
||||
|
@ -5347,6 +5349,7 @@ type IgnorePluginOptions =
|
|||
type ImportAttributes = Record<string, string> & {};
|
||||
declare interface ImportDependencyMeta {
|
||||
attributes?: ImportAttributes;
|
||||
externalType?: "import" | "module";
|
||||
}
|
||||
declare interface ImportModuleOptions {
|
||||
/**
|
||||
|
@ -8257,6 +8260,7 @@ declare interface ModuleFederationPluginOptions {
|
|||
| "jsonp"
|
||||
| "system"
|
||||
| "promise"
|
||||
| "module-import"
|
||||
| "script"
|
||||
| "node-commonjs";
|
||||
|
||||
|
@ -14674,6 +14678,7 @@ declare interface WebpackOptionsNormalized {
|
|||
| "jsonp"
|
||||
| "system"
|
||||
| "promise"
|
||||
| "module-import"
|
||||
| "script"
|
||||
| "node-commonjs";
|
||||
|
||||
|
|
Loading…
Reference in New Issue