背景

最近项目更新频繁,每次一更新客户都说还跟之前的一样。一查原因是因为客户没有清空浏览器的缓存。所以为了方便客户看到最新版本,开始调研再发布新版本后自动清理缓存。

方案

每次打包后的js和css都加上hash值后缀。当文件发生改变时,hash值也改变。这样就不会走缓存

举个例子

vue.config.js

const path = require("path"); // 获取当前的时间戳
module.exports = {
  publicPath: "./",
  filenameHashing: false, 
  configureWebpack: {    
    output: { 
      filename: `js/js[name].[hash].js`, //hash可替换为contenthash 下面同理
      chunkFilename: `js/chunk.[id].[hash].js`,
    }
  },
  // css: {  这个可要可不要
  //   extract: { 
  //     filename: `css/[name].[hash].css`,
  //     chunkFilename: `css/chunk.[id].[hash].css`,
  //   }
  // }
};

上述配置中,我们使用了[hash]占位符来为文件名添加一个基于内容的哈希值。这样,每次发布新版本时,文件名会随之改变,从而强制浏览器重新下载和缓存新的文件。

注意,这种方法只适用于JavaScript文件和CSS文件。如果你想清除其他类型的缓存,如图片、字体等,可以使用workbox-webpack-plugin插件来生成Service Worker,并在其中添加缓存管理逻辑。你可以在vue.config.js文件中添加以下配置来使用该插件:

const { GenerateSW } = require('workbox-webpack-plugin');

module.exports = {
  // ...其他配置

  configureWebpack: {
    plugins: [
      new GenerateSW({
        // ...缓存管理逻辑
      })
    ]
  }
}

使用workbox-webpack-plugin需要一定的Service Worker基础知识,如果你不熟悉该插件的使用方法,建议先查阅相关文档。

相关说明

contenthash 和 hash有什么区别?

hash和contenthash都是Webpack中用于生成唯一哈希值的占位符,它们的主要区别在于生成哈希的依据不同。

hash是根据整个项目的构建情况生成的哈希值,也就是说,只要项目中任意一个文件发生变化,生成的哈希值就会发生改变。这意味着,如果你在项目中有多个入口文件或者多个chunk,那么它们都会使用同一个hash占位符,生成的哈希值也会相同。因此,hash通常用于项目的整体构建过程中,用于区分不同版本的构建结果。

contenthash则是根据文件的内容生成的哈希值,也就是说,只要文件内容发生变化,生成的哈希值就会发生改变。这意味着,如果你在项目中使用了contenthash占位符,那么每个文件都会生成独立的哈希值,不受其他文件的影响。因此,contenthash通常用于文件级别的缓存控制中,用于强制浏览器重新下载和缓存新的文件,而不是重复使用旧的缓存文件。

在实际开发中,建议根据具体需求选择合适的哈希占位符。如果你需要在整个项目构建过程中保持哈希值的一致性,可以使用hash占位符;如果你需要对每个文件进行独立的缓存控制,可以使用contenthash占位符。在Vue项目中,通常使用[contenthash]占位符来对JavaScript和CSS文件进行独立的缓存控制,从而实现自动清除缓存的效果。

图片资源如何打包添加hash值

module.exports = {
  output: {
    publicPath: '/assets/'
  },
  module: {
    rules: [
      {
        test: /\.(png|jpe?g|gif|svg)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8192,
              name: '[name].[hash:8].[ext]',
              outputPath: 'assets/'
            }
          }
        ]
      }
    ]
  }
};

在这个例子中,url-loader将所有小于等于8KB的图片资源转换成Base64编码的字符串,并将其嵌入到JavaScript或CSS文件中,而大于8KB的图片资源则会被输出到/assets目录中,并且其文件名包含哈希值,以避免浏览器缓存问题。最后,output.publicPath指定了图片资源的URL路径为/assets/。