Webpack 在构建过程中提供了三种类型的哈希值:hash、chunkhash 和 contenthash。这些哈希值用于版本控制,帮助浏览器识别文件内容是否发生变化,从而决定是否需要下载新文件或可以使用缓存。
hash
hash 是基于整个项目构建的,这意味着项目中的任何一个文件发生变化,所有文件的 hash 值都会改变。
虽然 hash 对于每次构建都唯一,但它不适合用于长期缓存,因为任何一个文件的改动都会导致所有文件的哈希值变化,从而使得缓存失效。如果你的项目较小,或者你不太关心客户端缓存的问题,可以使用 hash。但在大多数生产环境中,更推荐使用下面两种哈希值。
当在 Webpack 配置中使用 hash 作为文件名的一部分时,确实只会生成一个唯一的 hash 值,用于该次构建的所有文件。这意味着在一次构建中,所有输出文件的 hash 值都将相同。这个 hash 值是基于整个构建过程生成的,因此任何源文件的变化都会导致新的构建拥有一个不同的 hash 值。
js
output: {
filename: '[name].[hash].js',
}
当我们修改项目中的代码,你会发现 webpack 的输出有如下图所示:
结果为只有一个 hash,所有文件的 hash 都相同。
当我们再次修改代码时,你会发现 hash 值又发生了变化了:
对比发现他们的 hash 都发生了改变,此时如果想修改 App.tsx,而 home 目录下的 index.tsx 不改变,则需要用到 chunkhash 。
chunkhash
chunkhash 是基于每个 chunk 的,Webpack 会为构建结果中的每个 chunk 生成一个哈希值。如果 chunk 的内容发生变化,那么这个 chunk 的 chunkhash 也会改变。
chunkhash 适合用于那些将代码分割成多个 chunk 的项目(如使用代码分割、懒加载等技术)。它可以更细粒度地控制缓存,因为只有改变了的 chunk 会失去缓存。
在使用 Webpack 进行代码分割时,推荐使用 chunkhash,因为它能够有效地利用浏览器缓存,只有改动的 chunk 会被重新下载。
如下配置所示:
这个时候我们运行 webpack,这是第一次运行的输出,如下图所示:
当我们修改 App.tsx 的时候,我们再次查看控制台终端:
根据图片我们发现, home 目录下的 index.tsx 的哈希值并没有变化,达到了我们的预期。
通过这个例子我们可以知道 chunkhash 只有更改内容的 chunk 会失去缓存,未更改的 chunk 可以继续从缓存中加载,提高了网页的加载速度。相比于 hash,chunkhash 提供了更细粒度的控制,允许对每个 chunk 单独缓存管理,而不是整个项目。
contenthash
contenthash 是针对文件内容的,由文件内容本身生成的哈希值。如果文件内容没有变化,即使其他文件发生变化,contenthash 也不会改变。
contenthash 特别适合用于样式文件(如 CSS)或者你的项目中任何可以独立缓存的资源。它确保了只有内容实际发生变化的文件才会更新其哈希值。在处理 CSS 或其他被提取出的资源文件时,使用 contenthash 是最佳实践。这样,只有当特定的样式文件发生变化时,用户浏览器才需要下载新的文件版本。
与 hash 和 chunkhash 相比,contenthash 提供了更细粒度的控制,允许更精确地管理应用的缓存策略。
参考资料
总结
hash 所有文件的哈希值都相同;chunkhash 根据不同的入口文件进行依赖文件解析,构建对应的 chunk,生成对应的哈希值;contenthash 计算与文件内容本省有关,主要用于 CSS 抽离 CSS 文件。