6. 什么是哈希碰撞
约 871 字大约 3 分钟
2025-06-20
哈希如何生成的
Webpack 生成哈希值的过程可以简化为以下关键步骤:
内容准备阶段
- 收集目标文件的所有内容(包括代码和依赖关系)
- 对模块内容进行标准化处理(移除空格/注释等不影响功能的差异)
哈希计算阶段
// 简化的哈希计算逻辑
const crypto = require("crypto");
function generateHash(content) {
return crypto
.createHash("md5") // 使用MD5算法
.update(content) // 输入内容
.digest("hex") // 输出16进制格式
.substring(0, 8); // 取前8位作为短哈希
}
输出应用阶段
- 将生成的哈希插入文件名:
main.[hash].js
→main.a1b2c3d4.js
- 不同哈希类型区别:
[hash]
:基于整个构建[chunkhash]
:基于代码块内容[contenthash]
:基于文件完整内容
典型示例:
- 文件内容:
console.log("Hello")
- 计算 MD5:
2ef7bde...
(完整哈希) - 截取使用:
2ef7bde8
- 生成文件:
main.2ef7bde8.js
什么是哈希碰撞
哈希碰撞是指两个文件根据文件特征计算出的哈希值相同。如果文件本身重名,可能会导致严重的缓存和版本管理问题。
如果文件内容相同,一定会产生哈希碰撞,但是一般不会影响代码运行。
如果内容不相同,产生哈希碰撞的概率极低,如果遇到了,就可能会导致代码运行出错。
哈希碰撞的危害
哈希碰撞主要影响 Webpack 的 emitAssets
阶段,这个阶段会输出 bundle 到指定目录下。这时候如果遇到了完全同名的 bundle,可能会发生 内容覆盖 的现象,即 后生成的 bundle 会覆盖之前生成的 bundle,最终只剩下一份。如果这些 bundle 的内容不相同,就意味着依赖这些 bundle 的代码在运行时可能会出现非常严重的问题。
如何解决
主要解决办法就是尽量避免生成相同的 bundle,可以通过以下方法:
使用更复杂的哈希算法
可以指定 webpack 使用更复杂的哈希算法:例如 SHA-256、SHA-512 等。这些算法的哈希值复杂度更高、长度更长、碰撞的概率也更低。
修改哈希算法的生成策略
contenthash
:根据文件内容计算的哈希值,所以文件内容不同,contenthash
也不同,不会产生哈希碰撞。chunkhash
:根据文件内容计算的哈希值,但是它是根据文件所属的代码块(chunk)来计算的,所以如果文件所属的代码块内容不同,chunkhash
也不同,不会产生哈希碰撞。
修改哈希值长度
// 根据文件体积自动调整哈希位数
output: {
filename: '[name].[contenthash:auto].js', // 体积>1MB → 16位
assetModuleFilename: '[name].[hash:12][ext]' // 12 位 Hash
}
人工加盐
在 bundle 的文件名中加入一些变化的字符串,如 文件的 size、时间戳,这样即使文件内容完全相同,哈希值也会不同,从而避免哈希碰撞。
// 采用 12 位哈希 + 时间戳双校验
filename: `[name].[contenthash:12].${Date.now()}.[ext]`;
使用 plugin 插件检测
可以通过插件来获取并临时保存构建过程中产生的 bundle 信息,在构建过程中随时比对,发现有重复的 bundle 就报错,或者重新生成一个新的 bundle 名称。
更新日志
2025/8/24 08:17
查看所有更新日志
e7112
-1于