macOS下由yarn与npm差异引发的Electron镜像地址读取问题

科技资讯 投稿 7100 0 评论

macOS下由yarn与npm差异引发的Electron镜像地址读取问题

写在前面:该问题仅仅出现在Linux和macOS上,Windows上不存在该问题!

初始背景

.npmrc中:

ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"

记住这个大写的Key

.npmrc文件的配置了上述的镜像后,便开开心心的准备进行项目搭建了。

问题出现

yarn执行如下命令的时候,却出了问题:

yarn add -D electron

运行启动以后,在Electron安装的环境一直卡住了很久很久。

问题排查

首先定位到node_module/electron包,能够看到有一段安装后脚本执行命令(postinstall):

也就是说,node_module/electron本身npm包install完成以后,还会执行其包内的install.js。

node_module/electron包下的install.js,该脚本内部主要逻辑是先检查Electron的二进制缓存,如果不存在缓存,则使用来自@electron/get包中提供的downloadArtifact方法从远端下载Electron二进制制品文件。

@electron/get包中的downloadArtifact

@electron/get包下的index.js内容:

getArtifactRemoteURL方法得到的url值,

    找到这个包的缓存(macOS上的路径为:~/Library/Caches/Yarn/v6/npm-@electron-get-xxxx):
  1. 找到上述indexjs代码,并添加一段日志打印:
  1. 准备完毕以后,我们重新在demo项目下执行yarn add -D electron。执行以后,等到超时以后,发现控制台日志打印如下:

继续查看代码,这个url来源于artifact-utils中的getArtifactRemoteURL方法,而这个方法里面关于最终返回的url最重要的部分是下图所示的base的值:

base值来源于mirrorVar这个方法:

"mirror",options未使用,defaultValue为:

"https://github.com/electron/electron/releases/download/"

process.env中找到对应的值,那么就会使用默认的github官方制品地址的值。按照代码逻辑,运行到这个方法的时候,会从process.env中尝试获取:

    "NPM_CONFIG_ELECTRON_MIRROR"
  1. "npm_config_electron_mirror"
  2. "npm_package_config_electron_mirror"
  3. "ELECTRON_MIRROR"

任何以 npm_config_ 开头的环境变量都将被解释为配置参数。 例如,将 npm_config_foo=bar 放入您的环境中会将 foo 配置参数设置为 bar。 任何未赋值的环境配置都将被赋值为 true。 配置值不区分大小写,因此 NPM_CONFIG_FOO=bar 的工作方式相同。 但是,请注意,在 scripts 内部,npm 将设置自己的环境变量,并且 Node 会更喜欢那些小写版本,而不是您可能设置的任何大写版本。 详情见此问题。

--allow-same-version 将变为 npm_config_allow_same_version=true

那我们在.npmrc中配置的ELECTRON_MIRROR,在process.env中变成了什么呢?通过添加日志打印,我们会看到:

process.env中,这个键为"npm_config_ELECTRON_MIRROR"npm_config小写,ELECTORN_MIRROR大写)。我们知道,nodejs中object对象的属性值是大小写敏感的!所以,当上面的mirrorVar代码运行,尝试获取process.env中的值的时候,根本找不到了,因为没有"NPM_CONFIG_ELECTRON_MIRROR""npm_config_electron_mirror""npm_package_config_electron_mirror""ELECTRON_MIRROR"这些属性。

npm进行安装的时候:

npm install -D electron

又能够很快安装。Why?!难道npm和yarn下的运行环境有差异吗?为了验证,我们编写一个简单的index.js代码:

console.log("process.env['npm_config_electron_mirror']", process.env['npm_config_electron_mirror']);
console.log("process.env['NPM_CONFIG_ELECTRON_MIRROR']", process.env['NPM_CONFIG_ELECTRON_MIRROR']);
console.log("process.env['npm_config_ELECTRON_MIRROR']", process.env['npm_config_ELECTRON_MIRROR']);

然后,在package.json中添加脚本:

{
  "name": "simple-electron-main-app",
  "version": "1.0.0",
  "scripts": {
+   "start": "node index.js"
  },
  "devDependencies": {}
}

最后,我们分别使用yarn(yarn start)和npm(npm run start)来运行脚本:

.npmrc中的"ELECTRON_MIRROR"直接拼接到了"npm_config_"后边,作为process.env的一个属性,所以你只能访问process.env["npm_config_ELECTRON_MIRROR"]得到值;

.npmrc中的"ELECTRON_MIRROR"首先被转为了小写,然后拼接到了"npm_config_"后边,作为了process.env的属性,所以你需要访问process.env["npm_config_electron_mirror"]来得到值。

macOS解决方式

.npmrc配置大写的ELECTRON_MIRROR的时候,使用yarn add -D electron安装electron的时候,二进制镜像地址没有生效了。那么,解决的办法也非常简单,两种:

    .npmrc配置改为小写key:electron_mirror="https://npmmirror.com/mirrors/electron/"
  1. 使用npm上下文环境进行安装。

关于Windows的特别说明

process.env | Node.js API 文档 (nodejs.cn)

const { env } = require('node:process');

env.TEST = 1;
console.log(env.test);
// => 1

也就是说,在Windows机器上,即使process.env中的key为"npm_config_ELECTRON_MIRROR",你也可以通过"npm_config_electron_mirror"或者是"NPM_CONFIG_ELECTRON_MIRROR"来访问这个值:

编程笔记 » macOS下由yarn与npm差异引发的Electron镜像地址读取问题

赞同 (40) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