原稿:语雀 · 缓存 · 原目录:Webpack › 官方指南学习 › 缓存

本篇的代码使用 webpack doc:缓存提供的 demo

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

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

输出文件名

可以通过替换 output.filename 中的 substitutions 设置,定义输出文件的名称

webpack 提供了一种使用称为 substitution(可替换模板字符串) 的方式,通过带括号字符串来模板化文件名。其中,

contenthashcontenthash

substitution 将根据资源内容创建出唯一 hash。当资源内容发生变化时,

contenthashcontenthash

也会发生变化。

修改配置文件

output: {
  filename: "[name].[contenthash].js",
    path: path.resolve(__dirname, "dist"),
},

执行 build 后,可以看到 bundle 的名称是其内容(通过 hash)的映射,当内容不修改时,即便再次 build 也不会改变 hash 值,保证了文件名的唯一

image.png

提取引导模板

extracting boilerplate

  • 在代码分离中使用了 SplitChunksPlugin 插件,将公共的依赖模块提取到已有的入口 chunk 中,或者提取到一个新生成的 chunk
  • webpack 还提供了一个优化功能,可使用 optimization.runtimeChunk 选项将 runtime 代码拆分为一个单独的 chunk。将其设置为 single 来为所有 chunk 创建一个 runtime bundle,构建后,可以看到提取出来的 runtime bundle。
image.png

通常推荐将第三方库(library)(例如 lodash 或 react)提取到单独的 vendor chunk(第三方块)中,因为它们很少像本地代码频繁修改。这样可以高效利用 client 的长效缓存机制,命中缓存来消除请求,并减少向 server 获取资源,同时还能保证 client 代码和 server 代码版本一致

这种模式可以通过 SplitChunksPlugin 插件的 cacheGroups 选项来实现

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

再次 build,此时 index 的大小明显缩小,其中不再含有来自 node_modules 目录的 vendor 代码,vendor 块被单独生成

image.png

模块标识符

重新添加 print.js 模块,重新构建

image.png

因为

  • main bundle 会随着自身的新增内容的修改,而发生变化
  • vendor bundle 会随着自身的 module.id 的变化,而发生变化
  • manifest runtime 会因为现在包含一个新模块的引用,而发生变化

当只新增了本地依赖,因此触发第一和第三项变化,重新编译后生成新的 hash