Webpack中文:
缓存 | webpack 中文文档

缓存的场景

  1. import _ from "lodash";
  2. import $ from "jquery";
  3. const dom = $("<div>");
  4. dom.html(_.join(["dell", "less"], ","));
  5. $("body").append(dom)
  1. // ...
  2. module.exports = {
  3. // ...
  4. optimization: {
  5. // TreeShaking 的配置
  6. usedExports: true,
  7. // SplittingCode 的配置
  8. splitChunks: {
  9. // 分割引入代码库的方式,默认为 async 异步,可选 all:同步和异步
  10. chunks: 'all',
  11. cacheGroups: {
  12. vendors: {
  13. test: /[\\/]node_modules[\\/]/,
  14. priority: -10,
  15. name: "chunk"
  16. }
  17. }
  18. },
  19. },
  20. // ...
  21. }

当前npm run build打包生成的文件:
image.png

假设现在把dist文件放到了服务器中,页面加载了三个文件,就在此时可恶的产品经理提需求了说:给我把字符串用~拼接并且加上Hello Word
image.png
接着我们去修改源代码代码:

  1. import _ from "lodash";
  2. import $ from "jquery";
  3. const dom = $("<div>");
  4. dom.html(_.join(["dell", "less","Hello Word"], "~"));
  5. $("body").append(dom)

这个时候我们将修改后的代码部署到了服务器,然后用户继续访问页面且进行刷新看到的内容可能还是dell,less ,这是因为我们生成的新的js文件名没有更改,浏览器的缓存机制认为我们的文件没有更新内容,则直接从缓存中读取js文件,用户刷新页面依然请求的是缓存的js文件,这样就会导致内容不同步的问题。

如何解决

只需要给生产环境的配置文件的产生文件名加上contenthash值就可以了:

  1. const { merge } = require("webpack-merge");
  2. const commonConfig = require("./webpack.common.js");
  3. const prodConfig = module.exports = {
  4. output: {
  5. // 当文件内容发生改变后 contenthash 会产生一个新的 hash 值,否则不会改变。
  6. filename: "[name].[contenthash].js",
  7. },
  8. // ...
  9. }
  10. module.exports = merge(commonConfig, prodConfig);

到现在我们可以使用contenthash的方式去设置文件名重新命名,当src/index.js文件内容方式了变化就会重新命名main.contenthash.js
当用户浏览网站时,index.html发现mian.contenthash.js文件发生了变化就会重新到服务器请求新的内容,而chunk.contenthash.js文件因为是第三方代码库我们没有更改所以浏览器则可以继续使用缓存的chunk.contenthash.js文件。

补充

假设老版本的Webpack配置了filename: "[name].[contenthash].js" 没有改变js文件内容依然产生了不同的hash值的时候需要额外添加一个配置

  1. // ...
  2. module.exports = {
  3. optimization: {
  4. runtimeChunk: {
  5. name: 'runtime'
  6. },
  7. // CSS代码压缩
  8. minimizer: [
  9. new CssMinimizerPlugin(),
  10. ],
  11. }
  12. }

此时就可以实现老版本 filename: "[name].[contenthash].js",但是你会发现dist目录下多了一个runtime.[contenthash].js的文件,这是因为runtimesrc/index.jsloadsh的关联到这个文件中。