私は大規模なプロジェクトに取り組んでおり、webpack 3-> 4アップデートを取得しようとしています。このアプリには約1,000個のエントリポイントがあり、そのうち約10個は「グローバル」または「コア」と見なされ、すべてのページに存在することが保証されています。これらのコアバンドルには、ベンダーコードと非ベンダーコードが混在しています。これらのバンドルのすべてに表示されるチャンクが、ページに追加する必要のある新しいアセットを作成せずに、チャンクのサイズに関係なく他のバンドルに表示されないように、これらすべてのアセットを構築するようにwebpackを構成する必要があります。
Webpack 3では、これを実現するためにCommonsChunkPluginを使用しています。以下に簡単な例を示します。
new webpack.optimize.CommonsChunkPlugin({
name: 'a-global-bundle',
minChunks: Infinity,
}),
現在、webpack 4とCommonsChunkPluginの削除により、この種の最適化を達成する方法は明確ではありません。
Webpackにエントリポイントのリストを提供し、それらのいずれかに表示されるチャンクは他のバンドルには表示されないようにしたいと思いますが、これを行う方法がわかりません。 splitChunks
に関する今後のドキュメント を読みましたが、解決策をまとめることができませんでした。
https://github.com/lencioni/webpack-splitchunks-playground をいじくり回すための出発点として小さなリポジトリを設定しました
私が試している興味深い方向の1つは、これらの各エントリポイントのグループでcacheGroups
を構成し、このチェックを行う関数でtest
オプションを実装することです。しかし、ドキュメントはこれについてかなりまばらであるため、このテスト関数を記述する正しい方法が何であるか、またはこれがまったく機能するかどうかは本当にわかりません。
わかりましたので、これを行う方法を考え出したと思います。ただし、最初に、デフォルトの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に表示されるモジュールが他のバンドルに表示されないようにすることが目標である場合、これは次の構成で実行できます。
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を使用)は、 明示的なベンダーチャンク にCommonsChunkPlugin
を使用します。
コードをベンダーとアプリケーションに分割します。
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'
}
}
}
}
_
バンドル間に非重複コードを生成します。
作業コードを確認できます こちら 。また、サンプルプロジェクトに対して pull request を作成しました。
私たちの目標は、これらのバンドルのいずれかに表示されるチャンクが他のバンドルに表示されないように、アセットを構築するようにwebpackを構成することです。
私が以前持っていたもの:
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
}
}
}
},