error:0308010C digital envelope routines::unsupported 怎么解决?Node 17+ 跑老项目的三种修法
现象:项目昨天还能跑,今天 npm run dev 直接炸
Error: error:0308010C:digital envelope routines::unsupported
at new Hash (node:internal/crypto/hash:71:19)
at Object.createHash (node:crypto:130:10)
at BulkCacheDecorator.cheaderHash (...) ← webpack 4 内部调用栈
一行结论:你的 Node 版本升到 17+ 了,而项目里的 webpack 4 还在用 OpenSSL 3.0 已移除的 MD4 哈希算法。这不是你的代码有 bug,是运行环境和新版 Node 的不兼容。
常见触发场景:
- 换了新电脑 / 重装系统,
nvm默认装了最新 LTS(Node 18/20/22) - CI 服务器基础镜像升级(
node:16→node:20) - Dockerfile 里
FROM node:latest - 接手别人的老项目(Vue CLI 4、create-react-app 4、 webpack 4)
根因:OpenSSL 3.0 与 MD4
Node 17 起捆绑 OpenSSL 3.0。OpenSSL 3.0 把 MD4 这类老旧算法挪进了「legacy provider」(遗留算法提供者),默认不加载。而 webpack 4 生成模块 hash 用的是 crypto.createHash('md4')——于是第一次调用就抛错。
注意看报错第一行的错误码 0308010C,这就是 ERR_OSSL_EVP_UNSUPPORTED 的十六进制表示。受影响的不只是 webpack 4:一些老版本的 grunt、gulp-rev、crypto-js 老版本也会踩中。
修法一:开启 legacy provider(5 分钟解阻塞)
给 Node 进程加 --openssl-legacy-provider 参数,把 MD4 重新放进来:
# macOS / Linux
export NODE_OPTIONS=--openssl-legacy-provider
npm run dev
# Windows CMD
set NODE_OPTIONS=--openssl-legacy-provider
# Windows PowerShell
$env:NODE_OPTIONS="--openssl-legacy-provider"
更稳妥的做法是写进 package.json,跨平台可用(需要安装 devDependency cross-env):
{
"scripts": {
"dev": "cross-env NODE_OPTIONS=--openssl-legacy-provider vue-cli-service serve",
"build": "cross-env NODE_OPTIONS=--openssl-legacy-provider vue-cli-service build"
}
}
适用判断:项目还剩几个月生命周期、或你只是临时接手——用这个最快。缺点:MD4 已被视为不安全哈希,等于延续技术债;且 Node 22+ 上该参数依旧有效,但总有一天你要面对升级。
修法二:升级到 webpack 5(根治)
| 项目类型 | 升级路径 |
|---|---|
| Vue CLI 4 项目 | vue upgrade 升到 Vue CLI 5(内置 webpack 5) |
| CRA 4 项目 | 迁移到 CRA 5,或直接迁 Vite |
| 自维护 webpack 4 配置 | npm i webpack@5 webpack-cli@4 -D 后逐项处理 breaking changes |
webpack 5 的 hash 默认改用 xxhash64/sha256,与 OpenSSL 3 完全兼容。同时你会得到更快的产品构建(持久化缓存)。
升级后高频报错:PolyfillPlugin 相关的 assert/process 找不到——webpack 5 不再自动 node polyfill,需要按报错逐个 resolve.fallback 或引入对应 npm 包。
修法三:锁定 Node 16(过渡方案)
nvm install 16
nvm use 16
node -v # v16.x
在仓库根目录加 .nvmrc:
16
CI 和 Dockerfile 同步锁版本:
FROM node:16-alpine
注意:Node 16 已于 2023 年 9 月停止维护,不再收安全补丁。只建议作为「升 webpack 5 之前的过渡」,不建议长期停留。
三种方案怎么选
| 方案 | 成本 | 风险 | 适用 |
|---|---|---|---|
| --openssl-legacy-provider | 5 分钟 | 低(仅本进程) | 快速解阻塞、老项目维稳 |
| 升级 webpack 5 | 0.5~3 天 | 中(构建行为差异) | 项目还要长期维护 |
| 锁定 Node 16 | 10 分钟 | 高(无安全补丁) | CI 复现、等升级排期 |
预防:把 Node 版本钉死在项目里
这类问题的本质是运行环境漂移。三道防线:
.nvmrc+package.json的engines字段双保险:
{
"engines": { "node": ">=18 <19" }
}
- CI 里开严格校验(
.npmrc加engine-strict=true),Node 版本不符直接 fail,而不是带病跑出诡异的错; - Dockerfile 永远不用
node:latest,写具体大版本号。
排查清单
node -v— 是否 ≥17?项目 webpack 版本npm ls webpack是否为 4.x?- 报错含
0308010C/digital envelope routines— 确认是本问题 - 急救:
NODE_OPTIONS=--openssl-legacy-provider先跑起来 - 排期升级 webpack 5,或
.nvmrc锁 16 过渡 - 复查
.nvmrc、engines、Dockerfile 三处 Node 版本一致性
本文由 ToolVault 工具匣 提供。相关阅读:npm 依赖冲突 ERESOLVE 排查、npm 网络问题换源指南、Cannot find module 排查。访问 首页 查看更多开发者工具。
相关工具
相关文章
Permission denied (publickey) 怎么解决?Git 推送失败的 6 种原因与修复
git clone/push 报 Permission denied (publickey) fatal: Could not read from remote repository?覆盖公钥没生成、没加载进 agent、没添加到 GitHub/Gitee、多账号配错密钥、deploy key 权限、remote URL 写错六种根因,附 ssh -v 诊断方法。
npm ERR! ERESOLVE:peer dependency 冲突的四种解决策略
npm install 报 ERESOLVE unable to resolve dependency tree 怎么办?理解 peer dependency 的设计意图,掌握四种解决策略(版本修复 / legacy-peer-deps / overrides / dedupe)及其适用场景与风险。
ECONNREFUSED 连接被拒绝怎么排查?5 种原因一次讲清(含 Docker 场景)
Node/Java/curl 报 connect ECONNREFUSED 127.0.0.1:3306 怎么办?含义是目标端口上没有任何进程在监听。覆盖服务未启动、端口记错、只监听 127.0.0.1、Docker 容器互连、防火墙五种根因,附 ss/lsof 排查命令。