mirror of https://github.com/webpack/webpack.git
fix: support `__non_webpack_require__` for ES modules
This commit is contained in:
parent
df204b5f71
commit
930785fb00
|
@ -5,7 +5,9 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const InitFragment = require("./InitFragment");
|
||||
const {
|
||||
getExternalModuleNodeCommonjsInitFragment
|
||||
} = require("./ExternalModule");
|
||||
const {
|
||||
JAVASCRIPT_MODULE_TYPE_AUTO,
|
||||
JAVASCRIPT_MODULE_TYPE_DYNAMIC,
|
||||
|
@ -128,8 +130,6 @@ function getReplacements() {
|
|||
|
||||
const PLUGIN_NAME = "APIPlugin";
|
||||
|
||||
const moduleCreateRequire = "__WEBPACK_EXTERNAL_createRequire";
|
||||
|
||||
class APIPlugin {
|
||||
/**
|
||||
* Apply the plugin
|
||||
|
@ -140,14 +140,14 @@ class APIPlugin {
|
|||
compiler.hooks.compilation.tap(
|
||||
PLUGIN_NAME,
|
||||
(compilation, { normalModuleFactory }) => {
|
||||
const importMetaName = compilation.outputOptions.importMetaName;
|
||||
const moduleOutput = compilation.options.output.module;
|
||||
const nodeTarget = compiler.platform.node;
|
||||
const nodeEsm = moduleOutput && nodeTarget;
|
||||
|
||||
const REPLACEMENTS = getReplacements();
|
||||
if (nodeEsm) {
|
||||
REPLACEMENTS.__non_webpack_require__.expr = `${moduleCreateRequire}(${importMetaName}.url)`;
|
||||
REPLACEMENTS.__non_webpack_require__.expr =
|
||||
"__WEBPACK_EXTERNAL_createRequire_require";
|
||||
}
|
||||
|
||||
compilation.dependencyTemplates.set(
|
||||
|
@ -179,13 +179,8 @@ class APIPlugin {
|
|||
(source, module, renderContext) => {
|
||||
if (/** @type {BuildInfo} */ (module.buildInfo).needCreateRequire) {
|
||||
const chunkInitFragments = [
|
||||
new InitFragment(
|
||||
`import { createRequire as ${moduleCreateRequire} } from ${renderContext.runtimeTemplate.renderNodePrefixForCoreModule(
|
||||
"module"
|
||||
)};\n`,
|
||||
InitFragment.STAGE_HARMONY_IMPORTS,
|
||||
0,
|
||||
"external module node-commonjs"
|
||||
getExternalModuleNodeCommonjsInitFragment(
|
||||
renderContext.runtimeTemplate
|
||||
)
|
||||
];
|
||||
|
||||
|
|
|
@ -128,6 +128,23 @@ const getSourceForCommonJsExternal = (moduleAndSpecifiers) => {
|
|||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {RuntimeTemplate} runtimeTemplate the runtime template
|
||||
* @returns {InitFragment<ChunkRenderContext>} code
|
||||
*/
|
||||
const getExternalModuleNodeCommonjsInitFragment = (runtimeTemplate) => {
|
||||
const importMetaName = runtimeTemplate.outputOptions.importMetaName;
|
||||
|
||||
return new InitFragment(
|
||||
`import { createRequire as __WEBPACK_EXTERNAL_createRequire } from ${runtimeTemplate.renderNodePrefixForCoreModule(
|
||||
"module"
|
||||
)};\n${runtimeTemplate.renderConst()} __WEBPACK_EXTERNAL_createRequire_require = __WEBPACK_EXTERNAL_createRequire(${importMetaName}.url);\n`,
|
||||
InitFragment.STAGE_HARMONY_IMPORTS,
|
||||
0,
|
||||
"external module node-commonjs"
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string | string[]} moduleAndSpecifiers the module request
|
||||
* @param {RuntimeTemplate} runtimeTemplate the runtime template
|
||||
|
@ -137,19 +154,13 @@ const getSourceForCommonJsExternalInNodeModule = (
|
|||
moduleAndSpecifiers,
|
||||
runtimeTemplate
|
||||
) => {
|
||||
const importMetaName = runtimeTemplate.outputOptions.importMetaName;
|
||||
const chunkInitFragments = [
|
||||
new InitFragment(
|
||||
`import { createRequire as __WEBPACK_EXTERNAL_createRequire } from ${runtimeTemplate.renderNodePrefixForCoreModule("module")};\n`,
|
||||
InitFragment.STAGE_HARMONY_IMPORTS,
|
||||
0,
|
||||
"external module node-commonjs"
|
||||
)
|
||||
getExternalModuleNodeCommonjsInitFragment(runtimeTemplate)
|
||||
];
|
||||
if (!Array.isArray(moduleAndSpecifiers)) {
|
||||
return {
|
||||
chunkInitFragments,
|
||||
expression: `__WEBPACK_EXTERNAL_createRequire(${importMetaName}.url)(${JSON.stringify(
|
||||
expression: `__WEBPACK_EXTERNAL_createRequire_require(${JSON.stringify(
|
||||
moduleAndSpecifiers
|
||||
)})`
|
||||
};
|
||||
|
@ -157,7 +168,7 @@ const getSourceForCommonJsExternalInNodeModule = (
|
|||
const moduleName = moduleAndSpecifiers[0];
|
||||
return {
|
||||
chunkInitFragments,
|
||||
expression: `__WEBPACK_EXTERNAL_createRequire(${importMetaName}.url)(${JSON.stringify(
|
||||
expression: `__WEBPACK_EXTERNAL_createRequire_require(${JSON.stringify(
|
||||
moduleName
|
||||
)})${propertyAccess(moduleAndSpecifiers, 1)}`
|
||||
};
|
||||
|
@ -1039,9 +1050,7 @@ class ExternalModule extends Module {
|
|||
scope.registerRawExport(specifier, finalName);
|
||||
}
|
||||
} else if (concatenationScope) {
|
||||
sourceString = `${
|
||||
runtimeTemplate.supportsConst() ? "const" : "var"
|
||||
} ${ConcatenationScope.NAMESPACE_OBJECT_EXPORT} = ${sourceString};`;
|
||||
sourceString = `${runtimeTemplate.renderConst()} ${ConcatenationScope.NAMESPACE_OBJECT_EXPORT} = ${sourceString};`;
|
||||
concatenationScope.registerNamespaceExport(
|
||||
ConcatenationScope.NAMESPACE_OBJECT_EXPORT
|
||||
);
|
||||
|
@ -1145,3 +1154,5 @@ makeSerializable(ExternalModule, "webpack/lib/ExternalModule");
|
|||
|
||||
module.exports = ExternalModule;
|
||||
module.exports.ModuleExternalInitFragment = ModuleExternalInitFragment;
|
||||
module.exports.getExternalModuleNodeCommonjsInitFragment =
|
||||
getExternalModuleNodeCommonjsInitFragment;
|
||||
|
|
|
@ -168,6 +168,13 @@ class RuntimeTemplate {
|
|||
: `"${mod}"`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {"const" | "var"} return `const` when it is supported, otherwise `var`
|
||||
*/
|
||||
renderConst() {
|
||||
return this.supportsConst() ? "const" : "var";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} returnValue return value
|
||||
* @param {string} args arguments
|
||||
|
|
|
@ -612,7 +612,7 @@ class AssetGenerator extends Generator {
|
|||
);
|
||||
|
||||
return new RawSource(
|
||||
`${runtimeTemplate.supportsConst() ? "const" : "var"} ${
|
||||
`${runtimeTemplate.renderConst()} ${
|
||||
ConcatenationScope.NAMESPACE_OBJECT_EXPORT
|
||||
} = ${content};`
|
||||
);
|
||||
|
|
|
@ -60,7 +60,7 @@ class AssetSourceGenerator extends Generator {
|
|||
concatenationScope.registerNamespaceExport(
|
||||
ConcatenationScope.NAMESPACE_OBJECT_EXPORT
|
||||
);
|
||||
sourceContent = `${runtimeTemplate.supportsConst() ? "const" : "var"} ${
|
||||
sourceContent = `${runtimeTemplate.renderConst()} ${
|
||||
ConcatenationScope.NAMESPACE_OBJECT_EXPORT
|
||||
} = ${JSON.stringify(encodedSource)};`;
|
||||
} else {
|
||||
|
|
|
@ -171,11 +171,7 @@ class CssGenerator extends Generator {
|
|||
usedIdentifiers.add(identifier);
|
||||
generateContext.concatenationScope.registerExport(name, identifier);
|
||||
source.add(
|
||||
`${
|
||||
generateContext.runtimeTemplate.supportsConst()
|
||||
? "const"
|
||||
: "var"
|
||||
} ${identifier} = ${JSON.stringify(v)};\n`
|
||||
`${generateContext.runtimeTemplate.renderConst()} ${identifier} = ${JSON.stringify(v)};\n`
|
||||
);
|
||||
}
|
||||
return source;
|
||||
|
|
|
@ -1234,14 +1234,9 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
|
|||
mode.hidden
|
||||
)
|
||||
: /** @type {ExportModeIgnored} */ (mode.ignored);
|
||||
const modern =
|
||||
runtimeTemplate.supportsConst() &&
|
||||
runtimeTemplate.supportsArrowFunction();
|
||||
let content =
|
||||
"/* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {};\n" +
|
||||
`/* harmony reexport (unknown) */ for(${
|
||||
modern ? "const" : "var"
|
||||
} __WEBPACK_IMPORT_KEY__ in ${importVar}) `;
|
||||
`/* harmony reexport (unknown) */ for(${runtimeTemplate.renderConst()} __WEBPACK_IMPORT_KEY__ in ${importVar}) `;
|
||||
|
||||
// Filter out exports which are defined by other exports
|
||||
// and filter out default export because it cannot be reexported with *
|
||||
|
@ -1256,7 +1251,7 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
|
|||
}
|
||||
|
||||
content += "__WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = ";
|
||||
content += modern
|
||||
content += runtimeTemplate.supportsArrowFunction()
|
||||
? `() => ${importVar}[__WEBPACK_IMPORT_KEY__]`
|
||||
: `function(key) { return ${importVar}[key]; }.bind(0, __WEBPACK_IMPORT_KEY__)`;
|
||||
|
||||
|
|
|
@ -206,7 +206,7 @@ class JsonGenerator extends Generator {
|
|||
/** @type {string} */
|
||||
let content;
|
||||
if (concatenationScope) {
|
||||
content = `${runtimeTemplate.supportsConst() ? "const" : "var"} ${
|
||||
content = `${runtimeTemplate.renderConst()} ${
|
||||
ConcatenationScope.NAMESPACE_OBJECT_EXPORT
|
||||
} = ${jsonExpr};`;
|
||||
concatenationScope.registerNamespaceExport(
|
||||
|
|
|
@ -144,7 +144,14 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
|
|||
renderStartup(
|
||||
source,
|
||||
module,
|
||||
{ moduleGraph, chunk, codeGenerationResults, inlined, inlinedInIIFE },
|
||||
{
|
||||
moduleGraph,
|
||||
chunk,
|
||||
codeGenerationResults,
|
||||
inlined,
|
||||
inlinedInIIFE,
|
||||
runtimeTemplate
|
||||
},
|
||||
{ options, compilation }
|
||||
) {
|
||||
const result = new ConcatSource(source);
|
||||
|
@ -177,10 +184,6 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
|
|||
);
|
||||
}
|
||||
|
||||
const varType = compilation.outputOptions.environment.const
|
||||
? "const"
|
||||
: "var";
|
||||
|
||||
outer: for (const exportInfo of exportsInfo) {
|
||||
if (!exportInfo.provided) continue;
|
||||
|
||||
|
@ -217,9 +220,9 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
|
|||
} else {
|
||||
finalName = `${RuntimeGlobals.exports}${Template.toIdentifier(originalName)}`;
|
||||
result.add(
|
||||
`${varType} ${finalName} = ${RuntimeGlobals.exports}${propertyAccess([
|
||||
usedName
|
||||
])};\n`
|
||||
`${runtimeTemplate.renderConst()} ${finalName} = ${RuntimeGlobals.exports}${propertyAccess(
|
||||
[usedName]
|
||||
)};\n`
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -237,7 +240,9 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
|
|||
|
||||
if (topLevelDeclarations && topLevelDeclarations.has(originalName)) {
|
||||
const name = `${RuntimeGlobals.exports}${Template.toIdentifier(originalName)}`;
|
||||
result.add(`${varType} ${name} = ${finalName};\n`);
|
||||
result.add(
|
||||
`${runtimeTemplate.renderConst()} ${name} = ${finalName};\n`
|
||||
);
|
||||
shortHandedExports.push(`${name} as ${originalName}`);
|
||||
} else {
|
||||
exports.push([originalName, finalName]);
|
||||
|
@ -263,7 +268,9 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
|
|||
}
|
||||
|
||||
for (const [exportName, final] of exports) {
|
||||
result.add(`export ${varType} ${exportName} = ${final};\n`);
|
||||
result.add(
|
||||
`export ${runtimeTemplate.renderConst()} ${exportName} = ${final};\n`
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
@ -3,9 +3,10 @@ const path = require("path");
|
|||
|
||||
it("module-import should correctly get fallback type", function() {
|
||||
const content = fs.readFileSync(path.resolve(__dirname, "a.js"), "utf-8");
|
||||
expect(content).toContain(`import { default as __WEBPACK_EXTERNAL_MODULE_external0_default__ } from "external0"`); // module
|
||||
expect(content).toContain(`import { default as __WEBPACK_EXTERNAL_MODULE_external0_default__ } from "external0";`); // module
|
||||
expect(content).toContain(`const __WEBPACK_EXTERNAL_createRequire_require = __WEBPACK_EXTERNAL_createRequire(import.meta.url);`); // module
|
||||
expect(content).toContain(`import * as __WEBPACK_EXTERNAL_MODULE_external1__ from "external1"`); // module
|
||||
expect(content).toContain(`module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("external2")`); // node-commonjs
|
||||
expect(content).toContain(`module.exports = __WEBPACK_EXTERNAL_createRequire_require("external2")`); // node-commonjs
|
||||
expect(content).toContain(`import * as __WEBPACK_EXTERNAL_MODULE_external3__ from "external3"`); // module
|
||||
expect(content).toContain(`const external3_2 = Promise.resolve(/*! import() */).then`); // import
|
||||
});
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
const pathModule = __non_webpack_require__('path');
|
||||
|
||||
export default pathModule;
|
|
@ -0,0 +1,5 @@
|
|||
import pathModule from "./common.js";
|
||||
|
||||
it("should work", () => {
|
||||
expect(typeof pathModule.dirname).toBe("function");
|
||||
});
|
|
@ -0,0 +1,5 @@
|
|||
"use strict";
|
||||
|
||||
const supportsRequireInModule = require("../../../helpers/supportsRequireInModule");
|
||||
|
||||
module.exports = () => supportsRequireInModule();
|
|
@ -0,0 +1,10 @@
|
|||
"use strict";
|
||||
|
||||
/** @type {import("../../../../").Configuration} */
|
||||
module.exports = {
|
||||
devtool: "eval-source-map",
|
||||
target: "node",
|
||||
experiments: {
|
||||
outputModule: true
|
||||
}
|
||||
};
|
|
@ -5356,6 +5356,9 @@ declare class ExternalModule extends Module {
|
|||
normalModuleFactory: NormalModuleFactory
|
||||
): void;
|
||||
static ModuleExternalInitFragment: typeof ModuleExternalInitFragment;
|
||||
static getExternalModuleNodeCommonjsInitFragment: (
|
||||
runtimeTemplate: RuntimeTemplate
|
||||
) => InitFragment<ChunkRenderContextJavascriptModulesPlugin>;
|
||||
}
|
||||
declare interface ExternalModuleInfo {
|
||||
type: "external";
|
||||
|
@ -15545,6 +15548,7 @@ declare abstract class RuntimeTemplate {
|
|||
supportTemplateLiteral(): boolean;
|
||||
supportNodePrefixForCoreModules(): boolean;
|
||||
renderNodePrefixForCoreModule(mod: string): string;
|
||||
renderConst(): "var" | "const";
|
||||
returningFunction(returnValue: string, args?: string): string;
|
||||
basicFunction(args: string, body: string | string[]): string;
|
||||
concatenation(...args: (string | { expr: string })[]): string;
|
||||
|
|
Loading…
Reference in New Issue