.npmrc 官方有 21 个配置项,但日常用到的就 10 来个。这篇是按使用频次排序的实战指南——每个配置都配可直接复制的 .ini 块,最后给 4 类典型场景的完整 .npmrc 模板、5 个错误码速查、10 条 FAQ、npm vs pnpm vs yarn 对比。

一、文件位置与优先级

1
2
3
4
5
6
7
8
# 项目级(仅当前项目生效,提交到 git 给整个团队用)
项目根/.npmrc

# 用户级(所有项目生效,只对自己)
~/.npmrc

# 全局级(系统级,所有用户的兜底)
/etc/npmrc

优先级:项目级 > 用户级 > 全局级。同一字段多处定义时,项目级赢。

1
2
3
4
5
# 查看当前生效的所有配置(合并后)
npm config list

# 含默认值的所有项(以 ; 开头的就是默认值)
npm config list -l | grep "^;"

实战建议:项目级 .npmrc 必须提交到 git;用户级只放”个人偏好”(如 init-author-email),不要放会影响团队构建的设置(如 registry、proxy);全局级基本不用。

二、12 个高频配置详解

1. registry — npm 镜像源

1
registry=https://registry.npmmirror.com/

国内项目必加。默认 https://registry.npmjs.org/ 在国内经常 30 秒超时。

镜像 URL 特点
阿里 https://registry.npmmirror.com/ 速度最快,淘宝团队维护
腾讯 https://mirrors.cloud.tencent.com/npm/ 偶尔更稳
中科大 https://mirrors.ustc.edu.cn/npm/ 学术网首选
npm 官方 https://registry.npmjs.org/ 海外服务器无障碍

scope 镜像(只对 @scope/ 包换源,私有包常用):

1
2
3
@my-company:registry=https://npm.internal.company.com/
@types:registry=https://registry.npmmirror.com/
@babel:registry=https://registry.npmmirror.com/

临时切换(不写文件):

1
2
npm install xxx --registry=https://registry.npmmirror.com/
# 一次性用,不影响其他命令

2. save-exact — 锁版本

1
save-exact=true

npm install xxx 默认写 "xxx": "^1.2.3"(范围),团队里两台机器可能装到不同次版本。save-exact=true 写精确版本 "xxx": "1.2.3",避免”我本地能跑你跑不了”。

注意:开了 save-exactnpm install 不带版本时仍会装 latest。建议同步加

1
2
3
4
save-exact=true
engine-strict=true
fund=false
audit=false

3. legacy-peer-deps — 跳过 peer 依赖检查

1
legacy-peer-deps=true

npm 7+ 严格检查 peer dependencies,老项目升级时常常报:

1
2
3
npm error ERESOLVE could not resolve
npm error While resolving: react@18.2.0
npm error Found: react@17.0.2

legacy-peer-deps=true 回到 npm 6 的宽松模式。仅在确认依赖没问题时用——它会隐藏真正的版本冲突。

对比

模式 行为 适用
npm 6 宽松 peer 检查 维护老项目
npm 7+ 默认 严格 peer 检查 新项目
legacy-peer-deps=true 强制宽松 npm 7+ 跑老项目
strict-peer-deps=true 强制严格 锁版本严格

4. engine-strict — 强制 Node 版本

1
engine-strict=true

如果 package.json 写了:

1
"engines": { "node": ">=18" }

不开这个,Node 16 装时只警告;开了就直接报错。生产项目必开,本地开发可以不开。

5. ignore-scripts — 跳过 install 钩子

1
ignore-scripts=true

postinstallpreinstall 等脚本可能跑恶意代码(历史上 event-stream 事件就是被攻击的)。在不可信环境下装包时开它。

典型场景

1
2
3
4
5
# CI 里跑陌生 PR 的依赖装包时
npm ci --ignore-scripts

# 本地装某个可疑包
npm install some-pkg --ignore-scripts

注意:开了之后很多包的关键功能会失效

  • husky(git hooks)
  • patch-package
  • prisma generate
  • electron-rebuild
  • 任何用 postinstall 跑构建脚本的包

生产构建别开

6. proxy / https-proxy — 代理

1
2
proxy=http://127.0.0.1:7890
https-proxy=http://127.0.0.1:7890

公司内网访问 npm 仓库需要代理。或用 npm config get proxy 先确认默认值。

noproxy 排除(内网仓库不走代理):

1
2
3
proxy=http://127.0.0.1:7890
https-proxy=http://127.0.0.1:7890
noproxy=localhost,127.0.0.1,.internal.company.com

