以上,我们使用 webpack 来打包我们的模块化后的应用程序,webpack 会生成一个可部署的 /dist 目录,然后把打包后的内容放置在此目录中。只要 /dist 目录中的内容部署到 server 上,client(通常是浏览器)就能够访问此 server 的网站及其资源。而最后一步获取资源是比较耗费时间的,这就是为什么浏览器使用一种名为 缓存 的技术。可以通过命中缓存,以降低网络流量,使网站加载速度更快,然而,如果我们在部署新版本时不更改资源的文件名,浏览器可能会认为它没有被更新,就会使用它的缓存版本。由于缓存的存在,当你需要获取新的代码时,就会显得很棘手。
此指南的重点在于通过必要的配置,以确保 webpack 编译生成的文件能够被客户端缓存,而在文件内容变化后,能够请求到新的文件。
输出文件的文件名(output filename)(这里和版本号的原理差不多,通过contenthash改为文件名可以被更新)
我们可以通过替换 output.filename 中的 substitutions 设置,来定义输出文件的名称。webpack 提供了一种使用称为 substitution(可替换模板字符串) 的方式,通过带括号字符串来模板化文件名。其中,[contenthash] substitution 将根据资源内容创建出唯一 hash。当资源内容发生变化时,[contenthash] 也会发生变化。
这里使用 起步 中的示例和 管理输出 中的 plugins 插件来作为项目基础,所以我们依然不必手动地维护 index.html 文件:

提取引导模板(extracting boilerplate)
正如我们在 代码分离 中所学到的,SplitChunksPlugin 可以用于将模块分离到单独的 bundle 中。webpack 还提供了一个优化功能,可使用 optimization.runtimeChunk 选项将 runtime 代码拆分为一个单独的 chunk。将其设置为 single 来为所有 chunk 创建一个 runtime bundle:
下面代码可以提取公共模块,生成一个 runtime bundle,这样做可以去除重复引用的问题
optimization: { runtimeChunk: 'single', },
将第三方库(library)(例如 lodash 或 react)提取到单独的 vendor chunk 文件中,是比较推荐的做法,这是因为,它们很少像本地的源代码那样频繁修改。因此通过实现以上步骤,利用 client 的长效缓存机制,命中缓存来消除请求,并减少向 server 获取资源,同时还能保证 client 代码和 server 代码版本一致。 这可以通过使用 SplitChunksPlugin 示例 2 中演示的 SplitChunksPlugin 插件的 cacheGroups 选项来实现。我们在 optimization.splitChunks 添加如下 cacheGroups 参数并构建:
这段代码是将上面引用到的 node_modules 中的模块提取到 common bundle中, 重复的引用提取到 runtime bundle中, 目的是这些不经常改动的库可以做一个缓存
optimization: { runtimeChunk: 'single', splitChunks: { cacheGroups: { vendor: { test: /[\\/]node_modules[\\/]/, name: 'common', chunks: 'all', }, }, }, },
现在,我们可以看到 main 不再含有来自 node_modules 目录的 vendor 代码,并且体积减少

将node_modules模块提取到 common bundle中,做个缓存,以后不用每次再拉一边

模块标识符(module identifier)

防止更改一个一个文件,所有文件的hash值都刷新,以至于都拉一遍,这样缓存就没有多大的意义了。

浙公网安备 33010602011771号