本文介绍: 本文详细描述nodejs升级后引起的前端老旧项目构建工具生成hash报错问题(0308010C:digital envelope routines::unsupported),以及给出的几种解决方案。这几种解决方案各自都存在一些不完美的地方,但都能解决当前构建错误可以根据自己的实际需求来确定使用哪种方案

最近,发现自己电脑上的nodejs版本居然还是14+,而最新的已经到了18+,由于并没有使用任何版本管理工具,于是直接升级到了最新版本(v18.14.1),然后悲剧就发生了。

电脑里以往的绝大部分的Vue和React项目,在执行脚本构建命令
npm run dev
npm run build 时,都出现同样的错误,导致构建失败,并且报类似下面的错误

在这里插入图片描述

查找原因

出现了问题,自然要想办法解决
网上搜索了一圈,发现问题早已出现,一般描述的大致原因就是:当 nodejs 升级到17+版本以后,开始支持 OpenSSL 3.0,而 OpenSSL 3.0 对各种摘要算法做了更严格限制可能会导致一些程序运行错误

webpack源码配置

但其实,并不是所有的项目都会出现,比如使用最新版本的 webpack 工具的项目就能够正常运行,所以得搞清楚其中的具体原因,到底是哪些地方影响了项目运行
而要搞清原因,还得回到错误信息里,仔细查看上图里的错误信息可以发现Error 出现在了 webpack 包的 lib/util/createHash.js 代码文件查看该文件,可知主要是用于创建hash值,这部分核心代码如下所示

switch (algorithm) {
  case 'debug':
    return new DebugHash()
  default:
    return new BulkUpdateDecorator(require('crypto').createHash(algorithm))
}

从上面的代码我们可以发现webpackhash 使用了 nodejs 中的 crypto 加密模块,根据传入的算法名称创建 Hash 对象

我们直接代码测试,进一步发现当前版本webpack这里参数 algorithm 算法都是使用的 md4,搜索 webpack 源码还能发现很多地方直接写死了 md4 算法名:

在这里插入图片描述
查看webpack文档,也有类似的介绍
webpack源码里,我们还找到了一个配置属性output.hashFunction,在webpack配置说明文档里也找到该属性说明

在这里插入图片描述
如上图所示,该属性定义webpack可使用的散列算法默认也是 md4

查看nodejscrypto模块

在回到错误源码上,主要是这句代码出错:

require('crypto').createHash(algorithm)

上面的代码调用crypto 模块的 createHash 方法,我们查看方法文档可以现有这样一段话:

algorithm 取决于平台OpenSSL 版本支持的可用算法
例如 'sha256''sha512' 等。
在最近的 OpenSSL 版本中,openssl list -digest-algorithms显示可用的摘要算法

可见 webpack 源码里的 algorithm表示 OpenSSL 能够支持的可用算法,——在源码注释里也有解释
md4 显然也是其中一种算法,但这里创建失败了。
这里,我们已能发现问题所在crypto 模块的 createHash 方法在使用 md4 算法创建 Hash 对象失败,无法创建,因此报错

为什么报错呢?继续寻找答案,我们直接在当前node环境调用方法

require('crypto').createHash('md4')

立马报错

在这里插入图片描述
错误信息和项目中的类似,出现不支持 unsupported这里还出现了 opensslErrorStack 错误栈,初始化失败网上提到 openssl 3.0支持 md4 算法看上去是正确的,但为什么支持呢?

查看openssl问题

我们先了解下这里提到的 openssl什么OpenSSL一个强大的安全接字密码库的开源项目,它提供了一个功能丰富 openssl 安全工具包,拥有多种加密算法,能处理对称与非对称算法密钥数字证书编解码等等。

而上文也提到在 nodejs加密模块中,生成hash就借助了 openssl 等能力,其中通过命令 openssl list -digest-algorithms 可以查看当前平台支持哪些算法,在命令行执行后,可以现有几十种算法,而 md4 也名列其中:

在这里插入图片描述
那又为什么会创建失败呢,继续查看 openssl 3.0 相关文档,经过寻找,终于发现问题细节

legacy 算法容器中包含 MD2、MD4、MDC2、RMD160、CAST5、BF、IDEA、SEED、RC2、RC4、RC5 和 DES 等算法。

解决方法

升级webpack

