webpack-hash-chunkhash-contenthash

hash、chunkhash、contenthash

hash

  • hash是跟项目构建挂钩的,只要项目中没有文件发生变化,hash就不会改变
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40

    const path = require('path')
    const ExtractTextPlugin = require('extract-text-webpack-plugin')
    const resolve = _path => path.resolve(__dirname, _path)
    module.exports = {
      entry: {
        main: resolve('./main.js'),
        other: resolve('./other.js')
      },
      output: {
        path: resolve('./dist'),
        filename: '[name].[hash].bundle.js'
      },
      module: {
        rules: [
          {
            test: /\.css$/,
            // 调用extract从已有的loader生成一个新的loader
            use: ExtractTextPlugin.extract({
              // 转换 .css 文件需要使用的 Loader
              use: [
                {
                  loader: 'css-loader',
                  options: {
                    url: false
                  }
                }
              ]
            })
          }
        ]
      },
      plugins: [
        // 实例化插件
        new ExtractTextPlugin({
          // 从 .js 文件中提取出来的 .css 文件的名称
          filename: `[name].[hash].css`
        })
      ]
    }

hash.png

  • 只要项目中没有文件发生变化,hash值就不会改变;反之,当有任意一个文件发生改变,hash就会发生改变
  • 这样会造成所有文件的hash都会发生变化

chunkhash

  • chunk挂钩,只要chunk中的module没有发生变化,chunkhash就不会变化
  • 每个chunk有自己独立的chunkhash,属于相同chunkmodulechunkhash也一样

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40

    const path = require('path')
    const ExtractTextPlugin = require('extract-text-webpack-plugin')
    const resolve = _path => path.resolve(__dirname, _path)
    module.exports = {
      entry: {
        main: resolve('./main.js'),
        other: resolve('./other.js')
      },
      output: {
        path: resolve('./dist'),
        filename: '[name].[chunkhash].bundle.js' // 修改为chunkhash
      },
      module: {
        rules: [
          {
            test: /\.css$/,
            // 调用extract从已有的loader生成一个新的loader
            use: ExtractTextPlugin.extract({
              // 转换 .css 文件需要使用的 Loader
              use: [
                {
                  loader: 'css-loader',
                  options: {
                    url: false
                  }
                }
              ]
            })
          }
        ]
      },
      plugins: [
        // 实例化插件
        new ExtractTextPlugin({
          // 从 .js 文件中提取出来的 .css 文件的名称
          filename: `[name].[chunkhash].css` // 修改为chunkhash
        })
      ]
    }
  • 修改main.js中代码,发现只有main chunk相关的chunkhash发生变化了,other chunk的没有发生变化
    chunkhash.png

  • 当一个.js文件引用了一个.css文件,当js文件变化时,css文件的chunkhash也会发生变化,导致缓存失效,这时需要contenthash

contenthash

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

const path = require('path')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const resolve = _path => path.resolve(__dirname, _path)
module.exports = {
  entry: {
    main: resolve('./main.js'),
    other: resolve('./other.js')
  },
  output: {
    path: resolve('./dist'),
    filename: '[name].[chunkhash].bundle.js' // 此处仍为chunkhash
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        // 调用extract从已有的loader生成一个新的loader
        use: ExtractTextPlugin.extract({
          // 转换 .css 文件需要使用的 Loader
          use: [
            {
              loader: 'css-loader',
              options: {
                url: false
              }
            }
          ]
        })
      }
    ]
  },
  plugins: [
    // 实例化插件
    new ExtractTextPlugin({
      // 从 .js 文件中提取出来的 .css 文件的名称
      filename: `[name].[contenthash].css` // 修改为contenthash
    })
  ]
}
  • 仅仅将csschunkhash改为contenthash
  • 修改main.js不会导致.css样式的contenthash发生变化
    contenthash.png
  • 修改.css文件,也仅仅是.css文件的contenthash变化,不会影响main.jschunkhash
    contenthash2.png
  • vue-cli 2.0也是使用相同策略(chunk使用chunkhashcss文件使用contenthash)
    contenthash3.png

相关项目

总结

  • css、jpg、fontasset文件可考虑使用contenthash
  • 其余文件使用chunkhash