问题描述
当你在 node17 及以上环境使用 vue-cli-service@4.x 运行项目时,会得到如下报错
Error: error:0308010C:digital envelope routines::unsupported
at new Hash (node:internal/crypto/hash:69:19)
at Object.createHash (node:crypto:133:10)
原因分析
TerserWebpackPlugin
这是因为 vue-cli-service@4 内部默认使用了 terser-webpack-plugin 这个包进行代码压缩,如下图
Node Crypto
terser-webpack-plugin 这个 webpack 插件会使用 crypto 的 createHash 函数并指定 md4 算法计算哈希,如下图
OpenSSL
createHash 传入的参数用于指定哈希算法,可传入的算法类型由所在平台的 OpenSSL 版本决定
The
algorithmis dependent on the available algorithms supported by the version of OpenSSL on the platform.
Node 17
Node 17 最大的改动就是使用了 OpenSSL 3.0,自此支持了 QUIC,但也同时停止了对于一些哈希算法的支持,其中就包括 md4
Moved the EVP digests MD2, MD4, MDC2, WHIRLPOOL and RIPEMD-160 to the legacy provider.
- Node 17 Release Note:nodejs.org/en/blog/rel…
- OpenSSL3.0 Release Note:openssl-library.org/news/openss…
因此当 vue-cli-service@4(或者说当使用 terser-webpack-plugin@1.4.5及以下版本)遇到 node 17 及以上版本时,会出现上面所说的报错
解决方法
方式1:增加 Node 参数
Node 17 的发布公告中提到了可以通过 --openssl-legacy-provider 运行参数来临时支持已废弃的算法
A command-line option,
--openssl-legacy-provider, has been added to revert to the legacy provider as a temporary workaround for these tightened restrictions.
因此如果是还在使用 vue-cli-service@4.x 版本的项目,可以如下增加 Node 运行参数
"serve": "env NODE_OPTIONS='--openssl-legacy-provider' vue-cli-service serve"
方式2:升级 terser-webpack-plugin 版本
terser-webpack-plugin 在 1.4.6 增加了对于 Node 18 的兼容
terser-webpack-plugin@1.4.6 Release Note:github.com/webpack-con…
因此可以在项目的 package.json 增加如下配置来安装兼容该问题的插件版本
"terser-webpack-plugin": "^1.4.6"
这种方式经过实践存在一些问题,因为原本 @vue/cli-service 会有自己的 node_modules,因此在运行命令时会优先使用它自己安装的依赖包,而不是项目中新安装的。
有两种方式解决这个问题:
- 手动删除 @vue/cli-service 下的 node_modules,这样它会降级寻找项目根 node_modules 下新安装的 1.4.6 版本(但这种可能不适用于其他环境通过 lock 文件重新安装后的情况)
- 搭配 package.json 的 resolutions 选项和依赖去重工具,比如对于使用 yarn1 的项目可以使用 yarn-deduplicate(yarn2及以上版本已经内置该能力) 具体操作可参考 yarn-deduplicate, 对于 resolutions 选项配置为 "terser-webpack-plugin": "^1.4.6" 可指定对于该包的使用优先使用满足指定条件的版本
方式3:升级 vue-cli-service
将 vue-cli-service 升级到 5.x 版本,因为 vue-cli-service@5.x 内部使用 webpack5,默认集成了最新版的 terser-webpack-plugin
Webpack v5 comes with the latest
terser-webpack-pluginout of the box.
修订记录
- 2025-05-08: 更新了解法2存在的问题