以上,我们使用 webpack 来打包我们的模块化后的应用程序,webpack 会生成一个可部署的 /dist 目录,然后把打包后的内容放置在此目录中。只要 /dist 目录中的内容部署到 server 上,client(通常是浏览器)就能够访问此 server 的网站及其资源。而最后一步获取资源是比较耗费时间的,这就是为什么浏览器使用一种名为 缓存 的技术。可以通过命中缓存,以降低网络流量,使网站加载速度更快,然而,如果我们在部署新版本时不更改资源的文件名,浏览器可能会认为它没有被更新,就会使用它的缓存版本。由于缓存的存在,当你需要获取新的代码时,就会显得很棘手。

本章通过必要的配置,以确保 webpack 编译生成的文件能够被客户端缓存,而在文件内容变化后,能够请求到新的文件

1. 输出文件的文件名

我们可以通过替换output.filename中的 substitutions 设置,来定义输出文件的名称。
webpack 提供了一种使用称为 substitution(可替换模板字符串) 的方式,通过带括号字符串来模板化文件名。其中,[contenthash]substitution 将根据资源内容创建出唯一 hash,当资源内容发生变化时,[contenthash]也会发生变化

目前 webpack.config.js 中output中的配置:

  1. output: {
  2. filename: 'js/[name].bundle.js',
  3. path: path.resolve(__dirname, './dist'),
  4. clean: true
  5. }

这种配置的输出文件名有个缺陷:当我们打包后生成一个 index.bundle.js 文件,浏览器有缓存特性,会将index.bundle.js 给缓存下来。当我们修改 index.js 文件的内容后重新打包,文件名依然是 index.bundle.js ,没有发生改变,而浏览器会认为我们没有修改这个文件,就会去使用缓存,而不是修改后的文件。所以我们在打包的时候,连带文件名也要重新打包。

重新修改:

  1. output: {
  2. filename: 'js/[name].[contenthash].js',
  3. path: path.resolve(__dirname, './dist'),
  4. clean: true
  5. }

这样每次打包后都会生成不一样的 hash 文件(即文件名发生改变),浏览器就能识别出来了

2. 将 js 文件放在同一个文件夹下

  1. output: {
  2. // 指定输出文件的文件夹及文件名
  3. filename: 'js/[name].[contenthash].js'
  4. },

截止目前,我们已经把 JS 文件、样式文件及图片等资源文件分别放到了js(通过配置 output )、css(通过插件 mini-css-extract-plugin 配置)、img(通过 loader 配置)三个文件夹中

3. 缓存第三方库

将第三方库(library)(例如 lodash)提取到单独的 vendor chunk 文件中,是比较推荐的做法,这是因为它们很少像本地的源代码那样频繁修改。因此通过实现以上步骤,利用 client 的长效缓存机制,命中缓存来消除请求,并减少向 server 获取资源,同时还能保证 client 代码和 server 代码版本一致

方法:在optimization.splitChunks添加如下cacheGroups参数并构建

  1. optimization: {
  2. splitChunks: {
  3. // 缓存组
  4. cacheGroups: {
  5. vendor: {
  6. // 第三方库的文件都在 node_modules 文件夹里
  7. test: /[\\/]node_modules[\\/]/,
  8. name: 'vendors',
  9. chunks: 'all'
  10. }
  11. }
  12. }
  13. }

index.js

  1. import _ from 'lodash'
  2. console.log(_.join(['index', 'module', 'loaded!'], ' '))

执行npx webpack查看 dist :
image.png
发现第三方库已经被抽离出来,以便被浏览器缓存使用