npm 镜像源怎么设置:pnpm、yarn、bun 换源回切与装包慢排查

博客 / 开发工具

npm 镜像源怎么设置:pnpm、yarn、bun 换源回切与装包慢排查

国内最常用的 npm 镜像源地址是 https://registry.npmmirror.com,官方源是 https://registry.npmjs.org。旧的 registry.npm.taobao.org 早已停用,配置里还写着它的话,要尽快换掉。换源只解决“包的元数据和 tarball 从哪下”,装包慢的另一半原因往往在二进制下载、lockfile 和本地网络,下面分开讲。

先确认:现在用的是哪个源?

改之前先看清现状,很多“换了源还是慢”的问题,其实是配置被别的地方覆盖了。

npm config get registry
npm config list            # 看每一项来自哪个配置文件
pnpm config get registry
yarn config get registry          # yarn v1
yarn config get npmRegistryServer # yarn Berry (v2+)

npm 的配置按优先级从高到低是:命令行参数 > 环境变量(NPM_CONFIG_REGISTRY / npm_config_registry)> 项目里的 .npmrc > 用户目录的 ~/.npmrc > 全局配置。如果 CI 里设置了环境变量,你在项目 .npmrc 里写什么都不生效。

再顺手查一下老域名有没有残留:

grep -rn "npm.taobao.org" ~/.npmrc ~/.yarnrc ~/.yarnrc.yml .npmrc .yarnrc .yarnrc.yml \
  package-lock.json yarn.lock 2>/dev/null

各个包管理器怎么换源?

每种工具都给出三种写法:全局(只影响你这台机器)、项目级(跟着仓库走,团队成员一致)、单次(只这一条命令)。

npm

# 全局:写入 ~/.npmrc
npm config set registry https://registry.npmmirror.com

# 项目级:在项目根目录建 .npmrc
echo "registry=https://registry.npmmirror.com" > .npmrc

# 单次
npm install --registry=https://registry.npmmirror.com

pnpm

pnpm 读的是同一套 .npmrc,所以上面 npm 的项目级写法对 pnpm 一样有效。

pnpm config set registry https://registry.npmmirror.com   # 全局
pnpm install --registry=https://registry.npmmirror.com    # 单次

yarn v1(Classic)

yarn v1 会读 .npmrc,也有自己的 .yarnrc。

yarn config set registry https://registry.npmmirror.com   # 全局,写入 ~/.yarnrc
echo 'registry "https://registry.npmmirror.com"' > .yarnrc  # 项目级
yarn install --registry https://registry.npmmirror.com     # 单次

yarn Berry(v2 及以上)

Berry 不读 .npmrc,配置项也换了名字,是 npmRegistryServer。

# 项目级:写入当前目录的 .yarnrc.yml
yarn config set npmRegistryServer https://registry.npmmirror.com

# 全局:写入 ~/.yarnrc.yml
yarn config set -H npmRegistryServer https://registry.npmmirror.com

# 单次:用环境变量
YARN_NPM_REGISTRY_SERVER=https://registry.npmmirror.com yarn install

bun

bun 推荐写在 bunfig.toml,项目级放在仓库根目录,全局放在 ~/.bunfig.toml:

[install]
registry = "https://registry.npmmirror.com"

较新的 bun 也会读取 .npmrc 里的 registry,并且认 NPM_CONFIG_REGISTRY 环境变量。团队里如果同时有人用 npm 和 bun,项目级 .npmrc 是最省事的共同配置。

对照表

工具项目级配置文件配置项单次
npm.npmrcregistry--registry=
pnpm.npmrcregistry--registry=
yarn v1.yarnrc 或 .npmrcregistry--registry
yarn Berry.yarnrc.ymlnpmRegistryServerYARN_NPM_REGISTRY_SERVER=
bunbunfig.toml 或 .npmrcinstall.registryNPM_CONFIG_REGISTRY=

发包或要拿最新版本时,怎么回切官方源?

镜像站从官方同步,新发布的版本可能要等一段时间才出现。另外 npm publish、npm login 必须对官方源操作,镜像不接受发布。

# 永久回切
npm config set registry https://registry.npmjs.org
yarn config set npmRegistryServer https://registry.npmjs.org   # Berry

# 只在发布时临时指定
npm publish --registry=https://registry.npmjs.org

如果公司有私有源,可以只给某个 scope 单独指定,不影响其他包:

# .npmrc
registry=https://registry.npmmirror.com
@your-company:registry=https://npm.your-company.example/

这里的私有源地址只是示例。

为什么换了源,CI 还在走旧地址?

原因通常在 lockfile。几种 lockfile 记录下载地址的方式不一样:

  • package-lock.json(npm):每个包都写了完整的 resolved URL。较新版本的 npm 有个 replace-registry-host 配置,默认值是 npmjs,意思是只把 registry.npmjs.org 替换成你当前配置的源。如果 lockfile 里写的是 npmmirror 或老淘宝域名,npm 不会替换,CI 换回官方源也照样去请求那个地址;老域名不可用时就直接失败。
  • yarn.lock(v1):同样写了完整 resolved URL,老域名需要手动替换。
  • yarn Berry 的 yarn.lock、pnpm-lock.yaml:对默认 registry 上的包一般只记版本和 integrity,不写完整地址,受影响小。
  • bun.lock:默认源的包通常不写完整地址,有疑问就用 grep 查一下。

处理办法有三种,按改动从小到大排:

# 1. 单次让 npm 替换所有 resolved 的域名
npm ci --replace-registry-host=always

