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 */
|
/** @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
|
* @returns {Record<string, {expr: string, req: string[] | null, type?: string, assign: boolean}>} replacements
|
||||||
*/
|
*/
|
||||||
function getReplacements(module, importMetaName) {
|
function getReplacements() {
|
||||||
return {
|
return {
|
||||||
__webpack_require__: {
|
__webpack_require__: {
|
||||||
expr: RuntimeGlobals.require,
|
expr: RuntimeGlobals.require,
|
||||||
|
@ -67,9 +65,7 @@ function getReplacements(module, importMetaName) {
|
||||||
assign: true
|
assign: true
|
||||||
},
|
},
|
||||||
__non_webpack_require__: {
|
__non_webpack_require__: {
|
||||||
expr: module
|
expr: "require",
|
||||||
? `__WEBPACK_EXTERNAL_createRequire(${importMetaName}.url)`
|
|
||||||
: "require",
|
|
||||||
req: null,
|
req: null,
|
||||||
type: undefined, // type is not known, depends on environment
|
type: undefined, // type is not known, depends on environment
|
||||||
assign: true
|
assign: true
|
||||||
|
@ -132,19 +128,9 @@ function getReplacements(module, importMetaName) {
|
||||||
|
|
||||||
const PLUGIN_NAME = "APIPlugin";
|
const PLUGIN_NAME = "APIPlugin";
|
||||||
|
|
||||||
/**
|
const moduleCreateRequire = "__WEBPACK_EXTERNAL_createRequire";
|
||||||
* @typedef {object} APIPluginOptions
|
|
||||||
* @property {boolean=} module the output filename
|
|
||||||
*/
|
|
||||||
|
|
||||||
class APIPlugin {
|
class APIPlugin {
|
||||||
/**
|
|
||||||
* @param {APIPluginOptions=} options options
|
|
||||||
*/
|
|
||||||
constructor(options = {}) {
|
|
||||||
this.options = options;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply the plugin
|
* Apply the plugin
|
||||||
* @param {Compiler} compiler the compiler instance
|
* @param {Compiler} compiler the compiler instance
|
||||||
|
@ -155,10 +141,14 @@ class APIPlugin {
|
||||||
PLUGIN_NAME,
|
PLUGIN_NAME,
|
||||||
(compilation, { normalModuleFactory }) => {
|
(compilation, { normalModuleFactory }) => {
|
||||||
const importMetaName = compilation.outputOptions.importMetaName;
|
const importMetaName = compilation.outputOptions.importMetaName;
|
||||||
const REPLACEMENTS = getReplacements(
|
const moduleOutput = compilation.options.output.module;
|
||||||
this.options.module,
|
const nodeTarget = compiler.platform.node;
|
||||||
importMetaName
|
const nodeEsm = moduleOutput && nodeTarget;
|
||||||
);
|
|
||||||
|
const REPLACEMENTS = getReplacements();
|
||||||
|
if (nodeEsm) {
|
||||||
|
REPLACEMENTS.__non_webpack_require__.expr = `${moduleCreateRequire}(${importMetaName}.url)`;
|
||||||
|
}
|
||||||
|
|
||||||
compilation.dependencyTemplates.set(
|
compilation.dependencyTemplates.set(
|
||||||
ConstDependency,
|
ConstDependency,
|
||||||
|
@ -190,7 +180,7 @@ class APIPlugin {
|
||||||
if (/** @type {BuildInfo} */ (module.buildInfo).needCreateRequire) {
|
if (/** @type {BuildInfo} */ (module.buildInfo).needCreateRequire) {
|
||||||
const chunkInitFragments = [
|
const chunkInitFragments = [
|
||||||
new InitFragment(
|
new InitFragment(
|
||||||
`import { createRequire as __WEBPACK_EXTERNAL_createRequire } from ${renderContext.runtimeTemplate.renderNodePrefixForCoreModule(
|
`import { createRequire as ${moduleCreateRequire} } from ${renderContext.runtimeTemplate.renderNodePrefixForCoreModule(
|
||||||
"module"
|
"module"
|
||||||
)};\n`,
|
)};\n`,
|
||||||
InitFragment.STAGE_HARMONY_IMPORTS,
|
InitFragment.STAGE_HARMONY_IMPORTS,
|
||||||
|
@ -215,9 +205,20 @@ class APIPlugin {
|
||||||
parser.hooks.expression.for(key).tap(PLUGIN_NAME, (expression) => {
|
parser.hooks.expression.for(key).tap(PLUGIN_NAME, (expression) => {
|
||||||
const dep = toConstantDependency(parser, info.expr, info.req);
|
const dep = toConstantDependency(parser, info.expr, info.req);
|
||||||
|
|
||||||
if (key === "__non_webpack_require__" && this.options.module) {
|
if (key === "__non_webpack_require__" && moduleOutput) {
|
||||||
/** @type {BuildInfo} */
|
if (nodeTarget) {
|
||||||
(parser.state.module.buildInfo).needCreateRequire = true;
|
/** @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);
|
return dep(expression);
|
||||||
|
|
|
@ -473,9 +473,7 @@ class WebpackOptionsApply extends OptionsApply {
|
||||||
|
|
||||||
new NodeStuffPlugin(options.node).apply(compiler);
|
new NodeStuffPlugin(options.node).apply(compiler);
|
||||||
}
|
}
|
||||||
new APIPlugin({
|
new APIPlugin().apply(compiler);
|
||||||
module: options.output.module
|
|
||||||
}).apply(compiler);
|
|
||||||
new ExportsInfoApiPlugin().apply(compiler);
|
new ExportsInfoApiPlugin().apply(compiler);
|
||||||
new WebpackIsIncludedPlugin().apply(compiler);
|
new WebpackIsIncludedPlugin().apply(compiler);
|
||||||
new ConstPlugin().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);
|
/** @type {BuildInfo} */ (m.buildInfo);
|
||||||
|
|
||||||
const buildInfo = /** @type {BuildInfo} */ (this.buildInfo);
|
const buildInfo = /** @type {BuildInfo} */ (this.buildInfo);
|
||||||
|
@ -901,6 +901,11 @@ class ConcatenatedModule extends Module {
|
||||||
buildInfo.topLevelDeclarations = undefined;
|
buildInfo.topLevelDeclarations = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// populate needCreateRequire
|
||||||
|
if (needCreateRequire) {
|
||||||
|
this.buildInfo.needCreateRequire = true;
|
||||||
|
}
|
||||||
|
|
||||||
// populate assets
|
// populate assets
|
||||||
if (assets) {
|
if (assets) {
|
||||||
if (buildInfo.assets === undefined) {
|
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