Electron 如何使用 taobao npm镜像

8,979 阅读2分钟
创建于 2019.10.27

## 背景

今天想重新摸一下 electron 做个带 web-server 的小 demo,所以就搭了一个 electron 的项目,执行yarn add electron --exact命令的时候时间很长,但是并没有报错,但是在后续执行yarn electron的时候,报错说我的 electron 没有安装成功,需要重新安装。

我按提示删除了node_modules/electron文件夹再执行 electron 的安装命令,重复几次以后,我通过yarn --force --verbose去看了详细的 log,应该就是网络问题,所以导致下载失败,因为 electron 的默认下载链接 BASE_URL是托管在 github 上,国内访问 github 基本是几十 kb,所以一定会挂。

经过一番 google,发现 Electron 官网有提到可以通过ELECTRON_MIRROR来指定自己的 electron 下载镜像站,并且直接提到可以通过以下的方式来指定淘宝 Electron 镜像

ELECTRON_MIRROR="https://npm.taobao.org/mirrors/electron/" yarn add electron
但是在使用上述指令安装时,还是没有报错,但是也没有成功,于是继续用--verbose来看是什么原因没有成功,发现这次的报错变成了 404 not found,这就是说这个ELECTRON_MIRROR环境变量是有用的。

于是我们开始看源码 electron 的安装到底做了些啥。

## 分析原因

1. electron 的 npm 包进行指定了"postinstall": "node install.js"
2. 两个判断会退出下载,设置ELECTRON_SKIP_BINARY_DOWNLOAD的环境变量,或是安装的 version 还没安过(dist 目录里没有这个文件)

if (process.env.ELECTRON_SKIP_BINARY_DOWNLOAD) {  
    process.exit(0);
}

const platformPath = getPlatformPath();
const electronPath =  process.env.ELECTRON_OVERRIDE_DIST_PATH || path.join(__dirname, 'dist', platformPath);

if (installedVersion === version && fs.existsSync(electronPath)) {
    process.exit(0);
}

3. 使用@electron/get(1.6.0)包的downloadArtifact函数进行下载,下载后解压
4. 然后找到拼接 url 的地方,是一个叫getArtifactRemoteURL的函数,他会用 details.version 作为默认值,然后通过customDir的环境变量来覆盖写

const path = mirrorVar('customDir', opts, details.version);
const url = `${base}${path}/${file}`;
5. 发现 version 这里有问题,他会把所有的 version 前面加上 v,但是淘宝镜像的路径是没有 v 的,所以才会拼出来 404,万幸的是后面的 file 拼接是没有问题的,所以我们只需要对customDir做一个指定就行了。

artifactDetails.version = normalizeVersion(artifactDetails.version);
export function normalizeVersion(version: string) {  
    if (!version.startsWith('v')) {    
        return `v${version}`;  
    }  
    return version;
}

## 解决方案

由于我现在用的是 7.0.0 版本,所以手动执行一下

ELECTRON_MIRROR=https://npm.taobao.org/mirrors/electron/ ELECTRON_CUSTOM_DIR=7.0.0 yarn --force --verbose
也可以在.npmrc 里面配置

electron-mirror=https://npm.taobao.org/mirrors/electron/
electron-custom-dir=7.0.0
还可以通过一些方式来指定吧,以下是 mirrorVar 函数的源码

function mirrorVar(name: keyof MirrorOptions, options: MirrorOptions, defaultValue: string) {  
    // Convert camelCase to camel_case for env var reading  
    const lowerName = name.replace(/([a-z])([A-Z])/g, (_, a, b) => `${a}_${b}`).toLowerCase(); 
    return (    
        process.env[`NPM_CONFIG_ELECTRON_${lowerName.toUpperCase()}`] ||    
        process.env[`npm_config_electron_${lowerName}`] ||    
        process.env[`npm_package_config_electron_${lowerName}`] ||    
        process.env[`ELECTRON_${lowerName.toUpperCase()}`] ||    
        options[name] ||    
        defaultValue  
);}

## 注意

需要注意这里的版本要手动指定,所以最好使用 exact 版本,防止^*semver 用了小版本或 patch 版,所以下载错了二进制文件了造成一些疑惑。