踩坑:proxy 配错会导致”卡在 idealTree:building: sill idealTree buildDeps“长时间无响应。建议先 curl -I https://registry.npmjs.org/ 测试代理可达性。

7. audit / audit-level — 关漏洞审计

1
2
audit=false
audit-level=high # 只报 high/critical

npm install 默认会跑 npm audit 查漏洞,有时要 30+ 秒。CI 上跑一次还好,本地反复装包时累。

建议配置

  • audit=high:只显示 high/critical,跳过 moderate/low
  • audit=false:完全关掉(自己另跑 npm audit

audit 报告解读

1
2
3
4
npm audit --json
# 看具体漏洞
npm audit fix # 自动升级补丁版本
npm audit fix --force # 升级 major(破坏性变更,慎用)

8. prefer-offline / cache — 优先用缓存

1
2
prefer-offline=true
cache=~/.npm-cache

网络差的时候救命。prefer-offline 让 npm 先查本地缓存,没命中再走网络。cache 指定缓存目录到 SSD 或大硬盘。

验证缓存命中

1
2
ls ~/.npm-cache/_cacache/content-v2/sha512/ | wc -l
# 1000+ 说明缓存有不少

清理缓存(磁盘不够时):

1
2
3
npm cache clean --force
# 删 ~/.npm 整个目录也行
rm -rf ~/.npm

9. loglevel — 控制日志噪音

1
loglevel=warn

可选值:silent / error / warn / info / http / verbose。日常 warn 够安静,CI 跑 verbose 看细节。

调试网络问题时改 http,看完整的 HTTP 请求:

1
loglevel=http

10. package-lock — 锁文件

1
package-lock=true

默认 true,别关。包锁文件能保证团队装的版本一致。

.gitignore 别忽略它(默认就不忽略)。如果 package-lock.json 提交后 PR 频繁冲突,说明团队没装好依赖,先 npm ci 同步再开发。

11. dry-run / yes — 自动确认

1
yes=true

npm init / npm create 时的 Are you sure? 自动 yes。谨慎开——只在自己熟悉的场景。

12. init-* — 项目初始化默认值

1
2
3
4
5
init-author-name=Kevin
init-author-email=kevin@example.com
init-author-url=https://kevin.com
init-license=MIT
init-version=0.0.1

npm init -y 时自动填这些,避免每次手输。

三、4 类典型 .npmrc 完整模板

模板 1:国内小团队

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# registry 镜像
registry=https://registry.npmmirror.com/

# 版本严格
save-exact=true
engine-strict=true

# CI 友好
audit=high
loglevel=warn
fund=false

# scope 镜像(私有包走自己的源)
@my-company:registry=https://npm.internal.company.com/

模板 2:企业内网

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 强制走公司内网仓库
registry=https://npm.internal.company.com/

# 代理出内网
proxy=http://proxy.internal:8080
https-proxy=http://proxy.internal:8080
noproxy=localhost,127.0.0.1,.internal.company.com

# 严格审计
audit=true
engine-strict=true
always-auth=true

# 自签证书(内网常遇到)
strict-ssl=false

模板 3:前端项目(多框架混用)

1
2
3
4
5
6
7
8
9
10
save-exact=true
legacy-peer-deps=true
engine-strict=true

# 加快 install
prefer-offline=true
audit=high

# 包锁文件必提交
package-lock=true

模板 4:CI/CD(GitHub Actions)

1
2
3
4
5
6
7
8
# 严格模式
save-exact=true
engine-strict=true
audit=true
fund=false

# 用 npm ci 更快(要求 lock 文件存在)
package-lock=true

对应 GitHub Actions 片段:

1
2
3
4
5
6
7
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

四、5 个常见错误码速查

错误 原因 解决
ETARGET package.json engine 字段与当前 Node 不符 升级 Node 或设 engine-strict=false
ERESOLVE peer dep npm 7+ 严格 peer 检查 legacy-peer-deps=true
EACCES permissions 全局安装需要 sudo 改用 nvm 管理 Node,或 chown 全局目录
ECONNRESET / ETIMEDOUT 网络问题或镜像源挂了 换镜像 / 开 prefer-offline / 检查代理
EPEERINVALID 装的两个包 peer 要求冲突 升级冲突的包,或装 --legacy-peer-deps

调试流程(错误时按顺序):

1
2
3
4
5
6
7
8
9
10
11
12
# 1. 清除缓存
rm -rf node_modules package-lock.json
npm cache clean --force

# 2. 验证网络
curl -I https://registry.npmmirror.com/

# 3. 详细日志
npm install xxx --loglevel=verbose

# 4. 跳过问题
npm install xxx --legacy-peer-deps --force

五、CI 集成模板(GitHub Actions)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
name: CI
on: [push, pull_request]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

# 用 npm ci 走 lock 文件,install 速度比 npm install 快 2-3 倍
- run: npm ci
env:
# 私有包需要 token
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

- run: npm run build
- run: npm test

npm ci vs npm install

命令 行为 速度 适用
npm ci node_modules 后按 lock 重装 快 2-3 倍 CI 必用
npm install 按 lock 增量装 本地开发
npm install pkg 装新包 加依赖时

私有 registry token 配置

1
2
3
# .npmrc(项目级)
@my-company:registry=https://npm.internal.company.com/
//npm.internal.company.com/:_authToken=${NPM_TOKEN}

GitHub Secrets 配置 NPM_TOKEN,env 注入到 npm ci 即可。

六、npm vs pnpm vs yarn 配置差异

配置 npm pnpm yarn
锁文件 package-lock.json pnpm-lock.yaml yarn.lock
镜像源 registry= registry= registry=https://registry.npmmirror.com/
锁版本 save-exact=true save-exact=true --save-exact flag
peer 依赖 legacy-peer-deps auto-install-peers=true nodeLinker: node-modules(Yarn Berry)
离线缓存 prefer-offline offline=true --prefer-offline flag
安装速度 慢(npm 7+ 改进) 最快(硬链接复用) 快(Yarn 3+)

多 package manager 团队.npmrcpnpm-workspace.yaml 要并行维护,写好注释避免混淆。项目里只能用一种engines + packageManager 字段锁住)。

