fix: add extra merge duplicates call after split chunks

This commit is contained in:
Mikhail Shipov 2024-09-10 13:15:06 +03:00
parent 6c4fd198d1
commit 1b217a6d94
15 changed files with 186 additions and 3 deletions

View File

@ -53,6 +53,7 @@ const DefaultStatsFactoryPlugin = require("./stats/DefaultStatsFactoryPlugin");
const DefaultStatsPresetPlugin = require("./stats/DefaultStatsPresetPlugin");
const DefaultStatsPrinterPlugin = require("./stats/DefaultStatsPrinterPlugin");
const { STAGE_BASIC, STAGE_ADVANCED } = require("./OptimizationStages");
const { cleverMerge } = require("./util/cleverMerge");
/** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
@ -434,7 +435,7 @@ class WebpackOptionsApply extends OptionsApply {
}
if (options.optimization.mergeDuplicateChunks) {
const MergeDuplicateChunksPlugin = require("./optimize/MergeDuplicateChunksPlugin");
new MergeDuplicateChunksPlugin().apply(compiler);
new MergeDuplicateChunksPlugin(STAGE_BASIC).apply(compiler);
}
if (options.optimization.flagIncludedChunks) {
const FlagIncludedChunksPlugin = require("./optimize/FlagIncludedChunksPlugin");
@ -474,6 +475,10 @@ class WebpackOptionsApply extends OptionsApply {
const SplitChunksPlugin = require("./optimize/SplitChunksPlugin");
new SplitChunksPlugin(options.optimization.splitChunks).apply(compiler);
}
if (options.optimization.mergeDuplicateChunks) {
const MergeDuplicateChunksPluginAdv = require("./optimize/MergeDuplicateChunksPlugin");
new MergeDuplicateChunksPluginAdv(STAGE_ADVANCED).apply(compiler);
}
if (options.optimization.runtimeChunk) {
const RuntimeChunkPlugin = require("./optimize/RuntimeChunkPlugin");
new RuntimeChunkPlugin(

View File

@ -5,12 +5,15 @@
"use strict";
const { STAGE_BASIC } = require("../OptimizationStages");
const { runtimeEqual } = require("../util/runtime");
/** @typedef {import("../Compiler")} Compiler */
class MergeDuplicateChunksPlugin {
constructor(stage) {
this.stage = stage;
}
/**
* @param {Compiler} compiler the compiler
* @returns {void}
@ -22,7 +25,7 @@ class MergeDuplicateChunksPlugin {
compilation.hooks.optimizeChunks.tap(
{
name: "MergeDuplicateChunksPlugin",
stage: STAGE_BASIC
stage: this.stage
},
chunks => {
const { chunkGraph, moduleGraph } = compilation;

View File

@ -4724,6 +4724,29 @@ global:
global (webpack x.x.x) compiled successfully in X ms"
`;
exports[`StatsTestCases should print correct stats for split-chunks-dedup 1`] = `
"asset main.js X KiB [emitted] (name: main) (id hint: main)
asset table--shared X bytes [emitted]
asset row-359--shared X bytes [emitted]
asset cell--shared X bytes [emitted]
asset templater--shared X bytes [emitted]
runtime modules X KiB 11 modules
built modules X bytes (javascript) X bytes (share-init) X bytes (consume-shared) [built]
cacheable modules X bytes
modules by path ./node_modules/ X bytes 4 modules
modules by path ./*.js X bytes 2 modules
provide-module modules X bytes
provide shared module (default) cell@1.0.0 = ./node_modules/cell/index.js X bytes [built] [code generated]
provide shared module (default) row@1.0.0 = ./node_modules/row/index.js X bytes [built] [code generated]
+ 2 modules
consume-shared-module modules X bytes
consume shared module (default) table@=1.0.0 (strict) (fallback: ./node_modules/...(truncated) X bytes [built] [code generated]
consume shared module (default) row@=1.0.0 (strict) (fallback: ./node_modules...(truncated) X bytes [built] [code generated]
consume shared module (default) templater@=1.0.0 (strict) (fallback: ./node_modu...(truncated) X bytes [built] [code generated]
consume shared module (default) cell@=1.0.0 (strict) (fallback: ./node_modules/...(truncated) X bytes [built] [code generated]
webpack x.x.x compiled successfully in X ms"
`;
exports[`StatsTestCases should print correct stats for tree-shaking 1`] = `
"asset bundle.js X KiB [emitted] (name: main)
runtime modules X bytes 3 modules

View File

@ -0,0 +1,5 @@
export default async () => {
const { test } = await import(/* webpackMode: "eager" */'./module')
test()
};

