npm、yarn、pnpm 有什么区别?lock 文件的作用?

包管理器对比

特性 npm yarn (v1) pnpm
安装速度 中 快 最快
磁盘空间 多 多 最少(硬链接)
幽灵依赖 ❌ 有 ❌ 有 ✅ 无
并行安装 ❌ ✅ ✅
Workspaces ✅ ✅ ✅
插件 ❌ ✅ (v2+) ✅

幽灵依赖问题

npm/yarn 采用扁平化 node_modules:

node_modules/
├── express/      ← 直接依赖
├── body-parser/  ← express 的依赖,被提升到顶层
├── debug/        ← body-parser 的依赖,也被提升
└── ...

问题:你的代码可以 import 未在 package.json 中声明的包(被提升的依赖),这就是幽灵依赖。

// package.json 只声明了 express
// 但代码中可以引用 express 的依赖(幽灵依赖)
import parse from 'body-parser'  // ✅ 能用但不应该
// 一天 express 不再依赖 body-parser,你的代码就崩了

pnpm 的解决方案

pnpm 使用非扁平结构 + 硬链接:

node_modules/
├── .pnpm/                    ← 真实存储位置
│   ├── express@4.18.2/
│   │   └── node_modules/
│   │       ├── express/      ← 硬链接到全局 store
│   │       └── body-parser/  ← 软链接
│   └── body-parser@1.20.1/
│       └── node_modules/
│           └── body-parser/
└── express/                   ← 软链接到 .pnpm/express@4.18.2/...

只有 package.json 中声明的依赖才出现在顶层 node_modules 中,彻底杜绝幽灵依赖。

pnpm 的全局 store

# 全局 store(内容寻址存储)
~/.pnpm-store/
└── v3/
    └── files/
        ├── ab/cdef123...  ← 文件按哈希存储
        └── ...

# 项目中的 node_modules 通过硬链接引用
# 多个项目共享同一份文件,节省磁盘空间

lock 文件

包管理器 lock 文件
npm package-lock.json
yarn yarn.lock
pnpm pnpm-lock.yaml

lock 文件的作用

  1. 版本锁定:确保团队/CI 安装的依赖版本完全一致
  2. 快速安装:跳过版本解析,直接按 lock 安装
  3. 安全性:防止依赖被篡改
// package-lock.json(简化)
{
  "packages": {
    "node_modules/lodash": {
      "version": "4.17.21",
      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
      "integrity": "sha512-..."  // 完整性校验
    }
  }
}

安装命令对比

# 安装
npm install          # 安装所有依赖
pnpm install         # 同上

# 添加依赖
npm install lodash   # 添加到 dependencies
pnpm add lodash

# 添加开发依赖
npm install -D vitest
pnpm add -D vitest

# 全局安装(不推荐)
npm install -g pkg
pnpm add -g pkg

# 删除依赖
npm uninstall lodash
pnpm remove lodash

# 更新
npm update
pnpm update

npm scripts 生命钩子

{
  "scripts": {
    "preinstall": "...",    // install 前
    "install": "...",
    "postinstall": "...",   // install 后
    "prepublishOnly": "..." // 发布前
  }
}

推荐

.npmrc 配置

# .npmrc
registry=https://registry.npmmirror.com/  # 淘宝镜像
auto-install-peers=true
shamefully-hoist=true  # 临时兼容旧工具(谨慎使用)

同分类其他题目