CommonsChunkPlugin

CommonsChunkPlugin 是一个可选功能,它会创建一个单独的文件(称为 chunk),其中包含在多个入口点之间共享的公共模块。

通过将公共模块从 bundle 中分离出来,生成的 `chunk` 文件可以只在初始时加载一次,然后存储在缓存中以备后续使用。这可以优化页面速度,因为浏览器可以快速从缓存中提供共享代码,而不是在每次访问新页面时都被迫加载更大的 bundle。

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.
}

示例

入口的公共 `chunk`

生成一个额外的 `chunk`,其中包含入口点之间共享的公共模块。

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)
});

你必须在入口点之前加载生成的 `chunk`。

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

显式 `vendor chunk`

将你的代码拆分为 `vendor` 和应用程序。

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>

将公共模块移至父 `chunk`

结合 Code Splitting,一个入口 `chunk` 的多个子 `chunk` 可以拥有公共依赖。为了防止重复,这些依赖可以被移动到父 `chunk` 中。这会减小总体大小,但会对初始加载时间产生负面影响。如果预期用户需要下载许多兄弟 `chunk`(即入口 `chunk` 的子 `chunk`),那么这应该会总体上改善加载时间。

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)
});

额外的异步公共 `chunk`

与上面类似,但不是将公共模块移入父 `chunk`(这会增加初始加载时间),而是使用一个新的异步加载的附加公共 `chunk`。当附加 `chunk` 被下载时,它会自动并行下载。

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 调用,并使用 modulecount 参数调用该函数。

module 参数代表你通过 name/names 属性提供的 `chunk` 中的每个模块。module 具有 NormalModule 的形状,对于此用例,它有两个特别有用的属性:

  • module.context:存储文件的目录。例如:'/my_project/node_modules/example-dependency'
  • module.resource:正在处理的文件名。例如:'/my_project/node_modules/example-dependency/index.js'

count 参数表示 module 在多少个 `chunk` 中被使用。

当你希望对 `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;
  },
});

如上所示,此示例允许你在且仅在函数内部满足所有条件时,将一个库移动到单独的文件中。

此概念可用于获取隐式的公共 `vendor chunk`。

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');
  },
});

Manifest 文件

要将 webpack 的启动逻辑提取到单独的文件中,请在未定义为 entryname 上使用 CommonsChunkPlugin。通常使用 manifest 作为名称。详情请参阅 缓存指南

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

结合隐式公共 `vendor chunk` 和 `manifest` 文件

由于 vendormanifest `chunk` 对 minChunks 使用了不同的定义,你需要两次调用该插件。

[
  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,
  }),
];

更多示例

9 贡献者

bebrawsimon04christopher4liskevinzwhuangjdbevanjeremenichellibyzykmadhavarshneysnitin315