ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Ubuntu 24.04 npm镜像源配置实战:解决npm install慢与404报错

Ubuntu 24.04 npm镜像源配置实战:解决npm install慢与404报错 搞 Node 开发的人应该都经历过这种窒息时刻npm install 一跑进度条半天不动最后蹦出一行 fetch 失败。在 Ubuntu 上尤其明显因为很多人第一台 Linux 开发机或服务器就是 Ubuntu网络出口到 npm 官方源的链路本身就忽快忽慢。给 npm 切换国内镜像源在 Ubuntu 上属于入门配置但网上资料比较碎有说淘宝旧域名、有教 npm cache clean --force 的有些方案已经过时甚至有害。这篇文章我会沿着我在 Ubuntu 24.04 上实际操作过的路径把镜像源选择、换源命令、项目级配置、常见报错都梳一遍适合刚在 Ubuntu 上搭好 Node 环境的人也适合被各种诡异报错反复折腾的老手。换源本身不复杂复杂的是换完之后你能不能解释它为什么管用、为什么有些包还是慢、哪些坑不能再踩。1. 为什么 npm 在国内这么慢换镜像到底换了什么1.1 慢的根源默认源指向国外节点npm 默认的 registry 是 https://registry.npmjs.org/这个服务本身没问题但它主要部署在国外的 CDN 上国内访问时链路长、绕路多再加上部分网络环境对国外流量本来就不友好结果就是 npm install 经常卡在 downloading、fetch 阶段甚至几兆的包能拉半小时。镜像源做的事情很简单把 npm 官方仓库的数据同步一份到国内服务器再通过国内 CDN 分发。你换源之后npm install 不再去连官方 Registry而是去连离你更近的国内节点。包的内容不会变只是下载的“仓库地址”变了逻辑上和你去官方源完全一致。npm 本身也有 lockfile 校验机制从镜像源下载的包只要 hash 对得上使用上没有任何风险。1.2 主流镜像源对比别再踩老淘宝域名的坑国内常见 npm 镜像源主要是这几个源名称地址特点淘宝 npmmirrorhttps://registry.npmmirror.com同步频率高、用户多、社区文档最多腾讯云https://mirrors.cloud.tencent.com/npm/腾讯内部同步速度稳定华为云https://mirrors.huaweicloud.com/repository/npm/华为云维护适合云上环境官方源https://registry.npmjs.org/包最全、无延迟但国内直连不稳这里必须重点提醒一句网上大量老教程里写的 https://registry.npm.taobao.org 已经不再维护了2022 年之后基本处于不可用状态继续按老教程配置会出现证书错误、404 或者长时间解析失败。我见过不少同事拿老博客的配置直接粘到 Ubuntu 服务器上结果 npm install 依然报错还以为是镜像源被墙了其实是域名换了。现在的正确地址是 npmmirror.com 这一套别再对着旧域名使劲。选型上我建议个人开发无脑用淘宝 npmmirror因为社区踩坑最多、同步最快。腾讯和华为作为冗余备选偶尔淘宝源抽风或者同步延迟时可以临时切换。如果是公司内部环境还要注意私有包的处理这个下面会专门说。2. 换源的三种姿势按实际场景选一种就行2.1 最省事全局改 npm config全局配置是大部分人的首选直接在终端执行npm config set registry https://registry.npmmirror.com运行完没有任何提示所以很多人不确定有没有生效。这时可以执行npm config get registry如果输出的是上面的 npmmirror 地址说明已经改好了。这里解释一下原理npm config set 会把配置写入当前用户的 ~/.npmrc 文件这个文件的作用域是全局的不管你进入哪个项目npm 都会优先读取它。默认情况下 npm 的配置优先级从低到高是内置默认配置、全局配置、用户配置、项目级配置所以全局设置之后所有项目的 install 都走镜像源。但有一个点容易被忽略npm config set 写入的是“用户级配置”不是“系统级配置”。如果你机器上有多个 Linux 用户只配置当前用户其他用户不受影响。服务器上多账号共存时别指望一条命令通吃所有用户要么挨个配置要么在项目里放 .npmrc下一段说。2.2 更稳项目级 .npmrc如果某个项目需要保证团队成员统一使用同一套源最好的方式不是让每个人手动执行 npm config set而是在项目根目录放一个 .npmrc 文件registryhttps://registry.npmmirror.com这个文件建议提交到 Git这样团队成员拉下代码后 npm install 会自动读取项目级配置走同一个镜像源。项目级配置的优先级高于用户级配置所以即使某个人全局配置过另一个源在这个项目里也会被覆盖。这里有个很多人容易踩的坑项目级 .npmrc 优先级太高如果你在公司私有源和镜像源之间切换容易导致某些包拉不到。正确做法是结合 scope 处理私有包比如公司私有包通常以 company 开头配置是这样registryhttps://registry.npmmirror.com company:registryhttps://npm.company.internal意思是普通公共包走淘宝镜像公司私有包仍然从公司私有源拉取。这种配置在大型团队里非常常见没有这个意识的话一旦项目里用了私有包镜像源会直接 404。2.3 进阶用 nrm 管理多套源如果你需要在官方源、淘宝源、腾讯源之间频繁切换靠 npm config set 一条条敲太机械我习惯用 nrm 这个工具。安装方式npm install -g nrm安装完成后查看可用源nrm ls输出会列出官方源、淘宝源、腾讯源等选项切换只需要nrm use taobaonrm 的本质也是修改 ~/.npmrc 文件只是帮你节省了手动记忆地址的时间。但它有一个小小的历史坑旧版本的 nrm 内置的淘宝源地址还是老的 registry.npm.taobao.org如果你发现 nrm use taobao 之后依然很慢或者报错可以先执行nrm add taobao https://registry.npmmirror.com nrm use taobao把新地址覆盖进去。有些老版本没有 add 后自动切换的逻辑加完源记得手动 nrm use 一次。nrm 适合个人开发机上多个项目来回切源的场景但在团队项目里我还是强烈建议用项目级 .npmrc而不是让每个人自己切源版本一致性问题远比快那几秒重要。2.4 附加项编译型依赖的二进制加速换源之后还有一个容易漏的部分很多 npm 包在安装时会从国外地址下载二进制文件比如 node-sass 要从 GitHub 下载编译好的 bindingElectron 要从 GitHub Release 下载预编译包sharp 要从 libvips 官方站拉二进制。这些下载路径和 registry 没有关系所以换完镜像源后安装这类包依然可能卡死。解决办法是把相关的二进制镜像也指到国内地址。在 ~/.npmrc 或项目级 .npmrc 中加入disturlhttps://npmmirror.com/mirrors/node/ sass_binary_sitehttps://npmmirror.com/mirrors/node-sass/ electron_mirrorhttps://npmmirror.com/mirrors/electron/disturl 是给 node-gyp 用的编译原生模块时它需要下载和当前 Node 版本匹配的头文件nodejs.org 直连也慢。sass_binary_site 和 electron_mirror 同理。不同包读取的配置名不一样遇到哪个包慢就去查它的文档里支持哪些 *_mirror 环境变量。把这几行加上去之后很多之前换完源仍然慢的编译场景会快一大截。3. 从零实操Ubuntu 24.04 完整配置过程3.1 环境检查先搞清楚 node 和 npm 是哪来的在开始配置镜像源之前先花一分钟确认环境。很多人以为直接执行 npm config set registry 就完事了但 node 和 npm 是怎么装的会直接影响后续权限和包目录位置。我建议先跑这三条命令node -v npm -v which node如果 which node 返回的是 /usr/bin/node说明是通过 apt 安装的全局包目录通常在 /usr/lib/node_modules 或 /usr/local/lib/node_modules这两个目录普通用户没有写权限后面全局安装容易出 EACCES。要是返回 /home/你的用户名/.nvm/versions/node/v20.x.x/bin/node说明用的是 nvm全局包装在用户目录下权限问题会少很多。另外再看一下 npm 的 prefixnpm config get prefix这个值决定了 npm install -g 时全局包装到哪里。如果是 /usr 或者 /usr/local后面遇到权限问题的概率就很高。我自己在 Ubuntu 20.04 年代用 apt 安装过 nodejs结果每次 npm install -g 都要加 sudo各种诡异的权限残留。后来彻底改用 nvm 管理 Node把所有东西都收敛到用户目录下一下子清净了。如果你还没装 Node想在 Ubuntu 24.04 上装一个 20 版本我建议直接走 nvmcurl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash source ~/.bashrc nvm install 20国内如果 raw.githubusercontent.com 访问慢可以先给 nvm 设置国内镜像export NVM_NODEJS_ORG_MIRRORhttps://npmmirror.com/mirrors/node/这样 nvm 下载 Node 二进制时会从 npmmirror 拉速度快很多。安装完 node 之后 npm 会跟着一起装上不需要单独装 npm。3.2 备份现有配置别手滑改坏任何配置操作前先备份是习惯问题虽然 .npmrc 一般就几行但万一手滑写坏排查起来很费时间。备份命令cp ~/.npmrc ~/.npmrc.bak.$(date %Y%m%d)如果之前没配置过这里会提示文件不存在直接跳过就行。备份完可以看一眼当前配置cat ~/.npmrc 2/dev/null如果里面已经有 registry 等配置说明之前有人改过先看清楚再动手。如果里面有一堆看不懂的配置尤其是 proxy 相关的行要小心这可能是之前某个工具写进去的后面出问题时优先怀疑它。3.3 正式切换镜像源并验证执行npm config set registry https://registry.npmmirror.com然后立即验证npm config get registry这里有个细节有些教程让你用 npm config set registry http://registry.npm.taobao.org 这种 http 地址但我强烈建议一律用 https。http 明文传输在链路上被篡改的风险虽然小但完全没有必要冒险更何况旧域名的 http 地址早就失效了。现在 npmmirror 的 https 地址不需要额外配置证书直接用就行。还可以进一步验证镜像源连通性curl -I https://registry.npmmirror.com/express如果返回 HTTP/2 200 之类的状态码说明网络链路没问题。如果 curl 超时那先检查服务器 DNS 或防火墙这不关 npm 的事。3.4 实测安装一个包看速度变化换完之后不要光看配置直接实测。我在 /tmp 下建了个临时项目mkdir /tmp/npm-registry-test cd /tmp/npm-registry-test npm init -y npm install express --no-audit --no-fund--no-audit 和 --no-fund 是关闭 npm 的审计检查和赞助提示在国内网络环境下这两步经常是额外的耗时环节实际项目中如果内网环境不太好也可以加上能少些等待。我用的是 express 这个中等体量的包依赖不算多安装过程比较有参考性。换源之前同样的操作会卡在 downloading 阶段换完之后几十秒就能跑完npm ls 看一眼依赖树都是完整的。如果安装过程中看到大量warning一般不用管那是依赖方内存放的 metadata 信息不完整不影响实际安装。真正要注意的是ERR!开头的行那种才叫错误warning 只是提示好多人被吓到其实是误解。3.5 检查 lockfile 里的 resolved 地址有没有跟着换项目里如果之前已经生成过 package-lock.json里面每个包的 resolved 字段会把完整的下载地址写死。比如resolved: https://registry.npmjs.org/express/-/express-4.19.2.tgz如果 lockfile 里还是官方源地址即使你全局换源npm install 时依然会根据 lockfile 里的地址去下载等于白换。遇到这种情况处理方式有两种第一种简单粗暴删除 node_modules 和 package-lock.json重新 npm install。好处是一步到位坏处是 lockfile 里的锁定版本会被重新解析如果团队里其他人还在用旧 lockfile会产生大量 diffreview 起来很痛苦。第二种保留 lockfile只更新地址npm install --registryhttps://registry.npmmirror.comnpm 会按照当前配置重写一部分 resolved 地址。实测下来这种方式能改大部分包的地址但有些锁定的旧地址残留还需要手动检查。我自己在维护老项目时一般会用 sed 做一次安全的地址替换sed -i s#registry.npmjs.org#registry.npmmirror.com#g package-lock.json然后跑一次 npm install 确认依赖树没坏。这个操作只改域名不改变版本号风险可控。但要注意如果项目里有私有包它们的 resolved 地址也是 registry.npmjs.org 形式手动全局替换会把私有包地址也改成公共镜像反而拉不到。所以替换前先 grep 看看到底有哪些域名grep -o https://[^/]* package-lock.json | sort -u把地址分布看清楚再动手。3.6 在 Docker 和 CI 环境里固化镜像配置除了本地开发机CI 构建镜像里的 npm install 同样会走官方源。Ubuntu 容器里换个源也不复杂Dockerfile 中这样处理FROM node:20-slim ENV npm_config_registryhttps://registry.npmmirror.com RUN npm install --no-audit --no-fund用 npm_config_registry 环境变量不需要额外写 .npmrc 文件构建时 npm 会自动识别。如果是 GitHub Actions 或自建 CI 平台可以在执行 npm install 之前加上npm config set registry https://registry.npmmirror.com或者直接在流水线环境变量里加 npm_config_registry。很多团队本地开发换源了但 CI 一直没换导致本地很快、构建超时这种问题非常隐蔽因为 CI 日志里不会主动告诉你用的哪个源只有慢到超时才被注意到。4. 常见问题排查实录4.1 遇到 404先看看是不是用了已经退役的淘宝域名我个人遇到过太多次这种场景了拿着老教程配置完npm install 直接报npm ERR! 404 Not Found - GET https://registry.npm.taobao.org/express不用怀疑就是域名问题。registry.npm.taobao.org 这个域名已经停止服务任何指向它的配置都会失败。正确做法是把所有配置里的域名改成 registry.npmmirror.com包括但不限于~/.npmrc项目根目录 .npmrcpackage-lock.json 中的 resolved 地址各类工具的配置文件nrm、cnpm 等排查的时候可以全盘搜索一下grep -r npm.taobao.org ~/.npmrc .npmrc package-lock.json 2/dev/null只要搜到旧域名就还能解释为什么换了源还报 404。这个坑的根因是历史教程太多时间一久大家都不记得旧域名已经退役照着复制就完蛋。以后看到包 404第一步永远先确认地址对不对不要急着怀疑镜像源本身挂了。4.2 权限报错的正确解法别一上来就 sudo在 Ubuntu 上用 apt 安装的 Node全局安装包时会频繁出现npm ERR! code EACCES npm ERR! syscall mkdir npm ERR! path /usr/lib/node_modules/xxx原因很简单Node 装在系统目录里普通用户没有写权限。很多新手的第一反应是加 sudosudo npm install -g xxx我非常不建议这么做。sudo 会把全局包装成 root 所有后续一些需要写日志、缓存的全局工具会莫名其妙地权限报错。更好的方案是用 nvm 重新安装 Node把 npm 的 prefix 指到用户目录。如果暂时不能重装可以手动设置前缀mkdir -p ~/.npm-global npm config set prefix ~/.npm-global export PATH$HOME/.npm-global/bin:$PATH然后把 export 那行加到 ~/.bashrc 里。之后全局包装在 ~/.npm-global 下不需要 sudo。实测很多开发者卡在“装了 nvm 还提示 EACCES”其实就是因为旧 apt 安装的全局目录权限没处理干净PATH 里还有 /usr/bin 的入口。检查一下 which npm 指向哪里如果还是 /usr/bin/npm说明 PATH 优先级有问题把 nvm 的 bin 目录往前放。4.3 换完源还是慢应该排查哪里换了镜像源仍然慢不要直接放弃按顺序排查第一看 registry 是否真的生效npm config get registry第二测试镜像源到服务器的真实连通性。有时候镜像源本身没问题但你的服务器到镜像源的网络链路有问题。可以用时间统计time curl -s https://registry.npmmirror.com/express | head -c 100耗时如果还在几十秒级别那就是网络链路问题换哪个源都救不了。第三检查是不是代理残留npm config get proxy npm config get https-proxy如果输出的是 http://127.0.0.1:8080 之类的地址而且这个代理已经失效npm 会尝试连代理导致所有请求超时。把代理清掉npm config delete proxy npm config delete https-proxy第四检查缓存。npm 默认会把下载过的包缓存到 ~/.npm 目录如果缓存里有损坏的 metadata可能一直重试同一个坏包。可以执行npm cache verify这个命令会校验缓存完整性比 npm cache clean --force 温和得多。npm cache clean --force 是暴力清空不到万不得已不用因为清完缓存之后首次安装会全部重新下载短时间可能更慢。4.4 全局 CLI 工具自动更新失败多半和 npm prefix 权限有关最近很多人遇到的报错auto-update failed: no write permission to npm prefix比如全局安装 claude code 这类带自动更新机制的命令行工具更新时它要往全局 node_modules 里写文件如果 npm prefix 指向系统目录普通用户没有写权限就会报这个错误。解决办法不是给系统目录 chmod 加权限那是最坏的方案而是让 npm prefix 指向用户可写的目录最干净的方式依然是 nvm 或手动 prefix 到 ~/.npm-global。检查当前 prefix npm prefix -g如果输出 /usr 或 /usr/local说明问题出在这里。配合 nvm 使用的话prefix 会指向 nvm 当前 node 版本的目录比如 /home/用户名/.nvm/versions/node/v20.11.1这个目录归当前用户所有自动更新就能正常写入了。这类问题表面上和换源无关但换源过程中很多人会顺手全局装 nrm、n 等工具装完之后发现工具无法自更新所以我把这条也写上。4.5 刚发布的新包拉不到不用反复切源镜像源同步官方仓库有一定延迟正常情况下几分钟就能追上但偶尔会有新发布的包在镜像源上暂时找不到。这时候不要立即怀疑配置有问题我的处理办法是单次安装临时指定官方源npm install 某新包 --registryhttps://registry.npmjs.org只对这一次安装生效不会污染全局配置。等镜像源同步完成后续安装还是走镜像源。如果急着发布新包的人是你自己发布到公共仓库后记得隔几分钟再验证一下镜像源不要在还没同步完成时反复切换源或者删缓存那样解决不了问题。另外还有一种 404 是新包名拼写错误或者私有包没授权会返回npm ERR! 404 Not Found - GET https://registry.npmmirror.com/scope/pkg这类情况和镜像源无关先去 npm 官网确认包名和权限不要被 404 带偏。5. 写在最后我习惯保留的几个操作换源这件事本身不难难的是形成一套稳定习惯。我现在的固定做法是个人机器上用 nrm 管理多套源日常默认淘宝 npmmirror需要排查问题时切回官方源对比团队项目里在仓库根目录放一份 .npmrc 并提交到 Git公共包走镜像源私有包走公司源大家拉代码后第一次 npm install 就能用不需要口头交代“你换一下源”。编译型项目还会额外加上 disturl 和二进制镜像配置避免换完 registry 之后卡在 node-sass 或 Electron 上。遇到过太多次有人遇到安装问题就执行 npm cache clean --force其实大部分时候是域名、权限或者网络链路问题清缓存不仅解决不了还让后续安装重新下载大量数据。我现在只在确定缓存损坏时才会碰缓存相关命令日常维护只用 npm cache verify。另外每次在 Ubuntu 新机器上配置完 Node 环境我都会把 which node、npm prefix -g、npm config get registry 这三个输出截一下图或者存档后续排查问题能快速定位环境来源。镜像源只是工具链里很小的一环但配置对了之后Ubuntu 下的 Node 开发体验能提升一大截。少一点 waiting多一点 console这种快乐用过就回不去了。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进