Hash vs ChunkHash vs ContentHash

Webpack 三种哈希策略的区别与使用场景

问题

Webpack 中 hashchunkhashcontenthash 有什么区别?分别在什么场景使用?

解答

这三种 hash 都用于生成文件名中的哈希值,实现浏览器缓存控制。

hash

整个项目构建的哈希值,所有文件共享同一个 hash。任意文件修改,所有文件的 hash 都会变化。

// webpack.config.js
module.exports = {
  output: {
    filename: '[name].[hash].js'
  }
}

问题:改一个文件,所有文件缓存都失效。

chunkhash

基于 chunk 内容生成的哈希值。同一入口的文件共享一个 chunkhash。

// webpack.config.js
module.exports = {
  entry: {
    main: './src/index.js',
    vendor: './src/vendor.js'
  },
  output: {
    filename: '[name].[chunkhash].js'
  }
}

问题:JS 和从中提取的 CSS 共享同一个 chunkhash,改 JS 会导致 CSS 缓存失效。

contenthash

基于文件内容生成的哈希值。只有文件内容变化,hash 才会变。

// webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = {
  output: {
    // JS 文件用 chunkhash 或 contenthash
    filename: '[name].[contenthash].js'
  },
  plugins: [
    new MiniCssExtractPlugin({
      // CSS 文件用 contenthash
      filename: '[name].[contenthash].css'
    })
  ]
}

完整配置示例

// webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = {
  entry: {
    main: './src/index.js'
  },
  output: {
    // JS 使用 contenthash
    filename: '[name].[contenthash:8].js',
    // 异步 chunk
    chunkFilename: '[name].[contenthash:8].chunk.js'
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader']
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      // CSS 使用 contenthash
      filename: '[name].[contenthash:8].css'
    })
  ],
  optimization: {
    // 将 runtime 代码单独提取,避免影响业务代码 hash
    runtimeChunk: 'single',
    // 提取公共模块
    splitChunks: {
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all'
        }
      }
    }
  }
}

对比表格

类型作用范围变化条件适用场景
hash整个项目任意文件变化开发环境
chunkhash同一 chunkchunk 内容变化JS 文件
contenthash单个文件文件内容变化CSS、图片等资源

关键点

  • hash 粒度最粗,整个项目共享,不适合生产环境
  • chunkhash 基于入口 chunk,JS 和提取的 CSS 会共享同一个 hash
  • contenthash 粒度最细,只与文件内容相关,缓存利用率最高
  • 生产环境推荐:JS 用 contenthash,CSS 用 contenthash
  • 配合 runtimeChunksplitChunks 可进一步优化缓存策略