Files
skillhub-047-pnpm/references/best-practices-migration.md
2026-07-13 21:35:53 +08:00

5.2 KiB
Raw Permalink Blame History

name, description
name description
migration-to-pnpm 从 npm 或 Yarn 迁移到 pnpm,尽可能降低摩擦

迁移到 pnpm

将现有项目从 npm 或 Yarn 迁移到 pnpm 的指南。

快速迁移

从 npm 迁移

# 删除 npm 的锁文件和 node_modules
rm -rf node_modules package-lock.json

# 使用 pnpm 安装
pnpm install

从 Yarn 迁移

# 删除 Yarn 的锁文件和 node_modules
rm -rf node_modules yarn.lock

# 使用 pnpm 安装
pnpm install

导入现有锁文件

pnpm 可以导入现有的锁文件:

# 从 npm 或 yarn 锁文件导入
pnpm import

# 这会从以下文件创建 pnpm-lock.yaml
# - package-lock.jsonnpm
# - yarn.lockYarn
# - npm-shrinkwrap.jsonnpm

处理常见问题

幽灵依赖

pnpm 对依赖关系要求严格。如果代码导入的包不在 package.json 中,将会失败。

问题:

// 在 npm(提升模式)下可以工作,但在 pnpm 下会失败
import lodash from 'lodash' // 不在 dependencies 中,由其他包安装

解决方案: 显式添加缺失的依赖:

pnpm add lodash

缺失对等依赖

pnpm 默认会报告对等依赖问题。

方案 1 让 pnpm 自动安装:

# .npmrcpnpm v8+ 默认值)
auto-install-peers=true

方案 2 手动安装:

pnpm add react react-dom

方案 3 如果可接受则忽略警告:

{
  "pnpm": {
    "peerDependencyRules": {
      "ignoreMissing": ["react"]
    }
  }
}

符号链接问题

某些工具无法与符号链接配合使用。请使用提升模式:

# .npmrc
node-linker=hoisted

或者提升特定包:

public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=*babel*

原生模块重建

如果原生模块失败,请尝试:

# 重建所有原生模块
pnpm rebuild

# 或者重新安装
rm -rf node_modules
pnpm install

Monorepo 迁移

从 npm Workspaces 迁移

  1. 创建 pnpm-workspace.yaml

    packages:
      - 'packages/*'
    
  2. 将内部依赖更新为使用 workspace 协议:

    {
      "dependencies": {
        "@myorg/utils": "workspace:^"
      }
    }
    
  3. 安装:

    rm -rf node_modules packages/*/node_modules package-lock.json
    pnpm install
    

从 Yarn Workspaces 迁移

  1. 删除 Yarn 专属文件:

    rm yarn.lock .yarnrc.yml
    rm -rf .yarn
    
  2. 创建 pnpm-workspace.yaml,内容与 package.json 中的 workspaces 匹配:

    packages:
      - 'packages/*'
    
  3. 更新 package.json —— 如不需要则删除 Yarn workspace 配置:

    {
      // 删除 "workspaces" 字段(可选,pnpm 使用 pnpm-workspace.yaml
    }
    
  4. 转换 workspace 引用:

    // 来自 Yarn
    "@myorg/utils": "*"
    
    // 改为 pnpm
    "@myorg/utils": "workspace:*"
    

从 Lerna 迁移

pnpm 可以在大多数使用场景下替代 Lerna:

# Lerna:在所有包中运行脚本
lerna run build

# pnpm 等价命令
pnpm -r run build

# Lerna:在特定包中运行
lerna run build --scope=@myorg/app

# pnpm 等价命令
pnpm --filter @myorg/app run build

# Lerna:发布
lerna publish

# pnpm:改用 changesets
pnpm add -Dw @changesets/cli
pnpm changeset
pnpm changeset version
pnpm publish -r

配置迁移

.npmrc 设置

大多数 npm/Yarn 设置可在 pnpm 的 .npmrc 中使用:

# 注册表设置(与 npm 相同)
registry=https://registry.npmjs.org/
@myorg:registry=https://npm.myorg.com/

# 认证令牌(与 npm 相同)
//registry.npmjs.org/:_authToken=${NPM_TOKEN}

# pnpm 专属补充设置
auto-install-peers=true
strict-peer-dependencies=false

脚本迁移

大多数脚本无需修改即可使用。更新 pnpm 专属模式:

{
  "scripts": {
    // npm:递归脚本
    "build:all": "npm run build --workspaces",
    // pnpm:使用 -r 标志
    "build:all": "pnpm -r run build",
    
    // npm:在特定 workspace 中运行
    "dev:app": "npm run dev -w packages/app",
    // pnpm:使用 --filter
    "dev:app": "pnpm --filter @myorg/app run dev"
  }
}

CI/CD 迁移

更新 CI 配置:

# 之前(npm
- run: npm ci

# 之后(pnpm
- uses: pnpm/action-setup@v4
- run: pnpm install --frozen-lockfile

将以下内容添加到 package.json 以启用 Corepack

{
  "packageManager": "pnpm@9.0.0"
}

渐进式迁移

对于大型项目,可以逐步迁移:

  1. 从 CI 开始:在 CI 中使用 pnpm,本地仍使用 npm/yarn
  2. 添加 pnpm-lock.yaml:运行 pnpm import 创建锁文件
  3. 全面测试:确保构建在 pnpm 下正常工作
  4. 更新文档:更新 README、CONTRIBUTING
  5. 删除旧文件:团队采纳后删除旧的锁文件

回滚方案

如果迁移导致问题:

# 删除 pnpm 文件
rm -rf node_modules pnpm-lock.yaml pnpm-workspace.yaml

# 恢复 npm
npm install

# 或者恢复 Yarn
yarn install

在 git 历史中保留旧的锁文件以便轻松回滚。