yarn install 超时
- Published on
- 发布于·预估阅读7分钟
- 问题1 trouble with your network connection
- 获取安装超时包
- 解决方法
- 问题2 卡在building fresh packages....
- 获取安装超时的文件
- 解决方法
- FAQ
- 为什么安装项目依赖之前已经设置了源,为什么实际安装的时候,还有包不是从设置的源安装
- Authors
- Name
- willson-wang
问题1 trouble with your network connection
针对 yarn
1.x版本在CI场景安装依赖的过程中出现 There appears to be trouble with your network connection. Retrying...
这样的提示,如下图所示
最终导致安装过程无限拉长,或者导致安装失败
针对这个问题,应该怎么去排查与解决
首先导致这个问题的原因是yarn 在install的时候,无法正确获取到tarball对应的tgz包,如下图所示
无法正确获取到tgz包的原因则是网络问题,因为我们是从npm官方源或者yarn源上获取的这些tgz包,而这些源都是国外服务
获取安装超时包
第一步:在yarn install命令上添加--verbose命令行参数,目的是打印install整个过程中日志
// 添加上--verbose参数
yarn --ignore-optional --frozen-lockfile --check-files --verbose
具体日志如下图所示,可以看到详细的请求日志
第二步:查看添加参数之后的日志
gitlab流水看日志
第三步:使用下面的函数,获取下载的tgz包 为什么要这一步,原因是就是加上--verbose
,yarn
输出的详细日志也只会有There appears to be trouble with your network connection. Retrying...
这样的打印,是看不出哪个包超时加载的,所以需要我们手动获取一下tgz包来判断是哪些包超时加载了
gitlab 流水日志查看超时包
function logPkg(txt) {
const map = new Map()
const result = txt.matchAll(/http.*?\.tgz/g);
for (let item of result) {
const pkg = decodeURIComponent(item[0])
if (map.has(pkg)){
map.get(pkg).push(pkg)
console.log(`当前npm包${pkg}属于超时安装`, map.get(pkg));
} else {
map.set(pkg, [pkg])
}
}
}
// 获取到全部日志的内容,并传入logPkg
logPkg(document.getElementsByTagName('pre')[0].innerHTML)
如果有超时安装的包,控制台会直接打印出对应的包
解决方法
使用淘宝源
问题2 卡在building fresh packages....
针对 yarn
1.x版本在CI场景安装依赖的过程中出现 building fresh packages...
这样的提示,如下图所示
最终导致install失败,或者install时间过长
如果在CI场景如果无法查看全部日志,可以通过grep过滤输出,如下所示
yarn install --verbose |grep -v 'Copying' |grep -v 'Creating'
OR
yarn install --verbose |grep -v 'Copying\|Creating'
针对这个问题,应该怎么去排查与解决
首先导致这个问题的原因是yarn在将tgz包拉取到全局缓存目录,并将全局缓存目录内的包 copy到当前项目目录的node_modules之后,会执行npm包内的install、postinstall等钩子,而有些npm包是会利用install、postinstall钩子做一些下载文件的操作,比如node-sass,如下图所示
定义了install与postinstall钩子
定义默认的文件获取路径,为github地址
执行下载文件的操作
这些包内的默认的下载地址都是国外的服务器地址,由于网络的问题,很容易导致超时,最终导致install失败
获取安装超时的文件
怎么知道项目内的哪些包在install等钩子内去下载依赖,可以按照下面的操作进行
在yarn install命令上添加--verbose命令行参数,目的是打印install整个过程中日志
// 添加上--verbose参数
yarn --ignore-optional --frozen-lockfile --check-files --verbose
具体日志如下图所示,可以看到详细的请求日志
从日志可以看到下载超时的文件
解决方法
设置针对上述问题,有通用的解决方法,就是允许通过专门的字段指定下载地址,比如node-sass这个包,可以通过sass_binary_site
指定文件下载路径,常用的需要指定文件下载路径的包,如下所示
方式1: 设置.npmrc
sass_binary_site=https://npmmirror.com/mirrors/node-sass
sentrycli_cdnurl=https://npmmirror.com/mirrors/sentry-cli
electron_mirror=https://npmmirror.com/mirrors/electron
chromedriver_cdnurl=https://npmmirror.com/mirrors/chromedriver
operadriver_cdnurl=https://npmmirror.com/mirrors/operadriver
selenium_cdnurl=https://npmmirror.com/mirrors/selenium
puppeteer_download_host=https://npmmirror.com/mirrors
grpc-node-binary-host-mirror=https://npmmirror.com/mirrors
方式2: 通过npm config set设置
npm config set sass_binary_site https://npmmirror.com/mirrors/node-sass
npm config set sentrycli_cdnurl https://npmmirror.com/mirrors/sentry-cli
npm config set electron_mirror https://npmmirror.com/mirrors/electron
npm config set chromedriver_cdnurl https://npmmirror.com/mirrors/chromedriver
npm config set operadriver_cdnurl https://npmmirror.com/mirrors/operadriver
npm config set selenium_cdnurl https://npmmirror.com/mirrors/selenium
npm config set puppeteer_download_host https://npmmirror.com/mirrors
npm config set grpc-node-binary-host-mirror https://npmmirror.com/mirrors
FAQ
为什么安装项目依赖之前已经设置了源,为什么实际安装的时候,还有包不是从设置的源安装
"set_registry": "npm config set registry https://registry.npmmirror.com/"
原因是:yarn 1.x设计上的缺陷,为了保证复用缓存与方便提升依赖,生成的yarn.lock内是直接包含了registry的,如下图所示 而yarn在install的时候,如果有yarn.lock,那么则会直接使用yarn.lock内的链接来直接安装 比如jsonwebtoken这个包,虽然设置了指定的源,但是yarn.lock内获取tgz的地址是https://registry.npmjs.org/,所以这个包就还会从npm官方源安装,而不是从指定源安装
怎么从根上避免这个问题,可以查看下一篇,自定义Node镜像