CommonsChunkPlugin
は、複数のエントリポイント間で共有される共通モジュールで構成される個別のファイル(チャンクと呼ばれます)を作成するオプトイン機能です。
共通モジュールをバンドルから分離することで、生成されたチャンクファイルは最初に一度だけロードされ、後で使用するためにキャッシュに保存できます。これにより、新しいページが訪問されるたびに大きなバンドルを強制的にロードするのではなく、ブラウザがキャッシュから共有コードをすばやく提供できるため、ページの速度が最適化されます。
new webpack.optimize.CommonsChunkPlugin(options);
{
name: string, // or
names: string[],
// The chunk name of the commons chunk. An existing chunk can be selected by passing a name of an existing chunk.
// If an array of strings is passed this is equal to invoking the plugin multiple times for each chunk name.
// If omitted and `options.async` or `options.children` is set all chunks are used, otherwise `options.filename`
// is used as chunk name.
// When using `options.async` to create common chunks from other async chunks you must specify an entry-point
// chunk name here instead of omitting the `option.name`.
filename: string,
// The filename template for the commons chunk. Can contain the same placeholders as `output.filename`.
// If omitted the original filename is not modified (usually `output.filename` or `output.chunkFilename`).
// This option is not permitted if you're using `options.async` as well, see below for more details.
minChunks: number|Infinity|function(module, count) => boolean,
// The minimum number of chunks which need to contain a module before it's moved into the commons chunk.
// The number must be greater than or equal 2 and lower than or equal to the number of chunks.
// Passing `Infinity` creates the commons chunk, but moves no modules into it.
// By providing a `function` you can add custom logic. (Defaults to the number of chunks)
chunks: string[],
// Select the source chunks by chunk names. The chunk must be a child of the commons chunk.
// If omitted all entry chunks are selected.
children: boolean,
// If `true` all children of the commons chunk are selected
deepChildren: boolean,
// If `true` all descendants of the commons chunk are selected
async: boolean|string,
// If `true` a new async commons chunk is created as child of `options.name` and sibling of `options.chunks`.
// It is loaded in parallel with `options.chunks`.
// Instead of using `option.filename`, it is possible to change the name of the output file by providing
// the desired string here instead of `true`.
minSize: number,
// Minimum size of all common module before a commons chunk is created.
}
エントリポイント間で共有される共通モジュールを含む追加のチャンクを生成します。
new webpack.optimize.CommonsChunkPlugin({
name: 'commons',
// (the commons chunk name)
filename: 'commons.js',
// (the filename of the commons chunk)
// minChunks: 3,
// (Modules must be shared between 3 entries)
// chunks: ["pageA", "pageB"],
// (Only use these entries)
});
生成されたチャンクは、エントリポイントの前にロードする必要があります。
<script src="commons.js" charset="utf-8"></script>
<script src="entry.bundle.js" charset="utf-8"></script>
コードをベンダーとアプリケーションに分割します。
module.exports = {
//...
entry: {
vendor: ['jquery', 'other-lib'],
app: './entry',
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
// filename: "vendor.js"
// (Give the chunk a different name)
minChunks: Infinity,
// (with more entries, this ensures that no other module
// goes into the vendor chunk)
}),
],
};
<script src="vendor.js" charset="utf-8"></script>
<script src="app.js" charset="utf-8"></script>
コード分割を使用すると、エントリチャンクの複数の子チャンクに共通の依存関係がある場合があります。重複を避けるために、これらを親に移動できます。これにより、全体的なサイズは小さくなりますが、初期ロード時間に悪影響があります。ユーザーが多数の兄弟チャンク(つまり、エントリチャンクの子)をダウンロードする必要があると予想される場合は、全体的なロード時間が改善されるはずです。
new webpack.optimize.CommonsChunkPlugin({
// names: ["app", "subPageA"]
// (choose the chunks, or omit for all chunks)
children: true,
// (select all children of chosen chunks)
// minChunks: 3,
// (3 children must share the module before it's moved)
});
上記と同様ですが、共通モジュールを親に移動する(初期ロード時間が増加する)のではなく、新しく非同期ロードされる追加の共通チャンクが使用されます。これは、追加のチャンクがダウンロードされるときに自動的に並行してダウンロードされます。
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
// or
names: ['app', 'subPageA'],
// the name or list of names must match the name or names
// of the entry points that create the async chunks
children: true,
// (use all children of the chunk)
async: true,
// (create an async commons chunk)
minChunks: 3,
// (3 children must share the module before it's separated)
});
minChunks
プロパティに関数を渡すminChunks
プロパティに関数を渡すこともできます。この関数は、CommonsChunkPlugin
によって呼び出され、module
とcount
の引数を付けて関数を呼び出します。
module
引数は、name
/names
プロパティを介して提供したチャンク内の各モジュールを表します。 module
はNormalModuleの形状を持ち、このユースケースで特に便利な2つのプロパティがあります。
module.context
:ファイルが格納されているディレクトリ。例:'/my_project/node_modules/example-dependency'
module.resource
:処理中のファイルの名前。例:'/my_project/node_modules/example-dependency/index.js'
count
引数は、module
が使用されているチャンクの数を表します。
このオプションは、CommonsChunkアルゴリズムがモジュールをどこに移動するかを決定する方法をきめ細かく制御したい場合に役立ちます。
new webpack.optimize.CommonsChunkPlugin({
name: 'my-single-lib-chunk',
filename: 'my-single-lib-chunk.js',
minChunks: function (module, count) {
// If module has a path, and inside of the path exists the name "somelib",
// and it is used in 3 separate chunks/entries, then break it out into
// a separate chunk with chunk keyname "my-single-lib-chunk", and filename "my-single-lib-chunk.js"
return module.resource && /somelib/.test(module.resource) && count === 3;
},
});
上記のように、この例では、関数内のすべての条件が満たされた場合にのみ、1つのライブラリを別のファイルに移動できます。
この概念を使用して、暗黙的な共通ベンダーチャンクを取得できます。
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module) {
// this assumes your vendor imports exist in the node_modules directory
return module.context && module.context.includes('node_modules');
},
});
webpackブートストラップロジックを別のファイルに抽出するには、entry
として定義されていないname
でCommonsChunkPlugin
を使用します。一般的に、manifest
という名前が使用されます。詳細については、キャッシュガイドを参照してください。
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity,
});
vendor
およびmanifest
チャンクはminChunks
の異なる定義を使用するため、プラグインを2回呼び出す必要があります。
[
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module) {
return module.context && module.context.includes('node_modules');
},
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity,
}),
];