CommonsChunkPlugin

CommonsChunkPlugin 插件,是一个可选的用于建立一个独立文件(又称作 chunk)的功能,这个文件包括多个入口 chunk 的公共模块。

The CommonsChunkPlugin 已经从 webpack v4 legato 中移除。想要了解在最新版本中如何处理 chunk,请查看 SplitChunksPlugin

通过将公共模块拆出来,最终合成的文件能够在最开始的时候加载一次,便存到缓存中供后续使用。这个带来页面速度上的提升,因为浏览器会迅速将公共的代码从缓存中取出来,而不是每次访问一个新页面时,再去加载一个更大的文件。

  1. new webpack.optimize.CommonsChunkPlugin(options);

配置

  1. {
  2. name: string, // or
  3. names: string[],
  4. // 这是 common chunk 的名称。已经存在的 chunk 可以通过传入一个已存在的 chunk 名称而被选择。
  5. // 如果一个字符串数组被传入,这相当于插件针对每个 chunk 名被多次调用
  6. // 如果该选项被忽略,同时 `options.async` 或者 `options.children` 被设置,所有的 chunk 都会被使用,
  7. // 否则 `options.filename` 会用于作为 chunk 名。
  8. // When using `options.async` to create common chunks from other async chunks you must specify an entry-point
  9. // chunk name here instead of omitting the `option.name`.
  10. filename: string,
  11. // common chunk 的文件名模板。可以包含与 `output.filename` 相同的占位符。
  12. // 如果被忽略,原本的文件名不会被修改(通常是 `output.filename` 或者 `output.chunkFilename`)。
  13. // This option is not permitted if you're using `options.async` as well, see below for more details.
  14. minChunks: number|Infinity|function(module, count) => boolean,
  15. // 在传入 公共chunk(commons chunk) 之前所需要包含的最少数量的 chunks 。
  16. // 数量必须大于等于2,或者少于等于 chunks的数量
  17. // 传入 `Infinity` 会马上生成 公共chunk,但里面没有模块。
  18. // 你可以传入一个 `function` ,以添加定制的逻辑(默认是 chunk 的数量)
  19. chunks: string[],
  20. // 通过 chunk name 去选择 chunks 的来源。chunk 必须是 公共chunk 的子模块。
  21. // 如果被忽略,所有的,所有的 入口chunk (entry chunk) 都会被选择。
  22. children: boolean,
  23. // 如果设置为 `true`,所有公共 chunk 的子模块都会被选择
  24. deepChildren: boolean,
  25. // 如果设置为 `true`,所有公共 chunk 的后代模块都会被选择
  26. async: boolean|string,
  27. // 如果设置为 `true`,一个异步的 公共chunk 会作为 `options.name` 的子模块,和 `options.chunks` 的兄弟模块被创建。
  28. // 它会与 `options.chunks` 并行被加载。
  29. // Instead of using `option.filename`, it is possible to change the name of the output file by providing
  30. // the desired string here instead of `true`.
  31. minSize: number,
  32. // 在 公共chunk 被创建立之前,所有 公共模块 (common module) 的最少大小。
  33. }

webpack1 构造函数 new webpack.optimize.CommonsChunkPlugin(options, filenameTemplate, selectedChunks, minChunks) 不再被支持。请使用相应的选项对象。

例子

公共chunk 用于 入口chunk (entry chunk)

生成一个额外的 chunk 包含入口chunk 的公共模块。

  1. new webpack.optimize.CommonsChunkPlugin({
  2. name: 'commons',
  3. // (公共 chunk(commnon chunk) 的名称)
  4. filename: 'commons.js',
  5. // (公共chunk 的文件名)
  6. // minChunks: 3,
  7. // (模块必须被3个 入口chunk 共享)
  8. // chunks: ["pageA", "pageB"],
  9. // (只使用这些 入口chunk)
  10. });

你必须在 入口chunk 之前加载生成的这个 公共chunk:

  1. <script src="commons.js" charset="utf-8"></script>
  2. <script src="entry.bundle.js" charset="utf-8"></script>

明确第三方库 chunk

将你的代码拆分成公共代码和应用代码。

  1. module.exports = {
  2. //...
  3. entry: {
  4. vendor: ['jquery', 'other-lib'],
  5. app: './entry'
  6. },
  7. plugins: [
  8. new webpack.optimize.CommonsChunkPlugin({
  9. name: 'vendor',
  10. // filename: "vendor.js"
  11. // (给 chunk 一个不同的名字)
  12. minChunks: Infinity,
  13. // (随着 entry chunk 越来越多,
  14. // 这个配置保证没其它的模块会打包进 vendor chunk)
  15. })
  16. ]
  17. };
  1. <script src="vendor.js" charset="utf-8"></script>
  2. <script src="app.js" charset="utf-8"></script>

结合长期缓存,你可能需要使用这个插件去避免 公共chunk 改变。 你也需要使用 records 去保持稳定的模块 id,例如,使用 NamedModulesPluginHashedModuleIdsPlugin

