浏览器可以使用缓存技术来降低网页流量,从而使网站加载速度更快。

但是我们在部署新版本时如果不更改资源名称,浏览器很可能认为资源没有被更新从而使用缓存版本。

我们可以通过配置,确保webpack编译生成的文件能被浏览器缓存,而文件内容发生变化后可以请求到新的文件。

1、可替换模板字符串(substitution)

利用[contenthash]可以根据资源内容创建出唯一的hash。当资源发生变化时,文件名称就会发生变化。

module.exports = {
	output: {
    filename: "[name].[contenthash].js",
  },
}

2、提取引导模板(runtime)

使用optimization.runtimeChunk将runtime代码拆分出一个独立的chunk,将其设置为single来为所有的chunk创建一个runtime bundle。

用于webpack优化。

optimization: {
    runtimeChunk: "single",
}

3、提取第三方库

一些第三方库很少修改,可以将第三方库提取到vendor chunk中。

这样可以利用浏览器的偿还村机制,命中缓存来消除请求,并减少向server获取资源。

通过设置splitChunks.cacheGroups进行设置。

optimization: {
  splitChunks: {
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all'
        }
      }
    }
}

4、模块标识符

上面的代码中我们已经将chunk分为了app.[hash].js、runtime.[hash].js、vendor.[hash].js。其中vendor chunk主要是第三方库,我们希望能够利用浏览器缓存机制缓存起来提升页面的加载速度。但是目前每次打包后vendor.[hash].js的名称都会发生变化。

  • app: 当自身内容修改后会发生变化
  • runtime(manifest) :当新增bundle时发生变化,比如在entry中新增入口,或者使用动态引入等。只要bundle出现修改就会发生变化。
  • vendor: 随自身module.id的变化而变化。webpack打包时module.id使用自增长数字,当有新增|删除module模块时,module.id就会发生变化。
  • 我们在这里不希望module.id发生变化,使用webpack提供的 HashedModuleIdsPlugin,用于生产环境构建。
const webpack = require("webpack");
module.exports = {
  plugins: [
    new webpack.HashedModuleIdsPlugin()
  ]
}

这里是对module.id进行固定。如果对chunk.id固定需要自定义插件,参考:https://zhuanlan.zhihu.com/p/34110535