DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

Webpack 报 ERR_OSSL_EVP_UNSUPPORTED:检查 OpenSSL 与 loader 哈希链

Webpack 在 OpenSSL 3 环境报哈希算法不支持,沿堆栈核对 Webpack 与 loader,区分 xxhash64 配置范围、依赖升级和临时 legacy provider。

Webpack 构建在 crypto.createHash 附近失败,提示 error:0308010C:digital envelope routines::unsupported 或 ERR_OSSL_EVP_UNSUPPORTED。如果堆栈进入旧版 Webpack、loader 或哈希工具,应先检查它请求的算法,以及这次 Node.js 实际使用的 OpenSSL 版本。

常见的一条路径是旧构建链请求 MD4,而 OpenSSL 3 的默认提供程序不再支持这项旧算法。这个错误也可能涉及其他受限算法或密钥条件,不能只凭错误码就断言一定是 MD4。

不只看 Node.js 的大版本

在失败的构建环境查看以下只读信息:

node --version
node -p "process.versions.openssl"
npm ls webpack loader-utils file-loader

官方 Node.js 17 开始采用 OpenSSL 3,但 Linux 发行版可能以不同方式编译或打包 Node。因此,不能把“Node 16”当成必然没有这项问题的证据。检查结果必须来自真正执行构建的进程环境,而非个人电脑上的另一个 Node。

接着沿完整异常堆栈定位请求算法的包。进入 Webpack 的 createHash,与进入 loader-utils 的 getHashDigest,需要检查的配置层可能不同。项目通过框架隐藏了 Webpack 配置时,也要查框架实际锁定的版本;全局安装新版 Webpack不会自动替换项目构建链。

优先更新有问题的构建依赖

保存 package.json、锁文件、Node 版本配置及上一份可部署产物,在独立工作目录中按框架支持范围更新构建工具。目标是让实际调用哈希的依赖支持当前运行环境,不能只升级一个顶层包,再忽略它下面的 loader。

若项目允许直接设置 Webpack 输出哈希,Webpack 5.54.0 及以后支持 xxhash64。下面是应合并到现有配置的局部示例:

module.exports = {
  output: {
    hashFunction: 'xxhash64'
  }
};

不要用这个片段覆盖原来的 entry、plugins 或其他 output 属性。该选项控制相应的 Webpack 哈希行为,不保证所有旧插件和 loader 都跟随它。修改后堆栈仍进入另一个包,就继续核对那个包的哈希选项或兼容更新,不能把“配置里已有 xxhash64”当作整个依赖树已修复的证明。

旧版 Webpack、框架限制或其他 loader 使用不同配置接口时,先核对对应版本支持范围。改变算法也会改变构建哈希和文件名,部署时要让 HTML、清单与静态资源来自同一份产物,避免缓存继续引用旧文件。

legacy provider 只能是临时兼容措施

Node 的 --openssl-legacy-provider 可以启用 OpenSSL 旧提供程序,让某些受限算法重新可用。它改变的是启动该 Node 进程的加密能力,不会更新依赖,也不是浏览器设置或 TLS 证书修复。

必须暂时维持旧构建、且运行环境支持并允许该选项时,可以按项目构建入口为单次进程配置它,记录撤除计划。不要把它永久写入所有终端的全局 NODE_OPTIONS,也不要为了绕过错误切回已经停止维护的 Node 版本。选项不被当前发行版支持时,更不能强行假定它生效。

直接搜索替换 node_modules 中全部 md4 字符串,会留下难以审查且重新安装后丢失的修改;修改全局 crypto.createHash 也可能影响无关代码。这些办法不适合作为可重复构建的长期维护方案。

用原构建入口验收

完成依赖或配置调整后,在原来失败的环境执行项目既有构建任务,确认相关哈希调用不再报错,再检查产物、资源引用和关键页面。一次简化哈希调用成功,不代表整个构建链已经通过。

若曾使用临时 legacy provider,在更新后撤除并重新构建;只有撤除后仍能完成,才证明不再依赖这项兼容开关。需要回退时恢复此前确认可用的依赖清单、锁文件和运行环境,并部署整份旧产物,而不是只恢复某一个 JavaScript 文件。