将公共模块打包进父 chunk

使用代码拆分功能,一个 chunk 的多个子 chunk 会有公共的依赖。为了防止重复,可以将这些公共模块移入父 chunk。这会减少总体的大小,但会对首次加载时间产生不良影响。如果预期到用户需要下载许多兄弟 chunks(例如,入口 trunk 的子 chunk),那这对改善加载时间将非常有用。

  1. new webpack.optimize.CommonsChunkPlugin({
  2. // names: ["app", "subPageA"]
  3. // (选择 chunks,或者忽略该项设置以选择全部 chunks)
  4. children: true,
  5. // (选择所有被选 chunks 的子 chunks)
  6. // minChunks: 3,
  7. // (在提取之前需要至少三个子 chunk 共享这个模块)
  8. });

额外的异步 公共chunk

与上面的类似,但是并非将公共模块移动到父 chunk(增加初始加载时间),而是使用新的异步加载的额外公共chunk。当下载额外的 chunk 时,它将自动并行下载。

  1. new webpack.optimize.CommonsChunkPlugin({
  2. name: 'app',
  3. // or
  4. names: ['app', 'subPageA'],
  5. // the name or list of names must match the name or names
  6. // of the entry points that create the async chunks
  7. children: true,
  8. // (选择所有被选 chunks 的子 chunks)
  9. async: true,
  10. // (创建一个异步 公共chunk)
  11. minChunks: 3,
  12. // (在提取之前需要至少三个子 chunk 共享这个模块)
  13. });

minChunks 配置传入函数

你也可以给 minChunks 传入一个函数。这个函数会被 CommonsChunkPlugin 插件回调,并且调用函数时会传入 modulecount 参数。

module 参数代表每个 chunks 里的模块,这些 chunks 是你通过 name/names 参数传入的。 module has the shape of a NormalModule, which has two particularly useful properties for this use case:

  • module.context: The directory that stores the file. For example: '/my_project/node_modules/example-dependency'
  • module.resource: The name of the file being processed. For example: '/my_project/node_modules/example-dependency/index.js'

count 参数表示 module 被使用的 chunk 数量。

当你想要对 CommonsChunk 如何决定模块被打包到哪里的算法有更为细致的控制, 这个配置就会非常有用。

  1. new webpack.optimize.CommonsChunkPlugin({
  2. name: 'my-single-lib-chunk',
  3. filename: 'my-single-lib-chunk.js',
  4. minChunks: function(module, count) {
  5. // 如果模块是一个路径,而且在路径中有 "somelib" 这个名字出现,
  6. // 而且它还被三个不同的 chunks/入口chunk 所使用,那请将它拆分到
  7. // 另一个分开的 chunk 中,chunk 的 keyname 是 "my-single-lib-chunk",而文件名是 "my-single-lib-chunk.js"
  8. return module.resource && (/somelib/).test(module.resource) && count === 3;
  9. }
  10. });

正如上面看到的,这个例子允许你只将其中一个库移到一个分开的文件当中,当而仅当函数中的所有条件都被满足了。

This concept may be used to obtain implicit common vendor chunks:

  1. new webpack.optimize.CommonsChunkPlugin({
  2. name: 'vendor',
  3. minChunks: function (module) {
  4. // this assumes your vendor imports exist in the node_modules directory
  5. return module.context && module.context.includes('node_modules');
  6. }
  7. });

In order to obtain a single CSS file containing your application and vendor CSS, use the following minChunks function together with ExtractTextPlugin:

  1. new webpack.optimize.CommonsChunkPlugin({
  2. name: 'vendor',
  3. minChunks: function (module) {
  4. // This prevents stylesheet resources with the .css or .scss extension
  5. // from being moved from their original chunk to the vendor chunk
  6. if(module.resource && (/^.*\.(css|scss)$/).test(module.resource)) {
  7. return false;
  8. }
  9. return module.context && module.context.includes('node_modules');
  10. }
  11. });

Manifest file

To extract the webpack bootstrap logic into a separate file, use the CommonsChunkPlugin on a name which is not defined as entry. Commonly the name manifest is used. See the caching guide for details.

  1. new webpack.optimize.CommonsChunkPlugin({
  2. name: 'manifest',
  3. minChunks: Infinity
  4. });

Combining implicit common vendor chunks and manifest file

Since the vendor and manifest chunk use a different definition for minChunks, you need to invoke the plugin twice:

  1. [
  2. new webpack.optimize.CommonsChunkPlugin({
  3. name: 'vendor',
  4. minChunks: function(module){
  5. return module.context && module.context.includes('node_modules');
  6. }
  7. }),
  8. new webpack.optimize.CommonsChunkPlugin({
  9. name: 'manifest',
  10. minChunks: Infinity
  11. }),
  12. ];

More Examples


贡献人员

bebraw bebraw byzyk byzyk christopher4lis christopher4lis jdbevan jdbevan jeremenichelli jeremenichelli kevinzwhuang kevinzwhuang madhavarshney madhavarshney simon04 simon04