七、10 条常见 FAQ

Q1:项目级 .npmrc 要不要提交到 git?
要。团队共享。

Q2:改了 .npmrc 不生效?

  • npm config list 输出,确认生效的是哪一份
  • 大小写敏感(Windows 上)
  • npm config get registry 测一下

Q3:私有 registry 的 token 安全吗?

  • .npmrc 里的 _authToken 别提交到 git
  • .npmrc 全局 + ~/.npmrc,加到 .gitignore(项目级 .npmrc 也别含 token)
  • CI 用 NODE_AUTH_TOKEN 环境变量

Q4:.npmrc 和 package-lock.json 哪个优先?

  • .npmrc 控制 npm 行为(registry/proxy/版本策略)
  • package-lock.json 记录依赖树
  • 两者都该有,互补

Q5:怎么知道某个包从哪个 registry 装的?

1
2
npm config get registry
npm ls --all # 看依赖树

Q6:npm install 卡在 sill idealTree 很久?
网络问题。开 prefer-offline 或换镜像。

Q7:能多个 registry 混用吗?
能,用 scope 镜像:

1
2
@scope-a:registry=https://reg-a.com/
@scope-b:registry=https://reg-b.com/

Q8:怎么清缓存里某个包?

1
2
3
npm cache clean <pkg-name>  # npm 不支持
# 实际只能全清
npm cache clean --force

Q9:可以用 yarn.lock 替换 package-lock.json 吗?
不能直接换。需要:

  1. package-lock.jsonnode_modules
  2. yarn install 生成 yarn.lock
  3. 团队统一改用 yarn

Q10:.npmrc 在 Docker 镜像里怎么处理?

  • DockerfileCOPY .npmrc ./ 后再 RUN npm ci
  • 私有 token 用 docker build --build-arg NPM_TOKEN=xxx 注入
  • 别在镜像里留 .npmrc(含 token),用 multi-stage build 在最终 stage 删掉

八、查所有可用项

1
2
3
npm config list                    # 当前生效
npm config list -l | grep "^;" # 含默认的所有项
man npmrc # 完整文档

完整文档:docs.npmjs.com/cli/v10/configuring-npm/npmrc

九、推荐配置(生产用)

把它当默认起点,项目里根据自己的情况微调:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# ===== registry =====
registry=https://registry.npmmirror.com/

# ===== 版本严格 =====
save-exact=true
engine-strict=true
package-lock=true

# ===== install 优化 =====
prefer-offline=true
audit=high
fund=false
loglevel=warn

# ===== 团队协作 =====
init-author-name=Your Team
init-license=MIT

国内项目用它起步,出问题再针对具体场景调(如老项目加 legacy-peer-deps,企业内网换 registry)。