View File

@ -0,0 +1,5 @@
import { table } from 'table'
export function test() {
expect(table([['1']])).toBe('<table><tr><td>1</td></tr></table>')
}

View File

@ -0,0 +1,5 @@
const { tmpl } = require('templater')
module.exports.cell = function(cell) {
return tmpl(`<td>CELL</td>`, { CELL: cell })
}

View File

@ -0,0 +1,8 @@
{
"name": "row",
"version": "1.0.0",
"dependencies": {
"cell": "=1.0.0",
"templater": "=1.0.0"
}
}

View File

@ -0,0 +1,6 @@
const { cell } = require('cell')
const { tmpl } = require('templater')
module.exports.row = function(cells) {
return tmpl(`<tr>CELLS</tr>`, { CELLS: cells.map(c => cell(c)).join('\n') })
}

View File

@ -0,0 +1,8 @@
{
"name": "row",
"version": "1.0.0",
"dependencies": {
"cell": "=1.0.0",
"templater": "=1.0.0"
}
}

View File

@ -0,0 +1,6 @@
const { row } = require('row')
const { tmpl } = require('templater')
module.exports.table = function(rows) {
return tmpl('<table>ROWS</table>', { ROWS: rows.map(r => row(r)).join('\n') })
}

View File

@ -0,0 +1,8 @@
{
"name": "table",
"version": "1.0.0",
"dependencies": {
"row": "=1.0.0",
"templater": "=1.0.0"
}
}

View File

@ -0,0 +1,6 @@
module.exports.tmpl = function(str, params) {
Object.keys(params).forEach((k) => {
str = str.replace(new RegExp(k, 'g'), params[k])
})
return str
}

View File

@ -0,0 +1,4 @@
{
"name": "templater",
"version": "1.0.0"
}

View File

@ -0,0 +1,9 @@
{
"private": true,
"engines": {
"node": ">=10.13.0"
},
"dependencies": {
"table": "=2.0.0"
}
}

View File

@ -0,0 +1,82 @@
const { ModuleFederationPlugin } = require("../../../").container;
const {
WEBPACK_MODULE_TYPE_PROVIDE
} = require("../../../lib/ModuleTypeConstants");
const chunkIdChunkNameMap = new Map();
const usedSharedModuleNames = new Set();
/** @type {import("../../../").Configuration} */
module.exports = {
entry: {
main: "./"
},
mode: "production",
optimization: {
splitChunks: {
cacheGroups: {
defaultVendors: false,
main: {
name: "main",
enforce: true,
minChunks: 3
}
}
}
},
output: {
chunkFilename(pathData) {
const { chunk } = pathData;
if (chunk && "groupsIterable" in chunk) {
for (const group of chunk.groupsIterable) {
if (group.origins) {
for (const origin of group.origins) {
if (
origin.module.type === WEBPACK_MODULE_TYPE_PROVIDE &&
chunk.id
) {
if (chunkIdChunkNameMap.has(chunk.id)) {
return chunkIdChunkNameMap.get(chunk.id);
}
// @ts-expect-error
const sharedModuleName = origin.module._name;
let suffix = "";
if (usedSharedModuleNames.has(sharedModuleName)) {
suffix = `-${chunk.id}`;
}
const chunkName = `${sharedModuleName}${suffix}--shared`;
usedSharedModuleNames.add(sharedModuleName);
chunkIdChunkNameMap.set(chunk.id, chunkName);
return chunkName;
}
}
}
}
}
return "[id]--chunk";
}
},
plugins: [
new ModuleFederationPlugin({
shared: {
table: {
requiredVersion: "=1.0.0"
},
cell: {
requiredVersion: "=1.0.0"
},
row: {
requiredVersion: "=1.0.0"
},
templater: {
requiredVersion: "=1.0.0"
}
}
})
],
stats: {
assets: true
}
};