# 2. 把 lockfile 里的老域名统一换成官方源(提交前看一眼 diff)
sed -i 's#https://registry.npm.taobao.org#https://registry.npmjs.org#g' package-lock.json

# 3. 删掉 lockfile 重新生成(会顺带升级依赖,慎用)

我们的建议是:lockfile 里统一保留官方源地址,各人的机器和 CI 通过 .npmrc 或环境变量决定实际走哪个源。这样 lockfile 不随个人习惯来回变,换源也不用改仓库。integrity 校验值和下载地址无关,镜像下来的 tarball 内容一致就能通过。

为什么 electron、sharp、playwright 换了源还是慢?

这类包的 npm 包本身很小,真正大的东西是在 postinstall 阶段从另一个域名下载的:electron 从 GitHub Releases 拉二进制,playwright 和 puppeteer 下载浏览器,老版本的 node-sass 下载编译好的 binding。registry 换到哪里,这些下载都不跟着走。

判断方法:装包时看日志卡在哪一步。

npm install --foreground-scripts --loglevel=http

如果最后停在某个包的 postinstall,而且日志里出现 github.com、playwright 或 storage 相关的域名,那就是二进制下载慢,不是 registry 慢。

常见的处理方式是通过环境变量把下载地址指向镜像。npmmirror 提供了二进制镜像目录(https://npmmirror.com/mirrors/),具体路径以目录里实际存在的为准:

export ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"
export PLAYWRIGHT_DOWNLOAD_HOST="https://npmmirror.com/mirrors/playwright"
export SASS_BINARY_SITE="https://npmmirror.com/mirrors/node-sass"

几点要注意:

  • 新版 sharp 的预编译文件改成以 @img/sharp-* 的 npm 包发布,会随 registry 一起走镜像,一般不需要再配二进制地址;老版本才需要。
  • 很多旧教程把 electron_mirror=... 这类键写进 .npmrc。新版 npm 对不认识的配置项会给出警告,并提示以后的大版本里将不再支持。放在环境变量或 CI 的 env 里更稳。
  • puppeteer 新版本的下载变量名和以前不同,以它的官方文档为准。
  • CI 里如果不需要浏览器,可以用对应工具的“跳过下载”变量,直接省掉这一步。

慢到底慢在哪一层?一个判断流程

换源是在解决“离源站太远”的问题。如果慢在 DNS、代理或者本地网络,换源没用。可以按下面的顺序查:

第一步:分别测 registry 和二进制下载域名的连接时间。

for u in https://registry.npmjs.org/react \
         https://registry.npmmirror.com/react \
         https://github.com; do
  curl -o /dev/null -s -w "$u\n  dns=%{time_namelookup}s connect=%{time_connect}s tls=%{time_appconnect}s ttfb=%{time_starttransfer}s total=%{time_total}s\n" "$u"
done

这几个时间是累计值:dns 是域名解析,connect 到 TCP 建好,tls 到握手完成,ttfb 到服务器返回第一个字节。这个拆法和 cdnping 在线测速 的口径一致:首页对公共前端 CDN 分别测“首次连接”(含 DNS 与 TLS 握手)和“往返”(连接复用后 3 次请求的中位数)。在浏览器里打开测一遍,可以快速看出当前网络到境外和境内 CDN 节点的大致差距;各家 CDN 的横向数据见 CDN 速度榜,测法见数据方法。关于这几段时间分别代表什么,可以参考 AI API 延迟拆解,原理和装包是一样的。

第二步:按结果对照处理。

现象大概率原因处理
dns 就要好几秒DNS 解析慢或被污染换 DNS,参考 DNS over HTTPS 配置指南
dns 正常,connect 很高到源站路由远或丢包换镜像源
镜像 ttfb 正常但安装仍慢卡在二进制下载按上一节配置二进制镜像
时快时慢,部分请求超时代理规则或 IPv6 出口不一致查分流和双栈
官方源和镜像都慢本地网络本身有问题先做整体网络自检

第三步:检查代理。 npm 会读 proxy、https-proxy 配置和 HTTPS_PROXY 环境变量。开着全局代理时访问国内镜像,流量可能先绕到境外再回来,反而更慢。可以用 npm config get https-proxy 和 env | grep -i proxy 看有没有残留。分流规则怎么判断是否生效,见 国内网站如何看到你的真实 IP 和 分流原理。

如果系统同时有 IPv4 和 IPv6,而代理只接管了其中一个,就会出现“同一个命令有时快有时超时”,排查方法见 IPv6 代理不生效。

第四步:仍然说不清楚,就做一遍全链路检查。 开发者网络自检清单(2026 版) 把出口 IP、DNS、分流和测速串成了一个顺序,适合在新机器或新 CI runner 上跑一遍。

换源前后的检查表

  • npm config list 里没有 npm.taobao.org
  • 项目 .npmrc、.yarnrc.yml 或 bunfig.toml 和团队约定一致
  • lockfile 里没有老域名;npm 项目的 resolved 统一用官方源
  • CI 的环境变量没有覆盖掉项目配置(或者覆盖是有意的)
  • 发布流程显式写了 --registry=https://registry.npmjs.org
  • electron、playwright 等二进制下载地址放在环境变量里,不放在 .npmrc
  • 用 curl 测过 registry 和二进制域名的连接时间,确认慢在哪一层

小结

镜像源本身只要改一行。换了还慢时,先用 curl 或在线测速把 DNS、连接、首字节时间拆开,再按上面的表决定是改源、配二进制镜像,还是查代理和 DNS。