vue-cli4与nodejs的兼容问题分析及解决方案

478 阅读3分钟

问题描述

当你在 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 algorithm is dependent on the available algorithms supported by the version of OpenSSL on the platform.

参考:nodejs.org/docs/latest…

Node 17

Node 17 最大的改动就是使用了 OpenSSL 3.0,自此支持了 QUIC,但也同时停止了对于一些哈希算法的支持,其中就包括 md4

Moved the EVP digests MD2, MD4, MDC2, WHIRLPOOL and RIPEMD-160 to the legacy provider.

因此当 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,因此在运行命令时会优先使用它自己安装的依赖包,而不是项目中新安装的。

有两种方式解决这个问题:

  1. 手动删除 @vue/cli-service 下的 node_modules,这样它会降级寻找项目根 node_modules 下新安装的 1.4.6 版本(但这种可能不适用于其他环境通过 lock 文件重新安装后的情况)
  2. 搭配 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-plugin out of the box.

参考:webpack.js.org/plugins/ter…

修订记录

  • 2025-05-08: 更新了解法2存在的问题