十、.npmrc 全 21 项速查表

默认 何时用
registry https://registry.npmjs.org/ 换镜像/私有源
save-exact false 团队项目必开
save-prefix ^ ~ 或精确版本
save-prod true 装 dev 依赖时改 false
save-dev false 命令行 npm i -D
legacy-peer-deps false npm 7+ 跑老项目
strict-peer-deps false 锁版本严格
engine-strict false 生产项目必开
ignore-scripts false 不可信环境装包
proxy / https-proxy 内网代理
noproxy 代理排除
strict-ssl true 自签证书改 false
audit true CI 跑、本地关
audit-level low high=只报高危
prefer-offline false 网络差
offline false 强制离线
cache ~/.npm 改到大盘
loglevel info warn / http / verbose
package-lock true 别关
dry-run false CI 测试用
yes false 自动化初始化
init-author-* npm init 默认值
fund true 关闭打赏提示
workspaces-update true monorepo 时
update-notifier true 关闭升级提示

十一、.npmrc vs package.json engines 字段

很多人搞混这两者:

维度 .npmrc package.json engines
作用对象 npm CLI 行为 包对运行环境的要求
谁能改 项目维护者(自己写) 项目维护者(写进 dependencies)
影响范围 当前项目(项目级)或用户所有项目(用户级) 任何安装本包的项目
被谁读 npm CLI npm install 时校验
示例 registry=... "engines": {"node": ">=18"}

关系.npmrc 决定怎么装engines 决定能不能装。两者互补。

engines 完整示例

1
2
3
4
5
6
7
{
"engines": {
"node": ">=18.0.0",
"npm": ">=9.0.0",
"pnpm": ">=8.0.0"
}
}

volta / nvm 替代

1
2
3
4
5
6
{
"volta": {
"node": "20.10.0",
"npm": "10.2.3"
}
}

Volta 在团队里更流行(自动切换版本)。.nvmrc 也是常见选择(node -v > .nvmrc)。

十二、故障排查完整流程

遇到 npm install 错误时按这个顺序查:

第一步:清缓存

1
2
3
rm -rf node_modules package-lock.json
npm cache clean --force
npm install --loglevel=verbose 2>&1 | tee /tmp/npm-install.log

tee 把日志存下来,方便贴到 issue。

第二步:检查网络

1
2
3
4
5
# 直接 curl 测镜像源
curl -I https://registry.npmmirror.com/

# 如果用代理,测试代理可达
curl -I --proxy http://127.0.0.1:7890 https://registry.npmjs.org/

第三步:单包测试

1
2
3
# 用最小 package.json 试
echo '{}' > /tmp/test.json
cd /tmp && npm install lodash --loglevel=verbose

如果单包能装,是项目配置问题;不能装是环境问题。

第四步:检查 Node/npm 版本

1
2
3
4
node -v
npm -v
which node
which npm

版本不匹配最常见:用 nvm 装多版本,按项目切:

1
2
3
4
nvm install 18
nvm install 20
nvm use 20 # 当前 shell
nvm alias default 20 # 默认

.nvmrc 自动切换:

1
2
3
# 项目根 .nvmrc 写 20
echo "20" > .nvmrc
nvm use # 自动读 .nvmrc

第五步:检查权限

1
2
ls -la /usr/local/lib/node_modules
ls -la ~/.npm

全局包权限问题多发。别 sudo——用 nvm 把 Node 装在用户目录。

十三、monorepo 实战

pnpm 是 monorepo 的事实标准,但 npm workspaces 也够用:

1
2
3
4
5
6
7
{
"name": "my-monorepo",
"workspaces": [
"packages/*",
"apps/*"
]
}
1
2
3
4
# .npmrc(项目级)
save-exact=true
link-workspace-packages=true
prefer-workspace-packages=true
1
2
3
# 在 monorepo 根目录装包
npm install lodash -w @my-company/web
npm install typescript -D -w @my-company/shared

monorepo 专有 .npmrc

1
2
3
4
5
6
7
# 用 npm 7+ 自带 workspace(不用 pnpm/yarn)
workspaces-update=true
workspaces-experimental=true # 早期实验功能

# 解决 workspace 间 hoisting 问题
install-strategy=nested
install-links=true

十四、3 个真实案例

案例 1:老 React 项目升级 React 18

错误:

1
2
npm error While resolving: react@18.2.0
npm error Found: react@17.0.2

解决:加 legacy-peer-deps=true,然后逐步升级 peer 依赖。

