mirror of https://github.com/webpack/webpack.git
fix: `needCreateRequire` should be set to true only when module output and node target (#19761)
This commit is contained in:
parent
08599420db
commit
076863133b
|
@ -30,11 +30,9 @@ const GetFullHashRuntimeModule = require("./runtime/GetFullHashRuntimeModule");
|
|||
/** @typedef {import("./javascript/JavascriptParser").Range} Range */
|
||||
|
||||
/**
|
||||
* @param {boolean | undefined} module true if ES module
|
||||
* @param {string} importMetaName `import.meta` name
|
||||
* @returns {Record<string, {expr: string, req: string[] | null, type?: string, assign: boolean}>} replacements
|
||||
*/
|
||||
function getReplacements(module, importMetaName) {
|
||||
function getReplacements() {
|
||||
return {
|
||||
__webpack_require__: {
|
||||
expr: RuntimeGlobals.require,
|
||||
|
@ -67,9 +65,7 @@ function getReplacements(module, importMetaName) {
|
|||
assign: true
|
||||
},
|
||||
__non_webpack_require__: {
|
||||
expr: module
|
||||
? `__WEBPACK_EXTERNAL_createRequire(${importMetaName}.url)`
|
||||
: "require",
|
||||
expr: "require",
|
||||
req: null,
|
||||
type: undefined, // type is not known, depends on environment
|
||||
assign: true
|
||||
|
@ -132,19 +128,9 @@ function getReplacements(module, importMetaName) {
|
|||
|
||||
const PLUGIN_NAME = "APIPlugin";
|
||||
|
||||
/**
|
||||
* @typedef {object} APIPluginOptions
|
||||
* @property {boolean=} module the output filename
|
||||
*/
|
||||
const moduleCreateRequire = "__WEBPACK_EXTERNAL_createRequire";
|
||||
|
||||
class APIPlugin {
|
||||
/**
|
||||
* @param {APIPluginOptions=} options options
|
||||
*/
|
||||
constructor(options = {}) {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the plugin
|
||||
* @param {Compiler} compiler the compiler instance
|
||||
|
@ -155,10 +141,14 @@ class APIPlugin {
|
|||
PLUGIN_NAME,
|
||||
(compilation, { normalModuleFactory }) => {
|
||||
const importMetaName = compilation.outputOptions.importMetaName;
|
||||
const REPLACEMENTS = getReplacements(
|
||||
this.options.module,
|
||||
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)`;
|
||||
}
|
||||
|
||||
compilation.dependencyTemplates.set(
|
||||
ConstDependency,
|
||||
|
@ -190,7 +180,7 @@ class APIPlugin {
|
|||
if (/** @type {BuildInfo} */ (module.buildInfo).needCreateRequire) {
|
||||
const chunkInitFragments = [
|
||||
new InitFragment(
|
||||
`import { createRequire as __WEBPACK_EXTERNAL_createRequire } from ${renderContext.runtimeTemplate.renderNodePrefixForCoreModule(
|
||||
`import { createRequire as ${moduleCreateRequire} } from ${renderContext.runtimeTemplate.renderNodePrefixForCoreModule(
|
||||
"module"
|
||||
)};\n`,
|
||||
InitFragment.STAGE_HARMONY_IMPORTS,
|
||||
|
@ -215,9 +205,20 @@ class APIPlugin {
|
|||
parser.hooks.expression.for(key).tap(PLUGIN_NAME, (expression) => {
|
||||
const dep = toConstantDependency(parser, info.expr, info.req);
|
||||
|
||||
if (key === "__non_webpack_require__" && this.options.module) {
|
||||
/** @type {BuildInfo} */
|
||||
(parser.state.module.buildInfo).needCreateRequire = true;
|
||||
if (key === "__non_webpack_require__" && moduleOutput) {
|
||||
if (nodeTarget) {
|
||||
/** @type {BuildInfo} */
|
||||
(parser.state.module.buildInfo).needCreateRequire = true;
|
||||
} else {
|
||||
const warning = new WebpackError(
|
||||
`${PLUGIN_NAME}\n__non_webpack_require__ is only allowed in target node`
|
||||
);
|
||||
warning.loc = /** @type {DependencyLocation} */ (
|
||||
expression.loc
|
||||
);
|
||||
warning.module = parser.state.module;
|
||||
compilation.warnings.push(warning);
|
||||
}
|
||||
}
|
||||
|
||||
return dep(expression);
|
||||
|
|
|
@ -473,9 +473,7 @@ class WebpackOptionsApply extends OptionsApply {
|
|||
|
||||
new NodeStuffPlugin(options.node).apply(compiler);
|
||||
}
|
||||
new APIPlugin({
|
||||
module: options.output.module
|
||||
}).apply(compiler);
|
||||
new APIPlugin().apply(compiler);
|
||||
new ExportsInfoApiPlugin().apply(compiler);
|
||||
new WebpackIsIncludedPlugin().apply(compiler);
|
||||
new ConstPlugin().apply(compiler);
|
||||
|
|
|
@ -884,7 +884,7 @@ class ConcatenatedModule extends Module {
|
|||
}
|
||||
}
|
||||
|
||||
const { assets, assetsInfo, topLevelDeclarations } =
|
||||
const { assets, assetsInfo, topLevelDeclarations, needCreateRequire } =
|
||||
/** @type {BuildInfo} */ (m.buildInfo);
|
||||
|
||||
const buildInfo = /** @type {BuildInfo} */ (this.buildInfo);
|
||||
|
@ -901,6 +901,11 @@ class ConcatenatedModule extends Module {
|
|||
buildInfo.topLevelDeclarations = undefined;
|
||||
}
|
||||
|
||||
// populate needCreateRequire
|
||||
if (needCreateRequire) {
|
||||
this.buildInfo.needCreateRequire = true;
|
||||
}
|
||||
|
||||
// populate assets
|
||||
if (assets) {
|
||||
if (buildInfo.assets === undefined) {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
export default __non_webpack_require__("./bar");
|
|
@ -0,0 +1,5 @@
|
|||
import foo from "./foo";
|
||||
|
||||
it("should generate createRequire in concatenated modules", function () {
|
||||
expect(foo).toBe(1);
|
||||
});
|
|
@ -0,0 +1,5 @@
|
|||
"use strict";
|
||||
|
||||
const supportsRequireInModule = require("../../../helpers/supportsRequireInModule");
|
||||
|
||||
module.exports = () => supportsRequireInModule();
|
|
@ -0,0 +1,16 @@
|
|||
"use strict";
|
||||
|
||||
const inCacheTest = (options) => {
|
||||
if (Array.isArray(options)) {
|
||||
return options.some((o) => o.cache);
|
||||
}
|
||||
return options.cache;
|
||||
};
|
||||
|
||||
module.exports = (options) => {
|
||||
if (inCacheTest(options)) {
|
||||
// We will pre-compile twice, and the module cache will result in no warnings in the stats during the third compilation
|
||||
return [];
|
||||
}
|
||||
return [[/__non_webpack_require__ is only allowed in target node/]];
|
||||
};
|
|
@ -0,0 +1,53 @@
|
|||
"use strict";
|
||||
|
||||
const webpack = require("../../../../");
|
||||
|
||||
/** @type {import("../../../../").Configuration[]} */
|
||||
module.exports = [
|
||||
{
|
||||
output: {
|
||||
module: true
|
||||
},
|
||||
target: ["node"],
|
||||
experiments: {
|
||||
outputModule: true
|
||||
},
|
||||
plugins: [
|
||||
{
|
||||
apply(compiler) {
|
||||
compiler.hooks.compilation.tap("Test", (compilation) => {
|
||||
compilation.hooks.processAssets.tap(
|
||||
{
|
||||
name: "copy-webpack-plugin",
|
||||
stage:
|
||||
compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL
|
||||
},
|
||||
() => {
|
||||
compilation.emitAsset(
|
||||
"bar.js",
|
||||
new webpack.sources.RawSource("module.exports = 1;")
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
output: {
|
||||
module: true
|
||||
},
|
||||
target: "web",
|
||||
experiments: {
|
||||
outputModule: true
|
||||
},
|
||||
plugins: [
|
||||
new webpack.BannerPlugin({
|
||||
raw: true,
|
||||
banner:
|
||||
'import { createRequire } from "module"; const require = createRequire(import.meta.url)'
|
||||
})
|
||||
]
|
||||
}
|
||||
];
|
Loading…
Reference in New Issue