从前文可知,目前环境出现的问题,主要是 webpack 的使用了 md4 算法导致错误,可见还得在 webpack 工具上下功夫。

注意:只改变 webpack配置属性 hashFunction 值为其他算法,无法解决问题,是因为 webpack 中很多地方写死了 md4 字符串

如果我们把 webpack 进行升级到较新的版本,就可以解决此类问题
据查,自 5.61.0 版本开始,webpack 就已解决了这个问题,可以查看同样创建hash的源码,新修改如下所示

switch (algorithm) {
  //...
  case "md4":
    if (createMd4 === undefined) {
      createMd4 = require("./hash/md4");
      if (BatchedHash === undefined) {
        BatchedHash = require("./hash/BatchedHash");
      }
    }
    return new BatchedHash(createMd4());
  // ...
  default:
    if (crypto === undefined) crypto = require("crypto");
    return new BulkUpdateDecorator(
      () => crypto.createHash(algorithm),
      algorithm
    );
}

以上代码可看出,针对 md4 已经做了专门处理,不再直接使用 crypto 模块创建,而是新建 md4 算法。

针对使用 @vue/cli-servicereact-scripts 工具构建的项目,由于还是依托 webpack,所以对应工具进行升级即可,其中:

但是,由于升级构建工具,可能随之带来很多不可知的问题,不少依赖包都会因为不支持而报错升级带来的成本并不小,所以很多人并不愿意升级构建工具。

当然,我们也可以自己修改 webpack 源码解决问题,只需要再创建hash对象的地方拦截 md4 换种算法就可以了,但还需要更改另外一个依赖terser-webpack-plugin,这个库里也有 md4

提供legacy容器环境

根据上文提到的错误原因,可知是由于我们使用了 openssllegacy 算法容器里的算法 md4,并不被标准默认容器支持,所以需要显式指定算法容器环境。
指定 legacy 算法容器,使用 --openssl-legacy-provider网上提供的很多解决方案,都是基于这个原则去做的,只不过都不交代具体的原因

增加系统环境变量

Windows系统下,可在系统环境变量添加一个新的变量NODE_OPTIONS,值为:--openssl-legacy-provider
下图所示

在这里插入图片描述
需要注意的是,
通过设置系统变量,我们只能解决 Git Bash系统右键启动时的构建命令正确执行,或者直接启动 git-bash.exe 软件,即单独的命令窗口能有效解决问题:

在这里插入图片描述
而在VSCode中添加的 git-bash 工具,却并不起作用,即在下面的窗口执行构建命令时仍然会报错

在这里插入图片描述

我并没有找到VSCode设置gitbash时有啥特殊配置,会导致两者之间有差异,如果有人了解,希望可以在评论里告知。

package.json中添加设置

一个能在新版nodejs完整解决问题的方案,就是在 package.json 配置的脚本命令中,增加对应的设置,如下所示

"dev": "set NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve",
"build": "set NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service build",

即增加 set NODE_OPTIONS=--openssl-legacy-provider 命令设置,就可以在 Git Bash 的右键命令以及VSCode中都能正常执行构建命令了。

注意,如果在 package.json 中添加脚本命令设置,会导致使用老版本的同事,无法执行脚本,因为老版本 nodejs 并不支持设置 --openssl-legacy-provider 属性值,将有如下提示中断构建执行:

node: --openssl-legacy-provider is not allowed in NODE_OPTIONS

nodejs版本降级或多版本管理

另外还有一种方案,就是不要使用最新版本的 nodejs,降级后重新使用V16的版本,低版本的 nodejs 可以保障项目正常运行
或者,还可以使用 nodejs 的多版本管理工具,能够自由切换不同的版本,同样满足要求。关于 nodejs 版本管理的简单介绍,可查看博文 node和npm如何升级版本

但是,已经使用了新版本的nodejs,再去用老版本的,也多少有些不那么回事。

最后

本文详细描述了 nodejs 升级后引起的前端老旧项目中构建工具生成hash报错的问题(0308010C:digital envelope routines::unsupported),以及给出的几种解决方案
这几种解决方案各自都存在一些不完美的地方,但都能解决当前构建错误,可以根据自己的实际需求来确定使用哪种方案

原文地址:https://blog.csdn.net/jimojianghu/article/details/129148486

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_27446.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注