案例 2:内网 Nexus 私有仓库

.npmrc

1
2
3
4
registry=https://nexus.internal.company.com/repository/npm-hosted/
@nexus-internal:registry=https://nexus.internal.company.com/repository/npm-private/
strict-ssl=false # 内网自签证书
always-auth=true

nexus.internal.company.com 的 token 配在 .npmrc

1
//nexus.internal.company.com/repository/npm-hosted/:_authToken=YOUR_TOKEN

案例 3:CI 跑陌生 PR 防供应链攻击

1
2
3
4
5
- name: Install with script-blocking
run: npm ci --ignore-scripts --no-audit

- name: Run audit only on direct deps
run: npm audit --omit=dev

--ignore-scripts 防恶意 postinstall;--omit=dev 只审计生产依赖,跳过 devDependencies 减少噪音。

十五、性能调优

用 pnpm 替代 npm(提速 3-5 倍)

1
2
npm install -g pnpm
pnpm install # 直接用,硬链接复用

不需要 .npmrc 改任何东西。pnpm 自己的配置在 ~/.pnpmrcpnpm-workspace.yaml

用 corepack 锁定 package manager

1
2
3
corepack enable
# package.json 里加
"packageManager": "pnpm@8.15.0"

团队用 corepack prepare pnpm@8.15.0 --activate 装指定版本,避免 pnpm/npm/yarn 混用导致的 lock 文件不兼容。

增量安装(适合 monorepo)

1
2
3
4
5
# 只装某 workspace 的依赖
npm install --workspace @my-company/web

# 增量装单包
npm install lodash --save --workspace @my-company/api

十六、最容易踩的 5 个坑

  1. proxy 配错导致卡死——loglevel=http 看到 CONNECT 阶段就知道代理问题
  2. .npmrc 留了 token 提交到 git——git log -p .npmrc 查历史
  3. save-exact=true 没生效——engines 字段不写版本号也无效
  4. engine-strict=true 严格度过高——本地 Node 18 跑 Node 20 项目会失败,可临时 engine-strict=false
  5. 多 .npmrc 嵌套——项目级被用户级覆盖是常见问题,用 npm config get <key> 确认实际生效值

十七、参考资源


总结.npmrc 配置 90% 的项目只需 5 项(registry / save-exact / engine-strict / audit / cache),剩下的按需加。CI 上多开 audit=true,本地多开 prefer-offline,团队统一 .npmrc 提交 git。

十八、4 个补充场景配置

场景 1:lock 文件冲突解决

1
2
3
4
5
# 团队里 lock 冲突了,强制统一
rm package-lock.json
npm install
git add package-lock.json
git commit -m "chore: regenerate lock"

预防:合并 PR 时先 npm ci 一遍,确认 lock 一致再合。

场景 2:私有 npm 包发布

自己组织内发布 @my-company/utils 类的私有包:

1
2
3
4
# .npmrc(项目级)
registry=https://registry.npmjs.org/
@my-company:registry=https://npm.pkg.github.com/
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}

发布命令:

1
2
npm login --registry=https://npm.pkg.github.com/ --scope=@my-company
npm publish

场景 3:Docker 多阶段构建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 阶段 1:装依赖
FROM node:20-alpine AS deps
WORKDIR /app
COPY package*.json .npmrc ./
RUN npm ci --ignore-scripts

# 阶段 2:构建
FROM node:20-alpine AS build
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build

# 阶段 3:生产镜像
FROM node:20-alpine
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY --from=deps /app/node_modules ./node_modules
COPY package*.json ./
USER node
CMD ["node", "dist/index.js"]

注意:构建阶段和运行阶段都装 .npmrc(含 token 用 build-arg 注入),但最终镜像用 multi-stage 把 .npmrc 留在 deps 阶段不复制到 final。

场景 4:GitHub Packages + 公共 npm 混用

1
2
3
4
5
6
7
8
# 默认公共 registry
registry=https://registry.npmjs.org/

# 自己的 scope 走 GitHub Packages
@my-org:registry=https://npm.pkg.github.com/

# 必要认证
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}

安装时自动从对应 registry 拉取:

1
2
npm install @my-org/utils  # 走 GitHub Packages
npm install lodash # 走 npm 公共

十九、给新手的 5 个起步配置

完全没设过 .npmrc?从这 5 项开始:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1. 国内镜像(速度)
registry=https://registry.npmmirror.com/

# 2. 锁版本(团队一致)
save-exact=true

