相关概念
pnpm:
pnpm
(Performant npm) 是一个快速、节省磁盘空间的 Node.js
包管理器,与 npm
和 Yarn
兼容但采用了不同的依赖管理方法。
- 全局存储:所有依赖只保存一份在
~/.pnpm-store
- 硬链接技术:项目中
node_modules
只是指向全局存储的链接 - 实际效果:相比
npm/Yarn
可节省 60-70% 的磁盘空间 - 典型项目安装速度比
npm
快 2倍 以上 - 解决幽灵依赖问题:无法引用未在
package.json
的依赖
Monorepo:
Monorepo
(单一代码仓库)是一种软件开发策略,指的是将多个相关项目或包的代码存储在同一个版本控制仓库中,而不是为每个项目或组件使用单独的仓库。
将 npm 项目迁移到 pnpm
-
安装
pnpm
bashnpm i pnpm -g
查看是否安装成功及版本号
bashpnpm -v
-
基本迁移
- 删除
npm
的锁定文件和node_modules
:
bashrm -rf node_modules package-lock.json
- 使用
pnpm
安装依赖:
bashpnpm install
这会创建
pnpm-lock.yaml
文件代替package-lock.json
- 删除
-
更新
package.json
脚本- 将 npm 命令替换为
pnpm
:
json{ "scripts": { "dev": "pnpm run dev", // 原先是 npm run dev "build": "pnpm run build" } }
- 将 npm 命令替换为
改造为 Monorepo
1. 配置工作区
-
在项目根目录创建
pnpm-workspace.yaml
yamlpackages: - 'packages/*'
配置: - `packages/*` - 存放共享的库/包 - `!**/__tests__` - 排除测试目录
-
或者在
package.json
中添加json{ "private": true, // monorepo 项目需要设置为私有 "type": "module", // 使用 ESM 模块系统 "workspaces": [ "packages/*" // 指定工作空间目录 ] }
两种选一种配置即可, 如果同时存在 package.json 的 workspaces 和 pnpm-workspace.yaml: pnpm-workspace.yaml 优先级更高,pnpm 会忽略 package.json 的 workspaces 配置。
2. 创建子包
创建共享库包
在根目录下创建 packages
目录,以及子包的目录:task-processor
,thread-pool
,shared
进入这两个目录中分别执行命令:
bash
pnpm init
编辑生成的 package.json
的 name
:
json
{
"name": "@my-monorepo/shared",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
3. 安装依赖
-
安装全局依赖(所有包共享)
bashpnpm add -D -w typescript vite @types/node # 或 pnpm add -Dw typescript vite @types/node
-D
表示开发依赖,没有则是生产依赖
-w
表示 在 Monorepo 的根目录(工作区根目录)执行操作,而不是在某个具体的子包中执行。 -
安装
packages
的子包的依赖bashpnpm add moment --filter @my-monorepo/thread-pool pnpm add lodash --filter @my-monorepo/task-processor
--filter
:指定在特定子项目中安装依赖。 -
子包之间相互依赖
bashpnpm add @my-monorepo/shared@workspace:* --filter @my-monorepo/thread-pool
workspace:*
表示总是使用工作区内的最新版本4. 常用命令
-
在所有包中运行命令
bashpnpm -r run build
-r
表示递归执行 -
在特定包中运行命令
bashpnpm --filter @my-monorepo/web run dev
-
安装所有依赖
bashpnpm install
-
5. 高级配置
共享配置
可以在根目录创建共享的配置文件(如 tsconfig.base.json),然后在各包中继承:
json
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./dist"
}
}
限制依赖版本
在根目录 package.json 中添加:
json
{
"pnpm": {
"overrides": {
"react": "18.2.0",
"typescript": "^4.9.0"
}
}
}
版本管理、发布
安装并初始化 Changesets
bash
pnpm add -Dw @changesets/cli
pnpm changeset init
这会创建 .changeset
目录和配置文件。
流程
-
添加变更说明
bashpnpm changeset
交互式命令行会引导您:
-
选择要版本化的包
-
选择版本更新类型 (
major/minor/patch
) 【未选中时,点击回车切换更新类型】 -
编写变更描述
这会生成一个 changeset 文件在 .changeset 目录中。
-
-
版本升级
bashpnpm changeset version
这个命令会:
- 根据 changeset 文件更新包版本
- 更新依赖关系
- 生成 CHANGELOG.md 文件
- 删除已处理的 changeset 文件
-
发布到 npm
在各个子包的
package.json
中添加:json"publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/" }
否则会报错:
402 Payment Required - PUT https://registry.npmjs.org/xxx - You must sign up for private packages
然后需要在
npm
中创建对应的 组织
然后执行命令:
bashnrm use npm npm login pnpm changeset publish
npm login
前需要切换至npm
源,不能使用cnpm
或者taobao
等源;扩展:在
git
中设置并提交对应的tag
为此次的版本发布