前言
在现代前端项目中,构建工具(如 Webpack、Vite、Rollup)都会为打包输出的文件生成带有哈希值的文件名,例如:
bundle.4a8f2d.js style.73a0de.css
这些 hash 值不仅是随机字符串,而是前端性能优化的重要组成部分。
它们的核心作用是:
✅ 实现浏览器缓存的精准控制(Cache Busting) ✅ 提高缓存命中率,减少重复加载
但当我们在配置中看到 [hash]、[contenthash]、[chunkhash] 时,很多人会迷惑:这些到底有什么区别?Vite 里也有类似的 hash 吗?
一、为什么需要 hash?
当浏览器加载静态资源(JS、CSS、图片)时,通常会缓存它们。这在性能上是好事,但也会带来一个经典问题:
❌ 文件更新了,但浏览器还在用旧缓存。
为了解决这个问题,我们给文件名添加哈希后缀:
main.83a6d2.js
当文件内容发生变化时,构建工具会生成新的 hash 值:
main.93b7e4.js
于是浏览器就会重新请求新文件,保证拿到最新版本。这就是所谓的缓存破坏(Cache Busting)机制。
二、在 Webpack 中的三种哈希类型
Webpack 提供了三种占位符,它们代表不同粒度的哈希策略:
| 占位符 | 含义 | 更新范围 |
|---|---|---|
[hash] | 整个构建的哈希 | 任意文件变动都会引起所有文件 hash 变化 |
[chunkhash] | 基于 chunk 的哈希 | 仅当前入口及依赖变动时更新 |
[contenthash] | 基于内容的哈希 | 仅当文件内容变化时更新(最精细) |
1. [hash]:全局构建级别
output: {
filename: "bundle.[hash].js"
}
任意文件(JS、CSS、图片)变动,都会让所有输出文件的 hash 全部更新。
适用场景: 开发环境(每次构建都重新加载无所谓) 不适合生产: 缓存命中率太低。
2. [chunkhash]:按入口粒度更新
output: {
filename: "bundle.[chunkhash].js"
}
当某个入口文件(chunk)内容变化时,只更新该 chunk 的文件。但它仍可能受到其他依赖的影响(尤其是公共模块)。