# 3. 严格 Node 版本(防环境差异)
engine-strict=true

# 4. 包锁文件必提交
package-lock=true

# 5. CI 友好
audit=true

贴到项目根 .npmrc,提交 git,团队所有人 npm ci 一次就同步了。别从 .gitignore 排除 .npmrc

二十、最后的小贴士

  • 复制别人项目的 .npmrc 时,先把 registry 改成自己团队的(特别是私有 registry)
  • 加了 .npmrc 但效果不对,先 npm config get <key> 查实际生效值(合并后)
  • Node.js 升级后 npm 也会自动升级,跨大版本后建议删 lock 重装
  • .npmrc 嵌套 项目里用 npm config get registry 看实际生效的是哪一份
  • lock 文件大(>5MB)通常是 monorepo 或装太多包,正常

二十一、npm install 4 个阶段解析

知道这 4 阶段能帮你定位 install 卡在哪:

1
2
3
4
1. idealTree:building    # 解析依赖树,下载 package.json
2. reify:create # 创建 node_modules 目录
3. reify:resolve # 解析所有包的实际版本
4. reify:extract # 解压包到 node_modules

常见卡点

  • 卡在 idealTree: sill idealTree buildDeps → 网络/registry 问题
  • 卡在 reify:extract → 磁盘慢(SSD vs HDD 差 10 倍)
  • 卡在 reify:resolve → peer deps 冲突,开 legacy-peer-deps

加速技巧

1
2
3
4
5
# 用 npm ci 代替 npm install(CI 必用)
npm ci --prefer-offline --no-audit --no-fund

# 看具体哪一步慢
npm install --timing # 输出每步耗时

二十二、完整项目 .npmrc 实战示例

一个中型 Node.js + TypeScript 项目的完整 .npmrc:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# ===== registry =====
registry=https://registry.npmmirror.com/

# ===== 镜像 scope =====
@my-company:registry=https://npm.internal.company.com/
@types:registry=https://registry.npmmirror.com/

# ===== 版本控制 =====
save-exact=true
engine-strict=true
package-lock=true

# ===== 安装优化 =====
prefer-offline=true
cache=~/.npm-cache

# ===== 行为 =====
audit=high
fund=false
loglevel=warn

# ===== CI 特殊 =====
# 在 CI 环境变量里加 NPM_CONFIG_FUND=false
# 关闭打赏提示加速

对应的 GitHub Actions

1
2
3
4
5
6
7
8
9
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'npm'

- run: npm ci
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_CONFIG_AUDIT: 'true'

engines 字段package.json):

1
2
3
4
5
6
{
"engines": {
"node": ">=20.0.0",
"npm": ">=10.0.0"
}
}

volta 字段(自动切换 Node 版本):

1
2
3
4
5
6
{
"volta": {
"node": "20.10.0",
"npm": "10.2.3"
}
}

这套组合拳让团队开发体验统一且稳定

  • .nvmrcvolta 决定 Node 版本
  • engines 校验
  • .npmrc 决定 npm 行为
  • package-lock.json 锁依赖
  • CI 用 npm ci 严格按 lock 装

二十三、版本演进历史

了解 .npmrc 演变能理解为什么有些配置看起来多余:

  • npm 5 之前:没有 .npmrc.lock 概念,所有依赖范围都允许
  • npm 7(2021):引入 strict peer deps,破坏了大量老项目
  • npm 7+:引入 overrides 字段(package.json 里),可以强制覆盖子依赖版本
  • npm 9(2022):默认开启 audit,引入 overrides 文档
  • npm 10(2023):改进 lockfile 性能,引入 install-strategy=hoisted/nested/shallow

overrides 示例package.json 里强制覆盖子依赖):

1
2
3
4
5
6
7
8
{
"overrides": {
"lodash": "4.17.21",
"axios": {
"follow-redirects": "1.15.0"
}
}
}

当某个传递依赖有安全漏洞,但顶层包没更新时,用 overrides 强制升级。

overrides vs .npmrclegacy-peer-deps

  • overrides:精确控制子依赖版本(推荐)
  • legacy-peer-deps:跳过 peer 检查(粗放)

新项目用 overrides 解决依赖冲突,老项目临时用 legacy-peer-deps 续命。

二十四、最后一句

.npmrc 看似琐碎,但它是项目从”我机器能跑”变成”团队都能跑”的关键一步。花 10 分钟配好它,能省下未来无数次”为什么你跑得起来我跑不起来”的调试时间。