webpack 的第三方库分离并持久化缓存

Posted 大泽队长

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了webpack 的第三方库分离并持久化缓存相关的知识,希望对你有一定的参考价值。

我们常常需要在浏览器缓存一些稳定的资源,如第三方库等。要达到这个目标,只需要两步:

1、提取出“稳定的资源”;

2、提供稳定的文件hash 。

 处理后的出的文件就像这样子: app.1w3ad4q4.js,然后,我们设置它的缓存规则为永不过期。这样,当文件没有改动时,浏览器将一直沿用第一次下载的缓存,不会浪费流量了。

详细说明:张云龙的知乎回答

 

webpack中提取公共模块一般使用 webpack 内置的  CommonsChunkPlugin 插件,他可以提取出 入口chunk中 的公共模块:

 

 

1、minChunks 参数 是指  至少有minChunks个入口引用的模块才会提取出来,“infinity“ 等价于入口数量,即所有入口都引用的模块才会提取出来;

上面的例子是一个SPA,入口是main.js。为了提取出第三方库,我们新增一个vendors入口中,并引入所有用到的第三方库,就像这样:

            

里面并没有业务代码,vendors文件只是为了引导CommonsChunkPlugin插件提取出 第三方库。

这样,我们就能将稳定的第三方库 与 不稳定的业务代码分开缓存了!~

另:看了vue-cli的源码后,发现她是这样做的

entry: {
    app: \'./src/main.js\'
}
...

new webpack.optimize.CommonsChunkPlugin({
      name: \'vendor\',
      minChunks (module, count) { // 插件会遍历所有引入的模块,传入此函数的module参数,而count是当前module的引用次数
        // any required modules inside node_modules are extracted to vendor
       return (  // 返回true则打包进vendor,否则不打包
          module.resource &&
          /\\.js$/.test(module.resource) &&
          module.resource.indexOf(
            path.join(__dirname, \'../node_modules\')
          ) === 0   // 从node_module引入的返回true
        )
     }
}),

还有这种操作!!

 

2、names 参数 传入数组的话(names: [\'vendors\', \'manifest\']),等效于 :

             

 文档的描述是:" 一个字符串数组被传入,这相当于插件针对每个 chunk 名被多次调用"

其中,从vendors中提取manifest 的操作,我查看vue-cli的配置,里面的注释是这样的 :

“extract webpack runtime and module manifest to its own file in order to prevent vendor hash from being updated whenever app bundle is updated”,

文档解释:

     但是,如果我们改变应用的代码并且再次运行 webpack,可以看到 vendor 文件的 hash 改变了。即使我们把 vendor 和 main 的 bundle 分开了,也会发现 vendor bundle 会随着应用代码改变。这意味着我们任然无法从浏览器缓存机制中受益,因为 vendor 的 hash 在每次构建中都会改变,浏览器也必须重新加载文件。 这里的问题在于,每次构建时,webpack 生成了一些 webpack runtime 代码,用来帮助 webpack 完成其工作。当只有一个 bundle 的时候,runtime 代码驻留在其中。但是当生成多个 bundle 的时候,运行时代码被提取到了公共模块中,在这里就是 vendor 文件。为了防止这种情况,我们需要将运行时代码提取到一个单独的 manifest 文件中。尽管我们又创建了另一个 bundle,其开销也被我们在 vendor 文件的长期缓存中获得的好处所抵消。"

,大意就是,如果不把manifest(运行时代码和模块清单)提取出来,只要业务代码有改动,vendors(存放提取出来的第三方库)文件的内容也会变化,也就是它的chunkhash也会改变,这不是我们想要的!

 

3、hash 与 chunkhash:

[ hash ]是webpack编译的hash值,每次编译都不一样;[ chunkhash ]则是根据文件内容计算所得的hash值,文件内容不变的话,这个值是固定的。用webpack构建时,默认是css  in  js的,即css包含在js内,webpack计算chunkhash时,整个chunk的内容会将css的内容也计算在内。所以,不论是修改了js代码还是css代码,整个chunk的内容都改变了,计算所得的chunkhash随之改变。但理想情况下是想css或js内容改变时仅影响自身文件的chunkhash,这样客户端只需更新css 或 js文件。

要解决此问题,首先要将css单独编译输出文件,并给他一个独立的extracttextplugin插件提供的 [ contenthash ] -- 根据文本内容生成的hash值

 把css提取出来并加上hash后,就可以令css单独缓存了!

 

以上是关于webpack 的第三方库分离并持久化缓存的主要内容,如果未能解决你的问题,请参考以下文章

Webpack 持久化缓存实践

webpack 持久化缓存实践

每日一读 | Webpack 持久化缓存实践

webpack性能优化2

webpack性能优化2

1分钟--前端03webpack常见优化手段