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

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

初始背景

最近笔者重新拾起了Electron,把最新版Electron的官方文档阅读了一遍。众所周知,Electron作为依赖在安装的时候,其二进制文件下载在国内一直以来都是问题(因为默认会从github上下载),好在现在Electron的官方文档已经写的非常详细了:安装指导 | Electron (electronjs.org),只需要配置一个镜像地址到.npmrc中:

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

记住这个大写的Key

笔者由于是新的机器,还没有配置改值,所以找到.npmrc文件的配置了上述的镜像后,便开开心心的准备进行项目搭建了。

问题出现

然而,当笔者准备使用yarn执行如下命令的时候,却出了问题:

yarn add -D electron

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

咦,难道镜像配置写错了吗?仔细对比以后,没有问题。难道因为我的网络访问很慢吗?等到访问超时以后,发现一个IP地址超时了,心想国内镜像再怎么也不应该超时,盲猜镜像地址没有生效。于是乎,准备尝试对下载Electron二进制文件的过程进行debug。

问题排查

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

关于postinstall的详细说明:scripts | npm Docs (npmjs.com)

也就是说,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值,

由于每一次这个包都会重新安装,我们不太好调试这个值,所以,我们做一个简单的trick:

  1. 找到这个包的缓存(macOS上的路径为:~/Library/Caches/Yarn/v6/npm-@electron-get-xxxx):

  1. 找到上述indexjs代码,并添加一段日志打印:

  1. 准备完毕以后,我们重新在demo项目下执行yarn add -D electron。执行以后,等到超时以后,发现控制台日志打印如下:

Why!?为什么这个下载的Electron二进制文件地址依然是github的?于是,我们有必要进一步查看这个URL是如何得到。

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

而这个base值来源于mirrorVar这个方法:

根据上面代码的逻辑,name值为"mirror",options未使用,defaultValue为:

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

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

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

环境变量—— 配置 | npm 中文网 (nodejs.cn)

任何以 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里面的配置,也会在npm/yarn启动的时候被作为环境变量放到process.env中被访问。

那我们在.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)来运行脚本:

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

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

macOS解决方式

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

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

个人更加建议按照第一种方式配置,不然大小写敏感的坑太容易发生了。

关于Windows的特别说明

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

在 Windows 操作系统上,环境变量不区分大小写。

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镜像地址读取问题的更多相关文章

  1. macOS下利用dSYM文件将crash文件中的内存地址转换为可读符号

    一.使用流程 Windows下的程序运行崩溃时,往往可以利用pdb文件快速解析出程序崩溃的具体位置,甚至可以对应到源代码的具体行数.macOS下的symbolicatecrash也具备相应的功能.对应 ...

  2. npm设置为淘宝镜像地址

    1. npm设置为淘宝镜像 $npm config set registry https://registry.npm.taobao.org 2. 检查一下 $npm config get regis ...

  3. npm 更改在线仓库镜像地址

    node 安装后,npm 的默认在线仓库镜像地址为: https://registry.npmjs.org/ 使用 npm get registry 命令可以获取到: 为了使用 npm 能够更快的下载 ...

  4. Yarn vs npm: 你需要知道的一切

    Yarn 是 Facebook, Google, Exponent 和 Tilde 开发的一款新的 JavaScript 包管理工具.就像我们可以从官方文档了解那样,它的目的是解决这些团队使用 npm ...

  5. Yarn vs npm: 你需要知道的一切(转)

    英文原文:https://www.sitepoint.com/yarn-vs-npm/ 译文:http://web.jobbole.com/88459/ Yarn 是 Facebook, Google ...

  6. [web前端] yarn和npm命令使用

    原文地址: https://blog.csdn.net/mjzhang1993/article/details/70092902/ 最初接触 yarn 还是在 0.17.10 版本,由于各种各样的原因 ...

  7. Yarn vs npm:你需要知道的一切(转)

    转载:https://zhuanlan.zhihu.com/p/23493436 原文链接:Yarn vs npm: Everything You Need to Know Facebook.Goog ...

  8. node的包管理工具:yarn和npm

    arn是Facebook发布的一款依赖管理工具,它比npm更快.更高效. NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题. 一.yarn官方网站: 英文官网:ht ...

  9. 了解 yarn 、npm、nodejs

    一.前言 针对即将上线的 jeecg-boot 做一些准备.   二.了解系列 1.了解 nodejs Node.js 就是运行在服务端的 JavaScript. Node.js 是一个基于Chrom ...

  10. 解决Homestead yarn , npm run dev, 命令报错问题!

    解决Homestead yarn , npm run dev, 命令报错问题! 2018年06月01日 11:50:51 偶尔发发颠 阅读数:1654    版权声明:本文为博主原创,未经博主同意,不 ...

随机推荐

  1. JS兼容问题总结

    JS兼容问题总结 "标准浏览器"和"低版本浏览器(IE)"兼容写法 一.浏览器卷去的高度和宽度 var scrollTop = document.documen ...

  2. 多路复用IO:select poll epoll

    [电话面试]io多路复用专题面试 这个真猛 有人做了笔记:点这里 select Select(Max+1,&rset,null,null,null)是因为0~max是max+1. 过程: 将文 ...

  3. Z 函数

    简单记一下,避免忘记. z 函数 对于字符串 \(S\),我们将 \(z(i)\) 定义为从 \(i\) 开始的后缀与 \(S\) 的最长公共前缀的长度. \(O(n)\) 求出 z 函数 我们添加一 ...

  4. 【ASP.NET Core】在node.js上托管Blazor WebAssembly应用

    由于 Blazor-WebAssembly 是在浏览器中运行的,通常不需要执行服务器代码,只要有个"窝"能托管并提供相关文件的下载即可.所以,当你有一个现成的 Blazor was ...

  5. MyBatis 版本升级引发的线上问题

    MyBatis上线前后的版本:上线前(3.2.3)上线后(3.4.6) 服务上线后,开始陆续出现了一些更新系统交互日志方面的报警,这属于系统的辅助流程,报警如下代码所示.我们发现都是跟 MyBatis ...

  6. TCP三次握手,四次分手。个人感觉最容易理解的解释

    三次握手 名词解释 SYN,ACK,FIN存放在TCP的标志位,一共有6个字符,这里就介绍这三个: SYN:代表请求创建连接,所以在三次握手中前两次要SYN=1,表示这两次用于建立连接,至于第三次什么 ...

  7. What's the best way to read and understand someone else's code?

    Find one thing you know the code does, and trace those actions backward, starting at the end Say, fo ...

  8. w11默认调用ie浏览器方法

    作为公司的一个it人员,最近发现w11不能不能调用ie,导致公司的系统不能正常使用,因为后台插件室默认调用ie,如果重新写插件太麻烦,所以百度了下,亲测可用,目前,公司电脑已经可以正常使用,具体方法如 ...

  9. 【Voyage】GDOI 2023 旅游记 || ECHO.

    \(\color{#FFFFFF}{那是什么样的旅途呢}\) \(\color{#FFFFFF}{真的会害怕很多东西呢.想想害怕的其实不止这样一件事,便产生了"其实都一样没关系的,都应该踏过 ...

  10. DVWA上low级别反射型,存储型,DOM型XSS攻击获取用户cookie

    1.什么是反射型 XSS 攻击? 反射型 XSS 是指应用程序通过 Web 请求获取不可信赖的数据,并在未检验数据是否存在恶意代码的情况下,将其发送给用户. 反射型 XSS 一般可以由攻击者构造带有恶 ...