webpack 中的 hash、chunkhash、contenthash 区别

3/2/2021 Webpack

# 问题背景

修改代码后,重新打包发布代码之后,打开页面之后控制台有些 css 文件会出现 404,如下图所示:

图片

需求: 如果当前文件没有改变,则每次打包之后对应文件的哈希值不会改变。

# hash 的应用

hash 一般结合 CDN 缓存来使用,通过 webpack 构建之后,生成对应文件名自动带上对应的 MD5 值。如果文件内容改变,对应文件的哈希值也会发生改变,对应的 HTM 引用的 URL 地址也会改变,触发 CDN 服务器从源服务器上拉取对应数据,进而更新本地缓存。

# hash、chunkhash、contenthash 的区别

  • hash

    hash 是跟整个项目的构建相关,只要项目里有文件更改,整个项目构建的 hash 值都会更改,并且全部文件都共用相同的 hash 值。使用 hash,每次构建生成的哈希值都不一样, hash

  • chunkhash

    chunkhash 根据不同的入口文件(Entry)进行依赖文件解析,构建对应的 chunk、生成对应的哈希值,在生产环境里把一些公共库和程序入口文件区分开,打包构建,不改公共库的代码,可以保证哈希值不受影响。
    

    hash)

    我们可以看到,由于采用 chunkhash,所以项目主入口文件 main.js 及其对应的依赖文件 man.css 由于被打包在同一个模块,所以共用相同的 chunkhash,但是公共库由于是不同的模块,所以有单独的 chunkhash。这样子就保证了在线上构建的时候只要文件内容没有更改就不会重复构建.
    问题:由于 main.css 被 main.js 引用了,所以共用相同的 chunkhash 值。但是这样子有个问题,如果 mian.js 更改了代码,css 文件就算内容没有任何改变,由于是该模块发生了改变,导致 css 文件会重复构建。
    
  • contenthash 和单个文件的内容相关,使用 contenthash 值,只要当前文件内容不变,那么不会重复构建,生成的相应文件哈希值也是一样。

# file-loader 的 hash

字体的 file-loader 的打包时,使用的是[name]_[hash:8].[ext]但是如果改了其他工程文件,比如 index.js,生成的图片 hash 并没有变化。这里需要注意的是,file-loader 的 hash 字段,这个 loader 自己定义的占位符,和 webpack 的内置 hash 字段并不一致。这里的 hash 是使用 md4 等 hash 算法,对文件内容进行 hash。

所以只要文件内容不变,hash 还是会保持一致。

{
    test: /\.(png|svg|jpg|gif)$/,
    use: [
        {
            loader: 'file-loader',
            options: {
                // limit: 5000,
                name: 'imgs/[hash].[ext]',
            },
        },
    ],
},
1
2
3
4
5
6
7
8
9
10
11
12
上次更新: 3/22/2021, 3:28:01 PM