如何配置 webpack 4 以防止块出现在任何其他包中的入口点列表中?
How to configure webpack 4 to prevent chunks from list of entry points appearing in any other bundle?
我正在做一个大项目,并试图登陆 webpack 3 -> 4 更新。这个应用程序有大约 1,000 个入口点,其中大约 10 个被认为是 "global" 或 "core" 并且保证在每个页面上。这些核心包包含供应商和非供应商代码的混合。
在 webpack 3 中,我们一直在使用 CommonsChunkPlugin 来实现这一点。这是一个简单的例子:
new webpack.optimize.CommonsChunkPlugin({
name: 'a-global-bundle',
minChunks: Infinity,
}),
现在使用 webpack 4 并删除了 CommonsChunkPlugin,我不清楚如何完成这种优化。
我希望能够为 webpack 提供一个入口点列表,并且出现在其中任何一个中的任何块都不会出现在任何其他包中,但我不确定如何执行此操作。我通读了 some forthcoming documentation on splitChunks
,但无法拼凑出解决方案。
我已经建立了一个小回购协议作为修补的起点:https://github.com/lencioni/webpack-splitchunks-playground
我正在尝试的一个有趣的方向是为每个入口点配置 cacheGroups
,并使用执行此检查的函数实现 test
选项。但是,关于这方面的文档非常少,所以我不太确定编写此测试函数的正确方法是什么,甚至不确定这是否可行。
Our goal is to configure webpack to build our assets so that any
chunks that appear in any of these bundles will not appear in any
other bundle.
我之前有:
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module, count) {
// this assumes your vendor imports exist in the node_modules directory and module should be required
// in at least 3 entries before it moved to common chunk
return (module.context && module.context.indexOf('node_modules') !== -1) && count > 2;
}
}),
现在的运作方式:
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /[\/]node_modules[\/]/,
chunks: 'all',
name: 'vendor',
enforce: true,
minChunks: 3
}
}
}
},
您当前的配置(使用 Webpack 3)使用 CommonsChunkPlugin
作为 Explicit vendor chunk:
Split your code into vendor and application.
检查 repo 的 Webpack 输出,我发现 a.bundle.js
包含以下代码:
// `react`, `react-dom` plus
console.log('core module'); // from core-module.js
console.log('core module b'); // from core-module-b.js
console.log('non-core module'); // from non-core-module.js
类似的代码在b.bundle.js
里面(这个脚本的区别是最后一个console.log
引用自non-core-module-b.js
:console.log('non-core module b');
)。
将 webpack.config.js
优化选项更新为:
optimization: {
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
cacheGroups: {
default: {
enforce: true,
priority: 1
},
vendors: {
test: /[\/]node_modules[\/]/,
priority: 2,
name: 'vendors',
enforce: true,
chunks: 'all'
}
}
}
}
在捆绑包之间生成非重复代码。
您可以查看工作代码here。
我还为您的示例项目创建了一个 pull request。
的更多信息
好的,所以我想我已经想出了如何做到这一点。但首先,这是使用默认 splitChunks 配置构建的样子(注意 FOO.bundle.js 是由动态导入创建的异步包):
Asset Size Chunks Chunk Names
core.bundle.js 605 KiB 0 [emitted] [big] core
coreB.bundle.js 791 KiB 1 [emitted] [big] coreB
coreC.bundle.js 791 KiB 2 [emitted] [big] coreC
a.bundle.js 748 KiB 3 [emitted] [big] a
b.bundle.js 792 KiB 4 [emitted] [big] b
c.bundle.js 674 KiB 5 [emitted] [big] c
FOO.bundle.js 709 bytes 6 [emitted] FOO
runtime.bundle.js 7.49 KiB 7 [emitted] runtime
如果目标是让出现在 core、coreB 和 coreC 中的任何模块都不会出现在任何其他 bundle 中,这可以通过以下配置来完成:
function coreBundleCacheGroups(coreBundles) {
const cacheGroups = {};
const coreChunkNames = Object.keys(coreBundles);
const coreChunkNamesSet = new Set(coreChunkNames);
coreChunkNames.forEach((name) => {
cacheGroups[name] = {
name,
chunks: 'all',
minSize: 0,
minChunks: 1,
reuseExistingChunk: true,
priority: 10000,
enforce: true,
test(module, chunks) {
if (module.depth === 0) {
return false;
}
// Find first core chunk name that matches
const partOfGlobalChunks = chunks.filter(chunk => coreChunkNamesSet.has(chunk.name));
if (!partOfGlobalChunks.length) {
return false;
}
const partOfGlobalChunksSet = new Set(partOfGlobalChunks.map(chunk => chunk.name));
const firstCoreChunkName = coreChunkNames.find(name => partOfGlobalChunksSet.has(name));
return firstCoreChunkName === name;
},
};
});
return cacheGroups;
}
const coreBundles = {
core: './src/bundles/core.js',
coreB: './src/bundles/core-b.js',
coreC: './src/bundles/core-c.js',
};
module.exports = {
mode: 'none',
entry: {
...coreBundles,
a: './src/bundles/a.js',
b: './src/bundles/b.js',
c: './src/bundles/c.js',
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
optimization: {
runtimeChunk: 'single',
splitChunks: {
cacheGroups: {
...coreBundleCacheGroups(coreBundles),
},
},
},
};
产生以下输出:
Asset Size Chunks Chunk Names
core.bundle.js 605 KiB 0 [emitted] [big] core
coreB.bundle.js 188 KiB 1 [emitted] coreB
coreC.bundle.js 1.5 KiB 2 [emitted] coreC
a.bundle.js 76.4 KiB 3 [emitted] a
b.bundle.js 2.28 KiB 4 [emitted] b
c.bundle.js 1.91 KiB 5 [emitted] c
FOO.bundle.js 622 bytes 6 [emitted] FOO
runtime.bundle.js 7.49 KiB 7 [emitted] runtime
我正在做一个大项目,并试图登陆 webpack 3 -> 4 更新。这个应用程序有大约 1,000 个入口点,其中大约 10 个被认为是 "global" 或 "core" 并且保证在每个页面上。这些核心包包含供应商和非供应商代码的混合。
在 webpack 3 中,我们一直在使用 CommonsChunkPlugin 来实现这一点。这是一个简单的例子:
new webpack.optimize.CommonsChunkPlugin({
name: 'a-global-bundle',
minChunks: Infinity,
}),
现在使用 webpack 4 并删除了 CommonsChunkPlugin,我不清楚如何完成这种优化。
我希望能够为 webpack 提供一个入口点列表,并且出现在其中任何一个中的任何块都不会出现在任何其他包中,但我不确定如何执行此操作。我通读了 some forthcoming documentation on splitChunks
,但无法拼凑出解决方案。
我已经建立了一个小回购协议作为修补的起点:https://github.com/lencioni/webpack-splitchunks-playground
我正在尝试的一个有趣的方向是为每个入口点配置 cacheGroups
,并使用执行此检查的函数实现 test
选项。但是,关于这方面的文档非常少,所以我不太确定编写此测试函数的正确方法是什么,甚至不确定这是否可行。
Our goal is to configure webpack to build our assets so that any chunks that appear in any of these bundles will not appear in any other bundle.
我之前有:
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module, count) {
// this assumes your vendor imports exist in the node_modules directory and module should be required
// in at least 3 entries before it moved to common chunk
return (module.context && module.context.indexOf('node_modules') !== -1) && count > 2;
}
}),
现在的运作方式:
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /[\/]node_modules[\/]/,
chunks: 'all',
name: 'vendor',
enforce: true,
minChunks: 3
}
}
}
},
您当前的配置(使用 Webpack 3)使用 CommonsChunkPlugin
作为 Explicit vendor chunk:
Split your code into vendor and application.
检查 repo 的 Webpack 输出,我发现 a.bundle.js
包含以下代码:
// `react`, `react-dom` plus
console.log('core module'); // from core-module.js
console.log('core module b'); // from core-module-b.js
console.log('non-core module'); // from non-core-module.js
类似的代码在b.bundle.js
里面(这个脚本的区别是最后一个console.log
引用自non-core-module-b.js
:console.log('non-core module b');
)。
将 webpack.config.js
优化选项更新为:
optimization: {
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
cacheGroups: {
default: {
enforce: true,
priority: 1
},
vendors: {
test: /[\/]node_modules[\/]/,
priority: 2,
name: 'vendors',
enforce: true,
chunks: 'all'
}
}
}
}
在捆绑包之间生成非重复代码。
您可以查看工作代码here。 我还为您的示例项目创建了一个 pull request。
的更多信息好的,所以我想我已经想出了如何做到这一点。但首先,这是使用默认 splitChunks 配置构建的样子(注意 FOO.bundle.js 是由动态导入创建的异步包):
Asset Size Chunks Chunk Names
core.bundle.js 605 KiB 0 [emitted] [big] core
coreB.bundle.js 791 KiB 1 [emitted] [big] coreB
coreC.bundle.js 791 KiB 2 [emitted] [big] coreC
a.bundle.js 748 KiB 3 [emitted] [big] a
b.bundle.js 792 KiB 4 [emitted] [big] b
c.bundle.js 674 KiB 5 [emitted] [big] c
FOO.bundle.js 709 bytes 6 [emitted] FOO
runtime.bundle.js 7.49 KiB 7 [emitted] runtime
如果目标是让出现在 core、coreB 和 coreC 中的任何模块都不会出现在任何其他 bundle 中,这可以通过以下配置来完成:
function coreBundleCacheGroups(coreBundles) {
const cacheGroups = {};
const coreChunkNames = Object.keys(coreBundles);
const coreChunkNamesSet = new Set(coreChunkNames);
coreChunkNames.forEach((name) => {
cacheGroups[name] = {
name,
chunks: 'all',
minSize: 0,
minChunks: 1,
reuseExistingChunk: true,
priority: 10000,
enforce: true,
test(module, chunks) {
if (module.depth === 0) {
return false;
}
// Find first core chunk name that matches
const partOfGlobalChunks = chunks.filter(chunk => coreChunkNamesSet.has(chunk.name));
if (!partOfGlobalChunks.length) {
return false;
}
const partOfGlobalChunksSet = new Set(partOfGlobalChunks.map(chunk => chunk.name));
const firstCoreChunkName = coreChunkNames.find(name => partOfGlobalChunksSet.has(name));
return firstCoreChunkName === name;
},
};
});
return cacheGroups;
}
const coreBundles = {
core: './src/bundles/core.js',
coreB: './src/bundles/core-b.js',
coreC: './src/bundles/core-c.js',
};
module.exports = {
mode: 'none',
entry: {
...coreBundles,
a: './src/bundles/a.js',
b: './src/bundles/b.js',
c: './src/bundles/c.js',
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
optimization: {
runtimeChunk: 'single',
splitChunks: {
cacheGroups: {
...coreBundleCacheGroups(coreBundles),
},
},
},
};
产生以下输出:
Asset Size Chunks Chunk Names
core.bundle.js 605 KiB 0 [emitted] [big] core
coreB.bundle.js 188 KiB 1 [emitted] coreB
coreC.bundle.js 1.5 KiB 2 [emitted] coreC
a.bundle.js 76.4 KiB 3 [emitted] a
b.bundle.js 2.28 KiB 4 [emitted] b
c.bundle.js 1.91 KiB 5 [emitted] c
FOO.bundle.js 622 bytes 6 [emitted] FOO
runtime.bundle.js 7.49 KiB 7 [emitted] runtime