Merge pull request #11529 from webpack/bugfix/move-to-entrypoint
allow to move modules to parent chunks
This commit is contained in:
commit
2604b5279a
|
@ -28,6 +28,7 @@ const MinMaxSizeWarning = require("./MinMaxSizeWarning");
|
|||
/** @typedef {import("../../declarations/WebpackOptions").Output} OutputOptions */
|
||||
/** @typedef {import("../Chunk")} Chunk */
|
||||
/** @typedef {import("../ChunkGraph")} ChunkGraph */
|
||||
/** @typedef {import("../ChunkGroup")} ChunkGroup */
|
||||
/** @typedef {import("../Compilation").AssetInfo} AssetInfo */
|
||||
/** @typedef {import("../Compilation").PathData} PathData */
|
||||
/** @typedef {import("../Compiler")} Compiler */
|
||||
|
@ -926,8 +927,10 @@ module.exports = class SplitChunksPlugin {
|
|||
return entry2;
|
||||
};
|
||||
|
||||
/** @type {Map<string, boolean>} */
|
||||
const alreadyValidatedParents = new Map();
|
||||
/** @type {Set<string>} */
|
||||
const alreadyValidatedNames = new Set();
|
||||
const alreadyReportedErrors = new Set();
|
||||
|
||||
// Map a list of chunks to a list of modules
|
||||
// For the key the chunk "index" is used, the value is a SortableSet of modules
|
||||
|
@ -958,23 +961,55 @@ module.exports = class SplitChunksPlugin {
|
|||
cacheGroup.key
|
||||
);
|
||||
// Check if the name is ok
|
||||
if (!alreadyValidatedNames.has(name)) {
|
||||
alreadyValidatedNames.add(name);
|
||||
if (compilation.namedChunks.has(name)) {
|
||||
compilation.errors.push(
|
||||
new WebpackError(
|
||||
"SplitChunksPlugin\n" +
|
||||
`Cache group "${cacheGroup.key}" conflicts with existing chunk.\n` +
|
||||
`Both have the same name "${name}".\n` +
|
||||
"Use a different name for the cache group.\n" +
|
||||
'HINT: You can omit "name" to automatically create a name.\n' +
|
||||
"BREAKING CHANGE: webpack < 5 used to allow to use the " +
|
||||
"entrypoint as splitChunk. This is no longer allowed. " +
|
||||
"Remove this entrypoint and add modules to cache group's 'test' instead. " +
|
||||
"If you need modules to be evaluated on startup, add them to the existing entrypoints (make them arrays). " +
|
||||
"See migration guide of more info."
|
||||
)
|
||||
);
|
||||
const existingChunk = compilation.namedChunks.get(name);
|
||||
if (existingChunk) {
|
||||
const parentValidationKey = `${name}|${selectedChunksKey}`;
|
||||
const valid = alreadyValidatedParents.get(parentValidationKey);
|
||||
if (valid === false) return;
|
||||
if (valid === undefined) {
|
||||
// Module can only be moved into the existing chunk if the existing chunk
|
||||
// is a parent of all selected chunks
|
||||
let isInAllParents = true;
|
||||
/** @type {Set<ChunkGroup>} */
|
||||
const queue = new Set();
|
||||
for (const chunk of selectedChunks) {
|
||||
for (const group of chunk.groupsIterable) {
|
||||
queue.add(group);
|
||||
}
|
||||
}
|
||||
for (const group of queue) {
|
||||
if (existingChunk.isInGroup(group)) continue;
|
||||
let hasParent = false;
|
||||
for (const parent of group.parentsIterable) {
|
||||
hasParent = true;
|
||||
queue.add(parent);
|
||||
}
|
||||
if (!hasParent) {
|
||||
isInAllParents = false;
|
||||
}
|
||||
}
|
||||
const valid = isInAllParents;
|
||||
alreadyValidatedParents.set(parentValidationKey, valid);
|
||||
if (!valid) {
|
||||
if (!alreadyReportedErrors.has(name)) {
|
||||
alreadyReportedErrors.add(name);
|
||||
compilation.errors.push(
|
||||
new WebpackError(
|
||||
"SplitChunksPlugin\n" +
|
||||
`Cache group "${cacheGroup.key}" conflicts with existing chunk.\n` +
|
||||
`Both have the same name "${name}" and existing chunk is not a parent of the selected modules.\n` +
|
||||
"Use a different name for the cache group or make sure that the existing chunk is a parent (e. g. via dependsOn).\n" +
|
||||
'HINT: You can omit "name" to automatically create a name.\n' +
|
||||
"BREAKING CHANGE: webpack < 5 used to allow to use an entrypoint as splitChunk. " +
|
||||
"This is no longer allowed when the entrypoint is not a parent of the selected modules.\n" +
|
||||
"Remove this entrypoint and add modules to cache group's 'test' instead. " +
|
||||
"If you need modules to be evaluated on startup, add them to the existing entrypoints (make them arrays). " +
|
||||
"See migration guide of more info."
|
||||
)
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Create key for maps
|
||||
|
@ -1289,13 +1324,6 @@ module.exports = class SplitChunksPlugin {
|
|||
}
|
||||
if (chunkName) {
|
||||
newChunk.chunkReason += ` (name: ${chunkName})`;
|
||||
// If the chosen name is already an entry point we remove the entry point
|
||||
const entrypoint = compilation.entrypoints.get(chunkName);
|
||||
if (entrypoint) {
|
||||
compilation.entrypoints.delete(chunkName);
|
||||
entrypoint.remove();
|
||||
chunkGraph.disconnectEntries(newChunk);
|
||||
}
|
||||
}
|
||||
if (item.cacheGroup.filename) {
|
||||
newChunk.filenameTemplate = item.cacheGroup.filename;
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
export { default as moduleA } from "./moduleA";
|
||||
export { default as moduleB } from "./moduleB";
|
||||
export { default as moduleC } from "./moduleC";
|
|
@ -0,0 +1,15 @@
|
|||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
it("should place the module correctly", async () => {
|
||||
const { moduleA, moduleB, moduleC } = await import("./chunk");
|
||||
expect(fs.readFileSync(path.resolve(__dirname, "a.js"), "utf-8")).toContain(
|
||||
moduleA
|
||||
);
|
||||
expect(fs.readFileSync(path.resolve(__dirname, "b.js"), "utf-8")).toContain(
|
||||
moduleB
|
||||
);
|
||||
expect(
|
||||
fs.readFileSync(path.resolve(__dirname, "runtime.js"), "utf-8")
|
||||
).toContain(moduleC);
|
||||
});
|
|
@ -0,0 +1 @@
|
|||
export default "This is module a";
|
|
@ -0,0 +1 @@
|
|||
export default "This is module b";
|
|
@ -0,0 +1 @@
|
|||
export default "This is module c";
|
|
@ -0,0 +1,5 @@
|
|||
module.exports = {
|
||||
findBundle: function (i, options) {
|
||||
return ["runtime.js", "a.js", "b.js"];
|
||||
}
|
||||
};
|
|
@ -0,0 +1,38 @@
|
|||
/** @type {import("../../../../").Configuration} */
|
||||
module.exports = {
|
||||
entry: {
|
||||
a: {
|
||||
import: "./entryA",
|
||||
runtime: "runtime"
|
||||
},
|
||||
b: {
|
||||
import: "./entryB",
|
||||
dependOn: "a"
|
||||
}
|
||||
},
|
||||
output: {
|
||||
filename: "[name].js"
|
||||
},
|
||||
optimization: {
|
||||
chunkIds: "named",
|
||||
splitChunks: {
|
||||
cacheGroups: {
|
||||
a: {
|
||||
test: /moduleA/,
|
||||
name: "a",
|
||||
enforce: true
|
||||
},
|
||||
b: {
|
||||
test: /moduleB/,
|
||||
name: "b",
|
||||
enforce: true
|
||||
},
|
||||
c: {
|
||||
test: /moduleC/,
|
||||
name: "runtime",
|
||||
enforce: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue