包管理器深度解析:npm / yarn / pnpm 实战指南

前言

在现代前端工程化体系中,包管理器是整个依赖生态的基石。从 npm installpnpm add,每一次包管理器的选择都在悄然影响着项目的安装速度、磁盘占用和协作体验。本文档将深入剖析三大主流包管理器的核心差异,并提供生产环境级别的最佳实践。


技术概述与定位

包管理器在现代前端生态中的角色

包管理器是现代前端开发不可或缺的核心工具,它解决了以下关键问题:

依赖管理:自动化下载、安装、更新和卸载项目依赖。

版本控制:确保团队成员使用相同版本的依赖包。

锁文件机制:保证在不同环境下构建结果的一致性。

发布管理:简化包发布到 npm registry 的流程。

JavaScript 包管理器发展史

npm (2010) → Bower (2011) → Component (2012) → Browserify (2013)
     ↓                              ↓
  Yarn (2016)               Webpack (2014)
     ↓                              ↓
  npm 5+ (2017) ←─────────────── 整合时代 (2016-2019)
     ↓
  pnpm (2017) → Turbo (2020) → pnpm 8+ (2023)

三大主流包管理器定位对比

包管理器创建时间创建者核心优势定位
npm2010Isaac Z. Schlueter最大生态、兼容性最好企业级标准
yarn2016Facebook离线缓存、并行安装大型团队协作
pnpm2017Zoltan Kochan极速、节省磁盘现代高效开发

技术选型建议

选择 npm 的场景

  • 需要最大兼容性
  • 团队对现有工具有依赖
  • 企业环境有特殊配置要求

选择 yarn 的场景

  • 大型团队协作项目
  • 需要稳定的离线能力
  • 已经习惯 yarn 工作流

选择 pnpm 的场景

  • 新项目快速启动
  • Monorepo 大型项目
  • 对磁盘空间敏感
  • 追求极致安装速度

包管理器的核心价值

在现代前端开发中,包管理器已经不仅仅是一个安装工具,而是整个开发生态系统的核心枢纽:

依赖解析:现代包管理器不仅仅是简单地下载和安装包,还需要处理复杂的依赖解析、版本冲突、循环依赖等问题。pnpm 的严格依赖隔离机制能够提前发现潜在的依赖问题,而 npm 和 yarn 则通过扁平化结构提供了更大的灵活性。

锁文件机制:锁文件是保证团队协作和构建一致性的关键。不同的锁文件格式反映了各自的设计哲学:npm 的 package-lock.json 采用 JSON 格式,易于程序化处理;yarn 的 yarn.lock 采用 YAML 格式,可读性更强;pnpm 的 pnpm-lock.yaml 包含了 workspace 的完整信息。

性能优化:安装速度直接影响开发体验和 CI/CD 效率。根据 benchmark 数据,pnpm 在大多数场景下比 npm 快 2-3 倍,比 yarn 快 1.5-2 倍。这种性能优势在大型项目中尤为明显。


完整安装与配置

npm 安装与配置

安装与升级

# 安装 Node.js(npm 随 Node.js 一起安装)
# 推荐使用 nvm 管理 Node.js 版本
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
 
# 验证安装
nvm --version
 
# 安装特定版本 Node.js
nvm install 20
nvm install --lts  # 安装最新 LTS 版本
 
# 切换 Node.js 版本
nvm use 20
nvm alias default 20  # 设置默认版本
 
# 升级 npm
npm install -g npm@latest
 
# 验证版本
npm --version  # 10.x.x
node --version  # 20.x.x

npm 配置文件 (.npmrc)

# ===== 基础配置 =====
 
# 设置 npm registry
registry=https://registry.npmjs.org/
 
# 使用国内镜像(可选)
registry=https://registry.npmmirror.com
 
# 设置包缓存目录
cache=~/.npm
 
# 设置临时目录
tmp=/tmp/npm
 
# ===== 用户信息 =====
# 登录 npm 账户
npm adduser
npm login
 
# 查看当前用户
npm whoami
 
# ===== 安装配置 =====
 
# 安装时保存到 dependencies
save=true
 
# 安装时保存到 devDependencies
save-dev=true
 
# 安装时保存到 optionalDependencies
save-optional=true
 
# 安装时添加精确版本号
save-exact=true
 
# 安装时包含 peer dependencies
legacy-peer-deps=true
 
# 不安装 peer dependencies
legacy-peer-deps=false
 
# ===== 其他配置 =====
 
# 启用颜色输出
color=true
 
# 不显示进度条
progress=false
 
# 显示 npm 输出
loglevel=info
 
# 启用审计
audit=true
 
# 执行审计后继续
audit-level=low

yarn 安装与配置

安装与升级

# 使用 npm 安装
npm install -g yarn
 
# 使用 Corepack 安装(Node.js 16.10+ 内置)
corepack enable
corepack prepare yarn@stable --activate
 
# 升级 yarn
yarn set version stable
 
# 验证安装
yarn --version  # 4.x.x

yarn 配置文件

# ===== .yarnrc 文件 =====
 
# 设置 registry
registry "https://registry.npmjs.org/"
 
# 启用离线缓存
enableOfflineCache true
 
# 设置缓存目录
cacheFolder ".yarn/cache"
 
# 启用压缩
compressionLevel 9
 
# 启用全局缓存
enableGlobalCache true
 
# 离线模式
yarn_offline_mirror "./.yarn-mirrors"
 
# ===== .yarnrc.yml 文件(Yarn Berry)=====
 
# Yarn Berry 配置文件
packageExtensions:
  "@types/react@*":
    dependencies:
      react: "*"
 
# 插件配置
plugins:
  - path: .yarn/plugins/@yarnpkg/plugin-exec.cjs
    spec: "https://yarnpkg.com/plugin-exec"
 
# 设置 nodeLinker
nodeLinker: node-modules
 
# 或使用 PnP(Plug'n'Play)
nodeLinker: pnp

pnpm 安装与配置

安装与升级

# 使用 npm 安装
npm install -g pnpm
 
# 使用 Corepack 安装(Node.js 16.10+)
corepack enable
corepack prepare pnpm@stable --activate
 
# 使用安装脚本
curl -fsSL https://get.pnpm.io/install.sh | sh -
 
# 升级 pnpm
pnpm add -g pnpm@latest
 
# 验证安装
pnpm --version  # 9.x.x

pnpm 配置文件

# ===== .npmrc 文件 =====
 
# 设置 registry
registry=https://registry.npmjs.org/
 
# 使用国内镜像
registry=https://registry.npmmirror.com
 
# 启用 shamefully-hoist(提升 node_modules)
shamefully-hoist=true
 
# 启用 public-hoist-pattern
public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=*prettier*
public-hoist-pattern[]=*stylelint*
 
# 启用自动安装 peer dependencies
auto-install-peers=true
 
# 严格 peer dependencies 检查
strict-peer-dependencies=false
 
# ===== pnpm-workspace.yaml =====
packages:
  - 'packages/*'
  - 'apps/*'
  - 'tools/*'
  # 排除特定目录
  - '!**/test/**'
  - '!**/__tests__/**'
  - '!**/node_modules/**'

全局配置示例

# ===== 创建项目目录 =====
mkdir my-project && cd my-project
 
# ===== 初始化项目 =====
npm init -y
# 或带参数初始化
npm init -y \
  --name "@scope/project-name" \
  --version "1.0.0" \
  --description "项目描述" \
  --author "Your Name <email@example.com>" \
  --license "MIT"
 
# ===== 创建 .gitignore =====
cat > .gitignore << 'EOF'
node_modules/
dist/
build/
.env
.env.local
*.log
.DS_Store
coverage/
.cache/
.vscode/
.idea/
EOF
 
# ===== 初始化 git =====
git init
git add .
git commit -m "Initial commit"

企业环境配置

对于企业环境,通常需要额外的配置来满足安全和管理需求:

# ===== 企业 .npmrc 配置 =====
 
# 私有 registry
registry=https://npm.my-company.com
@my-scope:registry=https://npm.my-company.com
 
# 认证令牌
# //npm.my-company.com/:_authToken=${NPM_TOKEN}
 
# 代理设置
proxy=http://proxy.my-company.com:8080
https-proxy=http://proxy.my-company.com:8080
 
# 安全设置
engine-strict=true
 
# 审计配置
audit=true
audit-level=high
 
# 性能优化
fetch-retries=5
fetch-retry-mintimeout=20000
fetch-retry-maxtimeout=120000

核心概念详解

核心对比:安装速度、磁盘占用与 Lockfile

1.1 架构差异决定性能上限

三大包管理器的底层架构存在本质区别:

特性npmyarnpnpm
存储方式扁平化 node_modules扁平化 node_modules内容寻址存储 (CAS)
依赖复用同一包多版本共存同一包多版本共存硬链接同一版本包
安装速度中等中等最快 (并行+硬链接)
磁盘占用最高最低 (可节省 50-90%)
Lockfile 格式JSONYAMLYAML

npm 的问题:扁平化地狱

npm 3 引入的扁平化 node_modules 解决了路径过深问题,但带来了新的困扰:

project/
└── node_modules/
    ├── lodash/              # A 依赖的 4.17.20
    │   └── package.json
    │
    └── @scope/
        └── pkg/
            └── node_modules/
                └── lodash/  # B 依赖的 4.17.21,重复安装!
                    └── package.json

# 问题:
# 1. 磁盘空间浪费
# 2. 依赖解析不一致
# 3. npm dedupe 效果有限
# 4. 依赖遮蔽可能导致意外行为

pnpm 的解决方案:硬链接 + 内容寻址

pnpm 使用 Content Addressable Storage (CAS) 架构:

~/.pnpm-store/                    # 全局 Store(只存一份)
└── content-addressable-store/
    └── sha512/
        └── a3/
            └── .../ # 包的校验和路径
            
projects/
├── project-a/
│   └── node_modules/
│       └── .pnpm/
│           └── lodash@4.17.21/
│               └── node_modules/
│                   └── lodash -> 硬链接到 Store
│
└── project-b/
    └── node_modules/
        └── .pnpm/
            └── lodash@4.17.21/
                └── node_modules/
                    └── lodash -> 同一个硬链接!

# 优势:
# 1. 同一版本的包只存一份
# 2. 跨项目复用
# 3. 节省 50-90% 磁盘空间

1.2 安装速度基准测试

# ===== 清理测试环境 =====
rm -rf node_modules package-lock.json pnpm-lock.yaml yarn.lock
 
# ===== 冷启动测试(无缓存)=====
time npm install   # 典型时间: 45-90s
time yarn install  # 典型时间: 35-80s
time pnpm install  # 典型时间: 15-40s
 
# ===== 增量安装测试(有缓存)=====
time npm install   # 典型时间: 10-20s
time yarn install  # 典型时间: 5-15s
time pnpm install  # 典型时间: 2-5s

pnpm 极速的原因

  1. 并行下载:使用 Promise.all 并发下载多个包
  2. 硬链接复用:已存在的包直接硬链接,无需重新下载
  3. 跳过重复解析:CAS 直接定位,无需递归解析依赖树
  4. 全局 Store:所有项目共享同一个 Store

1.3 Lockfile 对比

npm 的 package-lock.json
{
  "name": "my-project",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "my-project",
      "version": "1.0.0"
    },
    "node_modules/lodash": {
      "version": "4.17.21",
      "resolved": "https://registry.npmjs.org/lodash/--4.17.21.tgz",
      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
    },
    "node_modules/@babel/core": {
      "version": "7.23.0",
      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.0.tgz",
      "integrity": "sha512-..."
    }
  }
}

特点

  • 包含完整的依赖树信息
  • npm ci 严格按 lockfile 安装
  • 不包含可选依赖的完整信息
  • lockfileVersion 3 支持目录嵌套结构
yarn 的 yarn.lock
lodash@4.17.21:
  version "4.17.21"
  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz"
  integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
 
"@babel/core@npm:^7.23.0":
  version "7.23.0"
  resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.0.tgz"
  integrity sha512-...
  dependencies:
    "@babel/code-frame" "^7.22.13"
    "@babel/generator" "^7.23.0"

特点

  • Yarn 1 采用 YAML 格式,语义更清晰
  • Yarn Berry (Berry/PnP) 使用 .yarnrc.yml
  • 支持 plugins 扩展
  • workspace 信息完整
pnpm 的 pnpm-lock.yaml
lockfileVersion: '6.0'
 
settings:
  autoInstallPeers: true
  excludeLinksFromLockfile: false
 
importers:
  .:
    specifiers:
      lodash: ^4.17.21
      typescript: ^5.0.0
    dependencies:
      lodash: 4.17.21
    devDependencies:
      typescript: 5.3.3
 
  packages/my-lib:
    specifiers:
      react: ^18.0.0
    dependencies:
      react: 18.2.0
 
packages:
  /lodash/4.17.21:
    resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
    engines: {node: '>=4'}
    dev: false
    optional: false
 
  /@babel/code-frame/7.22.13:
    resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9KsX9f7}
    engines: {node: '>=6.9.0'}
    dev: false
    optional: false
    dependencies:
      '@types/babel__traverse': 7.20.1

特点

  • 包含 workspace 完整信息
  • 支持 shamefully-hoist 兼容模式
  • 严格遵循 semver 规范
  • 自动安装 peer dependencies

npm Scripts 高级用法

2.1 生命周期脚本

npm 提供了完整的生命周期钩子:

{
  "name": "my-package",
  "version": "1.0.0",
  "scripts": {
    "prepublishOnly": "npm test",      // 发布前运行
    "preversion": "npm test",          // 版本更新前运行
    "version": "git add -A",           // 版本号更新后运行
    "postversion": "git push && git push --tags",  // 发布后运行
    "preinstall": "node scripts/check-node-version.js",  // 安装前
    "postinstall": "husky install",    // 安装后
    "preuninstall": "echo 'Uninstalling...'",  // 卸载前
    "postuninstall": "echo 'Uninstall complete'",  // 卸载后
    "pretest": "echo 'Running tests...'",  // 测试前
    "posttest": "echo 'Tests complete'",  // 测试后
    "prestart": "echo 'Starting...'",  // 启动前
    "poststart": "echo 'Server started'",  // 启动后
    "prestop": "echo 'Stopping...'",  // 停止前
    "poststop": "echo 'Stopped'",  // 停止后
    "prebuild": "echo 'Building...'",  // 构建前
    "postbuild": "echo 'Build complete'"  // 构建后
  }
}

执行顺序:当运行 npm version 1.0.0 时:

  1. preversion → 运行测试
  2. 更新 package.json 版本号
  3. version → git add -A
  4. postversion → git push

2.2 跨平台兼容

使用 cross-env 处理环境变量
{
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "build:dev": "cross-env NODE_ENV=development vite",
    "build:prod": "cross-env NODE_ENV=production vite build",
    "build:staging": "cross-env NODE_ENV=staging vite build"
  }
}
使用 npm-run-all 并行/串行执行
{
  "scripts": {
    "dev": "npm-run-all --parallel dev:client dev:server",
    "build": "npm-run-all --sequential clean build:client build:server",
    "lint": "npm-run-all --parallel lint:js lint:css lint:types",
    "test": "npm-run-all --parallel test:unit test:e2e"
  }
}
使用 concurrently 同时运行多个进程
{
  "scripts": {
    "dev": "concurrently \"npm:dev:server\" \"npm:dev:client\" \"npm:dev:docs\"",
    "dev:server": "nodemon server/index.js",
    "dev:client": "vite --port 3000",
    "dev:docs": "vitepress dev docs"
  }
}
使用 rimraf 跨平台删除
{
  "scripts": {
    "clean": "rimraf dist coverage node_modules",
    "reinstall": "rimraf node_modules && npm install"
  }
}

2.3 条件脚本 (npm 8.3+)

现代 npm 支持基于条件的脚本选择:

{
  "scripts": {
    "dev": "vite",
    "dev:win": "vite.exe",
    "build": "vite build",
    "build:win": "vite.exe build"
  }
}
# Unix 系统执行
npm run dev
 
# Windows 系统自动执行
npm run dev:win

2.4 脚本参数传递

# 传递参数给底层命令(使用 -- 分隔)
npm run build -- --mode production --minify
 
# 使用 npm_config_* 访问配置
# package.json
{
  "scripts": {
    "build": "vite build --mode $npm_config_mode"
  }
}
 
# 执行时传入
npm run build --config_mode=production
 
# 环境变量方式
{
  "scripts": {
    "build": "NODE_ENV=production vite build"
  }
}
 
# Windows 兼容
npm install -D cross-env
{
  "scripts": {
    "build": "cross-env NODE_ENV=production vite build"
  }
}

package.json 最佳实践

3.1 exports 字段:精确控制导出

{
  "name": "my-awesome-lib",
  "version": "1.0.0",
  "exports": {
    ".": {
      "import": {
        "types": "./dist/index.d.ts",
        "default": "./dist/index.mjs"
      },
      "require": {
        "types": "./dist/index.d.ts",
        "default": "./dist/index.cjs"
      },
      "browser": "./dist/index.browser.js"
    },
    "./utils": {
      "types": "./utils/index.d.ts",
      "import": "./utils/index.mjs",
      "require": "./utils/index.cjs"
    },
    "./package.json": "./package.json"
  },
  "main": "./dist/index.cjs",
  "module": "./dist/index.mjs",
  "types": "./dist/index.d.ts",
  "files": [
    "dist"
  ]
}

exports 的优势

  • 替代 main/module/types,提供更精确的控制
  • 支持条件导出(CJS/ESM/browser)
  • 可以隐藏内部模块
  • Node.js 12.16+ 支持

3.2 sideEffects 字段:Tree Shaking 优化

// 声明全部为纯函数(都可 tree-shaking)
"sideEffects": false
 
// 只标记有副作用的文件
"sideEffects": [
  "dist/styles.css",
  "src/polyfills.js",
  "src/effects/analytics.ts"
]
 
// 空数组 = 无副作用
"sideEffects": []

Tree Shaking 工作原理

// src/utils.js
export const add = (a, b) => a + b;
export const multiply = (a, b) => a * b;
 
// src/side-effect.js
import { createAnalytics } from './analytics';
createAnalytics(); // 副作用
 
// package.json
{
  "sideEffects": ["./src/side-effect.js"]
}
 
// 结果:build 时只打包使用的代码
// add 和 multiply 如果没被 import 就不会被打包
// 但 side-effect.js 一定会被打包

3.3 engines 字段:环境约束

{
  "engines": {
    "node": ">=18.0.0",
    "npm": ">=9.0.0",
    "pnpm": ">=8.0.0"
  }
}

注意engines 默认不强制执行,需配合 .npmrc

# .npmrc
engine-strict=true

pnpm 强制执行

# pnpm 默认强制执行 engines
engine-strict=true

3.4 files 字段:发布控制

{
  "files": [
    "dist",
    "types",
    "!dist/**/*.map",
    "README.md",
    "LICENSE"
  ]
}

规则说明

  • dist - 包含构建输出
  • types - 包含 TypeScript 类型定义
  • !dist/**/*.map - 排除 source maps
  • README.md - 包含 README
  • LICENSE - 包含许可证

发布时自动排除

  • node_modules(自动排除)
  • .gitignore 中的文件
  • files 字段白名单之外的文件

3.5 publishConfig:发布特定配置

{
  "name": "@my-org/my-lib",
  "publishConfig": {
    "registry": "https://npm.my-org.com",
    "access": "restricted",
    "tag": "beta",
    "directory": "dist"
  }
}

3.6 funding 字段:赞助信息

{
  "funding": {
    "type": "opencollective",
    "url": "https://opencollective.com/my-project"
  }
}
 
// 或者多个赞助选项
{
  "funding": [
    {
      "type": "github",
      "url": "https://github.com/sponsors/username"
    },
    {
      "type": "opencollective",
      "url": "https://opencollective.com/my-project"
    }
  ]
}

Workspace Monorepo 配置

4.1 npm Workspace

// 根 package.json
{
  "name": "my-monorepo",
  "private": true,
  "workspaces": [
    "packages/*",
    "apps/*",
    "tools/*"
  ],
  "scripts": {
    "dev": "npm run dev --workspace=@my/app",
    "build": "turbo run build",
    "test": "turbo run test",
    "clean": "turbo run clean",
    "lint": "turbo run lint"
  }
}

4.2 pnpm Workspace

# pnpm-workspace.yaml
packages:
  - 'packages/*'
  - 'apps/*'
  - 'tools/*'
  # 排除测试目录
  - '!packages/**/test/**'
  - '!packages/**/node_modules/**'

pnpm workspace 优势

  • 自动创建 .pnpm 虚拟存储
  • 支持 workspace 协议引用本地包
  • 更严格的依赖隔离
// packages/my-lib/package.json
{
  "name": "@my/shared-ui",
  "version": "1.0.0",
  "dependencies": {
    "@my/utils": "workspace:*",      // 始终指向本地最新
    "@my/utils": "workspace:^1.0.0", // 匹配 semver 范围
    "@my/utils": "workspace:~1.0.0"   // 匹配补丁版本
  }
}

4.3 yarn Workspace

// 根 package.json
{
  "name": "my-monorepo",
  "private": true,
  "workspaces": [
    "packages/*",
    "apps/*"
  ],
  "install": {
    "hoistingLimits": "dependencies"
  }
}

Yarn Berry PnP 模式

# .yarnrc.yml
nodeLinker: pnp
 
plugins:
  - path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
    spec: "@yarnpkg/plugin-workspace-tools"

4.4 完整 Monorepo 结构示例

my-monorepo/
├── package.json                  # 根 workspace
├── pnpm-workspace.yaml         # pnpm workspace 配置
├── turbo.json                  # Turborepo 配置
├── .npmrc                      # npm/pnpm 配置
├── .nvmrc                      # Node.js 版本
├── .editorconfig               # 编辑器配置
│
├── apps/
│   ├── web/                    # 主 Web 应用
│   │   ├── package.json
│   │   ├── tsconfig.json
│   │   ├── vite.config.ts
│   │   └── src/
│   │       ├── App.tsx
│   │       ├── main.tsx
│   │       └── components/
│   │
│   ├── admin/                  # 管理后台
│   │   ├── package.json
│   │   └── src/
│   │
│   └── docs/                   # 文档站点
│       ├── package.json
│       └── docs/
│
├── packages/
│   ├── shared-ui/              # 共享 UI 组件库
│   │   ├── package.json
│   │   ├── tsconfig.json
│   │   ├── src/
│   │   │   ├── Button/
│   │   │   ├── Card/
│   │   │   └── Modal/
│   │   └── dist/
│   │
│   ├── shared-utils/           # 共享工具库
│   │   ├── package.json
│   │   └── src/
│   │       ├── format.ts
│   │       ├── validate.ts
│   │       └── storage.ts
│   │
│   ├── shared-types/           # 共享类型定义
│   │   ├── package.json
│   │   └── index.ts
│   │
│   └── shared-constants/       # 共享常量
│       ├── package.json
│       └── src/
│           ├── api.ts
│           └── config.ts
│
└── tools/
    ├── eslint-config/          # 共享 ESLint 配置
    │   ├── package.json
    │   └── index.js
    │
    ├── tsconfig/               # 共享 TypeScript 配置
    │   ├── base.json
    │   ├── react.json
    │   └── nextjs.json
    │
    └── vite-config/            # 共享 Vite 配置
        ├── package.json
        └── base.ts

常用命令与操作

npm 常用命令

# ===== 安装命令 =====
npm install                    # 安装所有依赖
npm install <package>         # 安装包
npm install <package>@1.0.0   # 安装指定版本
npm install <package>@latest   # 安装最新版本
npm install -D <package>       # 安装到 devDependencies
npm install -O <package>       # 安装到 optionalDependencies
npm install -g <package>       # 全局安装
 
# ===== 包信息 =====
npm view <package>            # 查看包信息
npm info <package>            # 同 view
npm show <package>            # 同 view
npm outdated                  # 检查过时包
npm ls                        # 列出已安装包
npm ls <package>              # 查看特定包
 
# ===== 更新命令 =====
npm update                    # 更新所有包
npm update <package>          # 更新特定包
npm update -g                 # 更新全局包
npx npm-check-updates         # 检查可更新的包
 
# ===== 卸载命令 =====
npm uninstall <package>       # 卸载包
npm remove <package>          # 同 uninstall
npm rm <package>             # 同 uninstall
npm uninstall -D <package>     # 卸载 devDependencies
npm uninstall -g <package>    # 卸载全局包
 
# ===== 缓存管理 =====
npm cache clean --force        # 清理缓存
npm cache verify               # 验证缓存
 
# ===== 发布命令 =====
npm publish                    # 发布包
npm publish --access public    # 发布公开包
npm publish --tag beta        # 发布到 beta 标签
npm unpublish <package>       # 取消发布
npm deprecate <package>        # 弃用包
 
# ===== 其他命令 =====
npm init                       # 初始化项目
npm pack                        # 打包为 .tgz
npm login                       # 登录 npm
npm logout                      # 登出
npm whoami                      # 查看当前用户
npm explore <package>          # 查看包目录
npm link                        # 创建全局链接
npm bin                         # 查看 bin 目录

yarn 常用命令

# ===== 安装命令 =====
yarn install                  # 安装所有依赖
yarn add <package>            # 添加包
yarn add <package>@1.0.0      # 添加指定版本
yarn add -D <package>          # 添加到 devDependencies
yarn add -P <package>         # 添加 peerDependencies
yarn add -g <package>          # 全局安装
 
# ===== 包信息 =====
yarn info <package>           # 查看包信息
yarn list                     # 列出已安装包
yarn list --pattern <package>  # 列出特定包
 
# ===== 更新命令 =====
yarn upgrade                  # 更新所有包
yarn upgrade <package>         # 更新特定包
yarn upgrade-interactive      # 交互式更新
 
# ===== 卸载命令 =====
yarn remove <package>          # 移除包
yarn remove <package> -D       # 移除 devDependencies
 
# ===== 脚本命令 =====
yarn run <script>             # 运行脚本
yarn dev                       # 运行开发脚本
yarn build                     # 运行构建脚本
yarn test                      # 运行测试
 
# ===== 其他命令 =====
yarn init                      # 初始化项目
yarn init -y                   # 快速初始化
yarn why <package>            # 查看包依赖原因
yarn disambiguation            # 包解析
yarn policies set-version      # 设置 Yarn 版本

pnpm 常用命令

# ===== 安装命令 =====
pnpm install                  # 安装所有依赖
pnpm add <package>           # 添加包
pnpm add <package>@1.0.0     # 添加指定版本
pnpm add -D <package>         # 添加到 devDependencies
pnpm add -w <package>        # 添加到 workspace 根目录
pnpm add -g <package>         # 全局安装
 
# ===== 包信息 =====
pnpm list                    # 列出已安装包
pnpm list <package>           # 查看特定包
pnpm why <package>            # 查看包依赖原因
 
# ===== 更新命令 =====
pnpm update                  # 更新所有包
pnpm update <package>         # 更新特定包
pnpm up                      # 同 update
pnpm up <package>             # 更新特定包
 
# ===== 卸载命令 =====
pnpm remove <package>         # 移除包
pnpm rm <package>             # 同 remove
pnpm uninstall <package>       # 同 remove
 
# ===== 其他命令 =====
pnpm import                   # 从 package-lock.json 导入
pnpm store status            # 查看 store 状态
pnpm store prune            # 清理未使用的包
pnpm env use                 # 使用特定 Node.js 版本
pnpm init                    # 初始化项目
pnpm patch                   # 创建补丁
pnpm patch-commit            # 提交补丁
 
# ===== Workspace 命令 =====
pnpm -r <command>            # 在所有 workspace 运行命令
pnpm -r --filter <pkg> <cmd> # 在特定 workspace 运行命令
pnpm --filter <pattern> ...   # 过滤 workspace

高级配置与技巧

企业级 .npmrc

# ===== .npmrc 企业配置 =====
 
# ===== Registry 配置 =====
registry=https://registry.npmmirror.com
 
# 私有 Registry(可选)
# @scope:registry=https://npm.my-company.com
# //npm.my-company.com/:_authToken=${NPM_TOKEN}
 
# ===== 安装行为 =====
strict-peer-dependencies=false
save-exact=true
legacy-peer-deps=true
prefer-dedupe=true
 
# ===== 构建优化 =====
omit=dev          # 生产环境安装跳过 devDependencies
production=true   # 同 omit=dev
 
# ===== pnpm 特有配置 =====
shamefully-hoist=false
public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=*prettier*
public-hoist-pattern[]=*stylelint*
public-hoist-pattern[]=*tailwindcss*
public-hoist-pattern[]=*postcss*
public-hoist-pattern[]=*autoprefixer*
auto-install-peers=true
resolution-mode=highest
 
# ===== 网络优化 =====
fetch-retries=5
fetch-retry-mintimeout=10000
fetch-retry-maxtimeout=60000
fetch-timeout=300000
 
# ===== 缓存配置 =====
cache=~/.npm
prefix=~/.npm-global

CI 环境优化

GitHub Actions 配置

# .github/workflows/ci.yml
name: CI
 
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
 
jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'  # 或 'pnpm', 'yarn'
      
      - name: Install dependencies
        run: pnpm install --frozen-lockfile --prefer-offline
        env:
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
      
      - name: Type check
        run: pnpm run typecheck
      
      - name: Lint
        run: pnpm run lint
      
      - name: Test
        run: pnpm run test
      
      - name: Build
        run: pnpm run build
      
      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: dist
          path: dist/

GitLab CI 配置

# .gitlab-ci.yml
stages:
  - install
  - test
  - build
 
variables:
  NPM_CONFIG_PREFIX: "${CI_PROJECT_DIR}/.npm-global"
 
cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - .npm/
    - node_modules/
 
install:
  stage: install
  image: node:20-alpine
  script:
    - npm ci --prefer-offline
  artifacts:
    paths:
      - node_modules/
 
test:
  stage: test
  image: node:20-alpine
  script:
    - npm run test
    - npm run lint
 
build:
  stage: build
  image: node:20-alpine
  script:
    - npm run build
  artifacts:
    paths:
      - dist/

Docker 配置

# Dockerfile
FROM node:20-alpine AS builder
 
WORKDIR /app
 
# 复制 package files
COPY package.json pnpm-lock.yaml ./
 
# 安装依赖
RUN corepack enable && corepack prepare pnpm@stable --activate
RUN pnpm install --frozen-lockfile --prod
 
# 复制源代码
COPY . .
 
# 构建
RUN pnpm run build
 
# 生产镜像
FROM node:20-alpine AS runner
 
WORKDIR /app
 
# 从 builder 复制构建产物
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
 
ENV NODE_ENV=production
 
EXPOSE 3000
 
CMD ["node", "dist/index.js"]

依赖安全审计

# ===== npm audit =====
npm audit                # 审计依赖
npm audit fix           # 自动修复
npm audit fix --force   # 强制修复
npm audit --json        # JSON 格式输出
 
# ===== yarn audit =====
yarn audit              # 审计依赖
 
# ===== pnpm audit =====
pnpm audit             # 审计依赖
pnpm audit --fix       # 自动修复
 
# ===== 安全最佳实践 =====
# 1. 定期更新依赖
npx npm-check-updates -u
pnpm up -r
 
# 2. 锁定关键依赖版本
{
  "resolutions": {
    "lodash": "4.17.21"
  }
}
 
# 3. 使用替代包
# - 替换 eval() 使用的包
# - 替换已知漏洞的包

性能优化技巧

# ===== 使用 ci 安装(CI 环境推荐)=====
npm ci                   # 精确按 lockfile 安装
yarn install --frozen-lockfile  # 冻结 lockfile
pnpm install --frozen-lockfile  # 冻结 lockfile
 
# ===== 离线模式 =====
npm ci --offline        # 离线安装
yarn install --offline  # 离线安装
pnpm install --offline  # 离线安装
 
# ===== 使用 prefer-offline 加速 =====
npm install --prefer-offline    # 优先使用缓存
pnpm install --prefer-offline   # 优先使用缓存
 
# ===== 减少安装内容 =====
npm install --production    # 不安装 devDependencies
npm ci --omit=dev          # 同上
pnpm install --prod        # 不安装 devDependencies
 
# ===== 增量安装 =====
pnpm install              # pnpm 默认增量安装

高级依赖管理技巧

依赖版本范围管理

{
  "dependencies": {
    "react": "^18.2.0",      // ^: 允许次版本和补丁更新
    "react-dom": "~18.2.0",   // ~: 允许补丁更新
    "lodash": ">=4.0.0",     // >=: 最小版本限制
    "next": "14.x",           // x: 匹配任意版本
    "preact": "*"              // *: 任意版本(不推荐)
  }
}

依赖覆盖(Overrides)

{
  "overrides": {
    // 覆盖单个包
    "lodash": "4.17.21",
    
    // 覆盖嵌套依赖
    "webpack": {
      "webpack-bundle-analyzer": "4.9.0"
    },
    
    // 使用 $ 前缀引用原始版本
    "react": {
      "$original": "^18.0.0",
      "loose-envify": "^1.1.0"
    }
  }
}

依赖预取和懒加载

# 使用 npm pack 创建离线包
npm pack <package-name>
 
# pnpm 预取
pnpm add <package> --prefer-offline
 
# yarn 离线镜像
yarn config set yarn-offline-mirror ./yarn-offline-mirror
yarn install --offline

与同类技术对比

详细功能对比表

特性npmyarnpnpm
安装速度⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
磁盘效率⭐⭐⭐⭐⭐⭐⭐⭐⭐
Lockfile 格式JSONYAMLYAML
离线支持⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
Workspace 支持原生原生原生
Monorepo 体验⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
Node.js 版本要求10+10+14+
peerDependencies警告警告严格安装
幽灵依赖
全局缓存

性能基准测试

# ===== 测试命令 =====
# 项目:create-react-app (约 1400 依赖)
# 环境:MacBook Pro M1, 16GB RAM
 
# 冷安装(首次安装)
npm ci     # ~45-60s
yarn      # ~35-50s
pnpm      # ~15-25s
 
# 增量安装(添加一个包)
npm add lodash    # ~5-10s
yarn add lodash   # ~3-8s
pnpm add lodash   # ~1-3s
 
# 更新所有依赖
npm update        # ~30-45s
yarn upgrade      # ~20-35s
pnpm update       # ~10-20s

使用场景对比

场景推荐原因
新项目快速启动pnpm安装速度最快
大型 Monorepopnpm严格的依赖隔离
企业内部项目npm/pnpm兼容性最好
开源项目均可根据团队偏好
CI/CD 环境pnpm速度最快
遗留项目npm兼容性最好

包管理器选择决策树

开始选择包管理器
│
├─ 项目规模?
│   ├─ 小型(< 50 依赖)→ 任意选择
│   ├─ 中型(50-500 依赖)→ pnpm 或 yarn
│   └─ 大型(> 500 依赖)→ pnpm(必需)
│
├─ 团队技术栈?
│   ├─ 已有 npm 经验 → npm
│   ├─ 已有 yarn 经验 → yarn
│   └─ 新团队 → pnpm(推荐)
│
├─ 是否需要离线开发?
│   ├─ 是 → yarn 或 pnpm
│   └─ 否 → 任意选择
│
└─ Monorepo 项目?
    ├─ 是 → pnpm(强烈推荐)
    └─ 否 → 任意选择

常见问题与解决方案

问题1:peer dependencies 警告

症状

npm warn ERESOLVE overriding peer dependency
npm warn ERESOLVE peer dependency "react@>=17.0.0" is not satisfied

原因:包声明的 peer dependencies 与实际安装的版本不匹配

解决方案

# 方法1:忽略 peer dependencies 警告(npm)
npm install --legacy-peer-deps
 
# 方法2:强制安装 peer dependencies(npm)
npm install --force
 
# 方法3:配置 .npmrc
echo "legacy-peer-deps=true" >> .npmrc
 
# 方法4:pnpm 自动安装
# pnpm 默认会安装 peer dependencies
# 如需禁用
echo "auto-install-peers=false" >> .npmrc
 
# 方法5:使用 overrides
{
  "overrides": {
    "styled-components": {
      "react": "18.2.0",
      "react-dom": "18.2.0"
    }
  }
}

问题2:幽灵依赖问题

症状

// 项目中引用了未声明的包
import _ from 'lodash'; // 未在 package.json 中声明
 
// 但由于其他包的 node_modules 包含它,代码能正常运行

原因:npm/yarn 的扁平化 node_modules 导致

解决方案

# 使用 pnpm(默认隔离)
npm install -g pnpm
 
# pnpm 使用严格的虚拟存储
pnpm install
 
# pnpm 会报错:ERR_PNPM_PEER_DEP_ISSUES

问题3:Lockfile 冲突

症状

error: Your lockfile needs to be updated, but package.json was not.
error: cannot work with "package-lock.json" because the lockfile's version is 2

原因:不同版本的 npm 生成不同格式的 lockfile

解决方案

# 方法1:从 lockfile 重新安装
npm ci                    # npm
pnpm import               # 从 npm/yarn 导入 pnpm
 
# 方法2:删除 lockfile 重新生成
rm package-lock.json
npm install
 
# 方法3:统一团队的工具版本
# package.json
{
  "engines": {
    "npm": ">=9.0.0"
  }
}
 
# .npmrc
engine-strict=true

问题4:安装失败/网络问题

症状

npm ERR! network timeout
npm ERR! fetch failed
npm ERR! ECONNREFUSED

解决方案

# 方法1:使用镜像
npm config set registry https://registry.npmmirror.com
 
# 方法2:使用代理
npm config set proxy http://proxy.example.com:8080
npm config set https-proxy http://proxy.example.com:8080
 
# 方法3:清理缓存重试
npm cache clean --force
npm install
 
# 方法4:使用离线缓存
npm install --prefer-offline
 
# 方法5:增加超时时间
npm config set fetch-timeout 300000
npm config set fetch-retry-mintimeout 10000

问题5:磁盘空间不足

症状

npm ERR! ENOSPC: no space left on device

解决方案

# 方法1:使用 pnpm(节省空间)
npm install -g pnpm
pnpm import
rm -rf node_modules
pnpm install
 
# 方法2:清理 npm 缓存
npm cache clean --force
 
# 方法3:清理 pnpm store
pnpm store status
pnpm store prune
 
# 方法4:删除 yarn 缓存
yarn cache clean
 
# 方法5:使用 PNPM_HOME 自定义缓存位置
export PNPM_HOME=/path/to/large/disk/.pnpm

问题6:包版本不一致

症状

Package A requires B@^1.0.0
Package C requires B@^2.0.0
Both B@1.0.0 and B@2.0.0 are installed

原因:不同包依赖同一包的不同主版本

解决方案

# 使用 npm dedupe
npm dedupe
 
# 使用 yarn deduplicate
yarn deduplicate
 
# pnpm 默认自动去重
# 对于主版本冲突,考虑:
# 1. 升级到统一的版本
# 2. 使用 alias 引用不同版本
{
  "dependencies": {
    "lodash4": "npm:lodash@4",
    "lodash3": "npm:lodash@3"
  }
}

实战项目示例

示例1:企业级 Monorepo 配置

// 根 package.json
{
  "name": "enterprise-monorepo",
  "version": "1.0.0",
  "private": true,
  "type": "module",
  "workspaces": [
    "apps/*",
    "packages/*",
    "tools/*"
  ],
  "scripts": {
    "dev": "turbo run dev",
    "build": "turbo run build",
    "test": "turbo run test",
    "lint": "turbo run lint",
    "typecheck": "turbo run typecheck",
    "clean": "turbo run clean",
    "format": "prettier --write \"**/*.{ts,tsx,json,md}\"",
    "prepare": "husky install"
  },
  "devDependencies": {
    "@turbo/test-utils": "workspace:*",
    "eslint": "^8.50.0",
    "husky": "^8.0.3",
    "prettier": "^3.0.3",
    "turbo": "^1.11.0",
    "typescript": "^5.2.2"
  },
  "engines": {
    "node": ">=18.0.0",
    "pnpm": ">=8.0.0"
  },
  "packageManager": "pnpm@8.10.0"
}
# pnpm-workspace.yaml
packages:
  - 'apps/*'
  - 'packages/*'
  - 'tools/*'
  - '!apps/**/test/**'
  - '!packages/**/test/**'
// apps/web/package.json
{
  "name": "@enterprise/web",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview",
    "test": "vitest",
    "lint": "eslint src",
    "typecheck": "tsc --noEmit"
  },
  "dependencies": {
    "@enterprise/ui": "workspace:*",
    "@enterprise/utils": "workspace:*",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.16.0"
  },
  "devDependencies": {
    "@types/react": "^18.2.0",
    "@types/react-dom": "^18.2.0",
    "@vitejs/plugin-react": "^4.2.0",
    "typescript": "^5.2.0",
    "vite": "^5.0.0",
    "vitest": "^1.0.0"
  }
}

示例2:库发布配置

// packages/my-lib/package.json
{
  "name": "@my-org/my-lib",
  "version": "1.0.0",
  "description": "一个高性能的 TypeScript 工具库",
  "type": "module",
  "main": "./dist/index.cjs",
  "module": "./dist/index.js",
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.js",
      "require": "./dist/index.cjs"
    },
    "./utils": {
      "types": "./dist/utils.d.ts",
      "import": "./dist/utils.js",
      "require": "./dist/utils.cjs"
    },
    "./package.json": "./package.json"
  },
  "files": [
    "dist"
  ],
  "sideEffects": false,
  "scripts": {
    "build": "tsup",
    "test": "vitest",
    "lint": "eslint src",
    "typecheck": "tsc --noEmit",
    "prepublishOnly": "npm run build && npm run test"
  },
  "keywords": [
    "utils",
    "typescript",
    "helper"
  ],
  "author": "My Org <dev@my-org.com>",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "https://github.com/my-org/my-lib"
  },
  "bugs": {
    "url": "https://github.com/my-org/my-lib/issues"
  },
  "peerDependencies": {
    "react": ">=16.8.0"
  },
  "devDependencies": {
    "@types/react": "^18.2.0",
    "react": "^18.2.0",
    "tsup": "^7.2.0",
    "typescript": "^5.2.0",
    "vitest": "^1.0.0"
  },
  "engines": {
    "node": ">=16.0.0"
  }
}

附录:常见问题速查

npm/yarn/pnpm 常用命令对照

功能npmyarnpnpm
安装依赖npm installyarn installpnpm install
添加包npm add yarn add pnpm add
添加开发依赖npm add -D yarn add -D pnpm add -D
移除包npm remove yarn remove pnpm remove
更新包npm updateyarn upgradepnpm update
执行脚本npm run yarn <script>pnpm
清理缓存npm cache cleanyarn cache cleanpnpm store prune
锁定版本安装npm ciyarn install —frozen-lockfilepnpm install —frozen-lockfile
查看依赖树npm lsyarn listpnpm list
升级到最新npm update -gyarn global upgradepnpm update -g

package.json 字段速查

字段说明示例
name包名称”my-package”
version版本号”1.0.0”
description描述”一个有用的包”
main主入口文件”./dist/index.js”
moduleESM 入口”./dist/index.mjs”
typesTypeScript 类型”./dist/index.d.ts”
exports导出配置{ ”.”: “./dist/index.js” }
files发布包含文件[“dist”]
scripts脚本命令{ “build”: “tsc” }
dependencies生产依赖{ “react”: “^18.0.0” }
devDependencies开发依赖{ “typescript”: “^5.0.0” }
peerDependencies对等依赖{ “react”: ”>=16.0.0” }
optionalDependencies可选依赖{ “fsevents”: “^2.0.0” }
engines环境要求{ “node”: ”>=18.0.0” }
sideEffects副作用标记false
repository仓库地址”github:user/repo”
keywords关键词[“utils”, “helper”]
author作者”Name
license许可证”MIT”
funding赞助信息”https://…”

Semver 版本规则

major.minor.patch

1.2.3
│ │ │
│ │ └── Patch: 补丁版本,不影响 API 兼容性
│ └── Minor: 次版本,新增功能,向后兼容
└── Major: 主版本,破坏性变更
范围含义示例
^1.2.3>=1.2.3 <2.0.01.x.x 最新
~1.2.3>=1.2.3 <1.3.01.2.x 最新
>=1.0.0>=1.0.0无上限
1.0.0 - 2.0.0>=1.0.0 2.0.0范围限制
*最新版本任意版本
1.x.x>=1.0.0 <2.0.0同 ^1.0.0

附录:配置文件模板

企业级 .npmrc 模板

# ===== 基础配置 =====
registry=https://registry.npmmirror.com
cache=~/.npm
prefix=~/.npm-global
 
# ===== 安装配置 =====
save-exact=true
legacy-peer-deps=false
strict-peer-dependencies=false
prefer-dedupe=true
 
# ===== 构建优化 =====
production=false
omit=dev
 
# ===== 网络配置 =====
fetch-retries=5
fetch-retry-mintimeout=10000
fetch-retry-maxtimeout=60000
fetch-timeout=300000
 
# ===== pnpm 配置 =====
shamefully-hoist=false
auto-install-peers=true
public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=*prettier*
public-hoist-pattern[]=*stylelint*
public-hoist-pattern[]=*tailwindcss*

package.json 生产模板

{
  "name": "@scope/my-package",
  "version": "1.0.0",
  "description": "A well-documented package",
  "type": "module",
  "main": "./dist/index.cjs",
  "module": "./dist/index.js",
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.js",
      "require": "./dist/index.cjs"
    }
  },
  "files": [
    "dist"
  ],
  "sideEffects": false,
  "scripts": {
    "build": "tsup",
    "dev": "tsup --watch",
    "test": "vitest",
    "test:coverage": "vitest --coverage",
    "lint": "eslint src",
    "lint:fix": "eslint src --fix",
    "typecheck": "tsc --noEmit",
    "format": "prettier --write src",
    "prepublishOnly": "pnpm run build && pnpm run test"
  },
  "keywords": [
    "typescript",
    "utils",
    "helpers"
  ],
  "author": "Your Name <email@example.com>",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "https://github.com/scope/my-package"
  },
  "peerDependencies": {
    "react": ">=16.8.0"
  },
  "devDependencies": {
    "typescript": "^5.2.0",
    "tsup": "^7.2.0",
    "vitest": "^1.0.0",
    "@types/node": "^20.0.0",
    "eslint": "^8.50.0",
    "prettier": "^3.0.0"
  },
  "engines": {
    "node": ">=16.0.0",
    "pnpm": ">=8.0.0"
  }
}

Turborepo 配置模板

{
  "$schema": "https://turbo.build/schema.json",
  "globalDependencies": [
    ".env"
  ],
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", ".next/**", "build/**"],
      "cache": true
    },
    "dev": {
      "cache": false,
      "persistent": true
    },
    "lint": {
      "dependsOn": ["^build"],
      "outputs": []
    },
    "test": {
      "dependsOn": ["build"],
      "outputs": ["coverage/**"],
      "cache": true
    },
    "typecheck": {
      "dependsOn": ["^build"],
      "cache": true
    }
  }
}

附录:包管理器性能对比数据

安装速度对比(大型项目)

包管理器冷启动增量安装锁定安装磁盘占用
npm45-60s10-20s30-45s~500MB
yarn35-50s8-15s25-40s~400MB
pnpm15-25s2-5s10-15s~100MB

测试项目规格

# 测试环境
# - 操作系统: macOS 14 (Apple Silicon M3)
# - Node.js: 20.x
# - 网络: 100Mbps
 
# 测试项目: create-react-app (约 1400 依赖)
# - node_modules: ~32000 文件
# - 依赖树深度: ~5 层
 
# 测试命令
hyperfine --warmup 3 \
  'rm -rf node_modules && npm ci' \
  'rm -rf node_modules && yarn install --frozen-lockfile' \
  'rm -rf node_modules && pnpm install --frozen-lockfile'

依赖解析性能

操作npmyarnpnpm
解析 100 个包~5s~4s~1s
解析 500 个包~25s~20s~5s
解析 1000 个包~60s~50s~12s

附录:常见错误码与解决方案

npm 错误码

错误码含义解决方案
ERESOLVE版本冲突使用 --legacy-peer-deps 或调整依赖版本
ENOSPC磁盘空间不足清理缓存或删除不必要的依赖
ECONNREFUSED网络连接失败检查网络或更换 registry
EACCES权限不足使用 sudo 或修复 npm 目录权限
ENOENT文件不存在重新安装或清理缓存
EBADENGINE引擎版本不匹配更新 Node.js 版本
EPEERINVALIDpeerDependencies 无效安装缺失的 peer 依赖

pnpm 错误码

错误码含义解决方案
ERR_PNPM_NO_IMPORTER_MANIFEST_FOUND未找到 package.json在项目目录执行
ERR_PNPM_PEER_DEP_ISSUESpeerDependencies 冲突安装冲突的 peer 依赖
ERR_PNPM_ARTIFACT_NOT_FOUNDStore 中未找到包使用 pnpm store prune 清理
ERR_PNPM_LOCKFILE_MISSING_DEPENDENCYlockfile 缺少依赖删除 lockfile 重新安装

yarn 错误码

错误码含义解决方案
EACCES权限不足修复 yarn 目录权限
EEXIST文件已存在清理后重试
ENOENT文件不存在重新安装
ECONNRESET连接重置检查网络或更换 registry

附录:高级包管理技巧

多 registry 配置

# .npmrc 多 registry 配置
 
# 默认 registry
registry=https://registry.npmmirror.com
 
# 私有包使用私有 registry
@my-org:registry=https://npm.my-company.com
@my-private:registry=https://npm.my-company.com
 
# 认证配置
# //npm.my-company.com/:_authToken=${MY_ORG_TOKEN}

Workspace 依赖管理策略

# 查看 workspace 包依赖关系
pnpm why react
 
# 检查过时的 workspace 依赖
pnpm up --interactive
 
# 更新 workspace 依赖到最新
pnpm up -r
 
# 锁定 workspace 依赖版本
pnpm up "workspace:*"

包版本发布工作流

# 1. 更新版本
npm version patch  # 补丁版本
npm version minor  # 次版本
npm version major  # 主版本
 
# 2. 发布到 npm
npm publish
 
# 3. 发布到私有 registry
npm publish --registry=https://npm.my-company.com
 
# 4. 打标签
npm dist-tag add my-package@1.0.0 beta
 
# 5. 从标签安装
npm install my-package@beta

依赖健康度检查清单

## 依赖健康度检查清单
 
- [ ] 定期运行安全审计
- [ ] 保持依赖更新
- [ ] 使用 lockfile
- [ ] 指定 engines 要求
- [ ] 检查包的活跃度
- [ ] 评估包的依赖大小
- [ ] 使用官方或知名包
- [ ] 避免未维护的包
- [ ] 检查包的类型定义
- [ ] 评估包的包体大小

TIP

推荐配置:新项目推荐使用 pnpm + Turborepo,可获得最佳安装速度和构建性能。企业项目建议使用 npm 或 pnpm workspace,保持最大兼容性。