在 webpack 2 中混合长期缓存和代码拆分

我正在编写一个使用 webpack 2 作为模块捆绑器的 javascript webapp.

I'm writing a javascript webapp using webpack 2 as module bundler.

我需要的是一种混合长期缓存功能的方法(https://webpack.js.org/guides/caching/)和代码拆分(https://webpack.js.org/guides/code-splitting/).

What I need is a way to mix long term caching feature (https://webpack.js.org/guides/caching/) and code splitting (https://webpack.js.org/guides/code-splitting/).

我可以使用 require.ensure 延迟加载供应商库(在我的情况下为 pixi.js),但这会导致创建包含库的包.我也可以创建可缓存的包,但我想创建一个用于长期缓存的包并在延迟加载部分使用它.

I'm able to lazy load a vendor library (pixi.js in my case) using require.ensure but this cause a bundle creation including the lib. I'm also able to create cachable bundles, but I would like to create a bundle for long term caching and use it in lazy loaded part.

有可能吗?

编辑 1

我添加了我的配置的一些部分以获得更好的解释.

I add some parts of my config for a better explanation.

entry: {
  vendor: ['some', 'vendors', 'libs'],
  pixi: ['pixi.js'],
  main: ['babel-polyfill', './app/index.js'],
},
output: {
  [... other configuration]
  filename: '[name].[chunkhash].bundle.js',
  chunkFilename: '[name].[chunkhash].js'
},

我将供应商捆绑包用于启动时所需的外部库,但 pixi.js 仅在某些情况下需要,但我希望长期缓存.

I'm using the vendor bundle for external libraries needed at startup time, but the pixi.js is only needed in some cases, but I would like to be long term cached.

捆绑阶段发出这 2 个文件(以及许多其他文件):

The bundling phase emit this 2 files (and many others):

pixi.8ef3aeac142f1bf921bf.bundle.js6.9331d810904191781167.js

它们的内容几乎相同.第二个是由 require.ensure 创建的,但我希望使用 pixi.8ef3aeac142f1bf921bf.bundle.js.

their content is almost the same. The second one is created by the require.ensure but I would like the pixi.8ef3aeac142f1bf921bf.bundle.js was used.

推荐答案

使用 require.ensure 生成不同的代码块,该代码块将构建在不同的文件中.您想要提供的缓存类型与您为这些捆绑包提供的命名策略有关(当然还有您的服务器配置).

Using require.ensure produce a different code chunk that will be built in a different file. The kind of cache you want to offer is about the naming policy you give to those bundles (and your server configuration of course).

你要找的参数是chunckFilename.

output: {
  chunkFilename: '[name].chunk.js',
}

如果您这样设置,您将始终拥有名为 0.chunk.js1.chunk.js 等的预先确定的块.

If you set it like this you will always have predeterminated chuncks named 0.chunk.js, 1.chunk.js, etc..

当然这会给客户端带来问题,所以你想配置这个参数如下:

Of course that can pose a problem for clients, so you would like to configure this parameter as follows:

output: {
  chunkFilename: '[name].[chunkhash].chunk.js',
}

将 chunkhash 添加到您的块名称中将为您提供 0.4c473bca1d7688737499.chunk.js1.2cfbf4a9cc0e1f24ec2c.chunk.js 等一种块名称.

Adding chunkhash to the name of your chunk will give you 0.4c473bca1d7688737499.chunk.js, 1.2cfbf4a9cc0e1f24ec2c.chunk.js, etc kind of chunk names.

对于不更改块代码的每个应用程序构建,块哈希都是相同的.这意味着,如果您从不更改库,则 chunkhash 将永远不会更改,因此用户将永远不必再次重新下载该文件.

The chunkhash is identical for each application build that doesn't change the chunck code. That means that if you never change your library, the chunkhash will never change, thus the user will never have to re-download that file again.

如果您想确保块始终具有相同的名称,那么您可以在 require.ensure 声明中指定名称:

If you want to ensure the chunk to always have the same name, then you can specify the name on the require.ensure declaration:

require.ensure([], function(require){
  var pixi = require('pixi');
  // ...
}, "pixi"); // this will be passed webpack template under [name] and can be used with chunkFilename

我个人建议对包命名采用相同的方法:

I personally suggest the same approach for bundles naming:

output: {
  /**
   * Specifies the name of each output file on disk.
   * IMPORTANT: You must not specify an absolute path here!
   *
   * See: https://webpack.js.org/configuration/output/#output-filename
   */
  filename: '[name].[hash].bundle.js',

  /** The filename of non-entry chunks as relative path
   * inside the output.path directory.
   *
   * See: https://webpack.js.org/concepts/output/#output-chunkfilename
   */
  chunkFilename: '[name].[chunkhash].chunk.js',
}

相关文章