一、依赖安装过程存在的问题
1)为什么安装依赖会遇到问题?
- 网络问题导致无法从默认的npm仓库下载
- 这些包在安装时需要从特定的镜像站点下载二进制文件,而这些镜像站点在国内可能访问受限。
2)为什么设置环境变量或.npmrc中的配置可以解决安装问题?
- 这可能涉及到npm在安装包时如何定位和下载依赖的二进制文件。通常,这些包在安装脚本中会检查环境变量或者配置文件中的路径来获取二进制文件的位置,而不是从默认的源下载。
3)环境变量与 .npmrc 的优先级机制
配置生效优先级
bash
# 层级越高优先级越高
1. 命令行参数:npm install --chromedriver_cdnurl=https://registry.npmmirror.com/binary.html/?path=chromedriver/
2. 环境变量:export CHROMEDRIVER_CDNURL=xxx
3. 项目级 .npmrc:./.npmrc
4. 用户级 .npmrc:~/.npmrc
5. 全局 npm 配置:npm config set xxx
4)如何确定该设置哪个环境变量?
-
查阅包的 官方文档 或
install.js
源码:bash# 查看 chromedriver 的安装脚本 cat node_modules/chromedriver/install.js
通常会在脚本中找到类似逻辑:
iniconst filePath = process.env.CHROMEDRIVER_FILEPATH || defaultUrl;
5)npm 安装二进制包的流程
当安装如 chromedriver
这类包时,npm 会执行以下步骤:
- 下载包的元数据(
package.json
) - 执行
install
脚本(通常包含下载预编译二进制文件的逻辑)- 这些包的安装脚本(如
install.js
)会优先读取环境变量或.npmrc
中的配置。 - 若检测到自定义路径或镜像源,则跳过默认下载逻辑,直接从指定位置获取文件。
- 从 默认源(如 GitHub Releases 或官方 CDN)下载二进制文件
- 这些包的安装脚本(如
- 将二进制文件解压到
node_modules/.bin
目录
问题根源:国内访问 GitHub 或国外 CDN 常出现网络不稳定,导致步骤2失败。
6)手动配置的核心原理
通过 覆盖默认下载路径,让 npm 从本地或国内镜像获取二进制文件:
-
方法 1 :设置环境变量(如
CHROMEDRIVER_FILEPATH
)bash# 在终端中临时设置 export CHROMEDRIVER_FILEPATH=https://registry.npmmirror.com/binary.html/?path=chromedriver/100.0.4896.20/chromedriver_win32.zip npm install chromedriver
-
方法 2 :在
.npmrc
中配置镜像源ini# .npmrc chromedriver_cdnurl=https://registry.npmmirror.com/binary.html/?path=chromedriver/ puppeteer_download_host=https://registry.npmmirror.com/binary.html
7)解决 Vue2 源码安装问题的通用方案
1. 配置国内镜像源
在 .npmrc
中统一设置镜像:
ini
registry=https://registry.npmmirror.com/
chromedriver_cdnurl=https://registry.npmmirror.com/binary.html/?path=chromedriver/
puppeteer_download_host=https://registry.npmmirror.com/binary.html
2. 手动下载 + 路径覆盖
对顽固依赖(如 phantomjs
):
perl
# 下载二进制文件到本地
wget https://registry.npmmirror.com/-/binary/phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2
# 安装时指定路径
PHANTOMJS_CDNURL=file:///path/to/phantomjs.tar.bz2 npm install phantomjs
二、完整操作流程(以 chromedriver
为例)
1. 手动下载二进制文件
访问 npm 镜像站,搜索 chromedriver
,找到对应版本(如 chromedriver_114.0.5735.90.zip
)。
ruby
wget https://registry.npmmirror.com/-/binary/chromedriver/114.0.5735.90/chromedriver_linux64.zip
2. 配置本地路径
bash
# 方式1:通过环境变量
export CHROMEDRIVER_FILEPATH=/Users/yourname/Downloads/chromedriver_114.0.5735.90.zip
# 方式2:在项目根目录创建 .npmrc
echo 'chromedriver_filepath=/Users/yourname/Downloads/chromedriver_114.0.5735.90.zip' >> .npmrc
3. 执行安装
bash
npm install chromedriver
# 安装脚本将跳过下载,直接使用本地文件
安装脚本实际行为:
rust
// 伪代码流程
if (发现.npmrc中配置了chromedriver_cdnurl) {
下载地址 = 'file:///home/user/downloads/chromedriver_linux64.zip';
} else {
下载地址 = 'https://chromedriver.storage.googleapis.com/114.0.5735.90/...';
}
下载文件 → 解压到 node_modules/chromedriver/bin
4. 验证安装
检查 node_modules/.bin
目录是否存在可执行文件:
bash
ls node_modules/.bin/chromedriver
5. 依赖包安装流程分析
- 以
chromedriver
为例,其安装流程核心代码如下(简化自 chromedriver/install.js):
javascript
async function install() {
// 1. 读取配置优先级:环境变量 > .npmrc > 默认值
const cdnUrl = process.env.CHROMEDRIVER_CDNURL
|| npmConfig.get('chromedriver_cdnurl')
|| 'https://chromedriver.storage.googleapis.com';
const version = process.env.CHROMEDRIVER_VERSION
|| npmConfig.get('chromedriver_version')
|| require('./package.json').version;
// 2. 构建下载地址
const binaryUrl = `${cdnUrl}/${version}/chromedriver_${process.platform}_${process.arch}.zip`;
// 3. 下载并解压
const tempFile = path.join(os.tmpdir(), 'chromedriver.zip');
await downloadFile(binaryUrl, tempFile);
await extractZip(tempFile, { dir: path.join(__dirname, 'bin') });
}
6. 核心源码解析(以 downloadFile
函数为例)
javascript
// chromedriver 的实际下载函数
async function downloadFile(url, destPath) {
const writer = fs.createWriteStream(destPath);
// 处理 file:// 协议
if (url.startsWith('file://')) {
const filePath = url.substring(7);
const reader = fs.createReadStream(filePath);
reader.pipe(writer);
return new Promise((resolve, reject) => {
writer.on('finish', resolve);
writer.on('error', reject);
});
}
// 处理 HTTP/HTTPS 下载
const response = await axios({
url,
method: 'GET',
responseType: 'stream'
});
response.data.pipe(writer);
return new Promise((resolve, reject) => {
writer.on('finish', resolve);
writer.on('error', reject);
});
}
关键点:
- 通过
url.startsWith('file://')
判断是否本地文件 - 使用 Node.js Stream 实现高效文件传输
五、调试技巧与验证方法
1. 查看实际下载地址
在安装时添加 --verbose
参数:
lua
npm install chromedriver --verbose
# 输出日志中搜索 "GET https://..."
2. 强制重新安装
bash
rm -rf node_modules/chromedriver
npm install chromedriver --force
3. 检查最终二进制文件
bash
ls -l node_modules/chromedriver/bin/
# 应存在 chromedriver 可执行文件
六、通用解决方案模板
对其他二进制包(如 phantomjs
、puppeteer
),只需修改对应的环境变量前缀:
包名 | 环境变量 | .npmrc 配置项 |
---|---|---|
chromedriver | CHROMEDRIVER_CDNURL |
chromedriver_cdnurl |
phantomjs | PHANTOMJS_CDNURL |
phantomjs_cdnurl |
puppeteer | PUPPETEER_DOWNLOAD_HOST |
puppeteer_download_host |
七、运行Vue2.6单测的实战经验
- 根据自己的操作系统,手动下载phantomjs2.1.1,并配置到环境变量 path中
- 根据自己的操作系统,手动下载chromedriver2.45,保存到本地,https:// registry.npmmirror.com/binary.html?path=chromedriver/2.45/
- 设置环境变量chromedriver_filepath,指向步骤2保存的目录
- (export PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true) npm install
- npm run build
- 根据自己的操作系统,手动下载chromium,https:// registry.npmmirror.com/binary.html?path=chromium-browser-snapshots/
- 设置环境变量PUPPETEER_EXECUTABLE_PATH,指向步骤6中chromium的执行路径
- 安装java1.8并配置环境变量,selenium运行时需要
- npm run test
mac电脑下环境变量配置如下,可供参考:
javascript
export PATH=$PATH:/xxx/lib/ phantomis-2.1.1-macosx/bin
export chromedriver_filepath=/xxx/lib/chromedriver_mac64.zip
export PUPPETEER_EXECUTABLE_PATH=/xxx/lib/chrome-mac/Chromium.app/Contents/MacOS/Chromium