19

使用 pnpm 构建 Monorepo 项目

 2 years ago
source link: https://innei.ren/posts/technology/pnpm-monorepo
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
使用 pnpm 构建 Monorepo 项目

monorepo 是什么

monorepo 是把多个项目的所有代码放到一个 git 仓库中进行管理,多个项目中会有共享的代码则可以分包引用。整个项目就是有 root 管理的 dependencies 加上多个 packages,每个 package 也可以在自己的作用域引入自己的 dependencies。
项目结构如下:
1.
2├── node_modules
3├── package.json
4├── packages
5│   ├── ui
6│   ├── utils
7│   └── web
8├── pnpm-lock.yaml
9├── pnpm-workspace.yaml
10├── readme.md
11└── tsconfig.json
packages 文件夹中的就是原本每个独立的项目(下文称之为 package )了,现在放在一起用 workspace 去管理。最外层路径称之为 root。在 root package.json 中的 deps 是所有子 package 共用的。

pnpm 是什么

Fast, disk space efficient package manager
pnpm 是新一代 node 包管理器。它由 npm/yarn 衍生而来,但却解决了 npm/yarn 内部潜在的 bug,并且极大了地优化了性能,扩展了使用场景。
pnpm 相比 yarn,npm,yarn PnP 安装包更快速,对包的依赖管理更偏平,对磁盘占用也有优势。
具体可以参考这篇文章:
为什么现在我更推荐 pnpm 而不是 npm/yarn?
https://jishuin.proginn.com/p/763bfbd3bcff

为什么要使用 monorepo

使用 monorepo 可以把原本一个项目的多个模块拆分成多个 packages,在 packages 之间相互引用,也可以单独发布成包,极大地解决了项目之间代码无法重用的痛点。在项目打包或者编译操作时也可重用一套配置,通吃所有 packages。
首先需要安装 pnpm,就不用多说了。然后 init 一个项目。
在 root 目录新建 pnpm-workspace.yaml,内容如下
yaml
1packages:
2  # all packages in subdirs of packages/ and components/
3  - 'packages/**'
我们所有的 packages 都放在 packages 目录下。
用 pnpm 安装全局共用的包,比如 react, react-dom。
sh
1pnpm install react react-dom -w
注意这里使用 -w 表示把包安装在 root 下,该包会放置在 <root>/node_modules 下。当然也可以把把安装在所有 packages 中,使用 -r 代替 -w。你必须使用其中一个参数。例如把 dayjs 装入 packages/web 下,packages/web 中的 package.json name 为 @test/web。需要执行:
sh
1pnpm i dayjs -r --filter @test/web
使用 --filter 后面接子 package 的 name 表示只把安装的新包装入这个 package 中。

接下来,我们在 packages 中新建以下几个目录。
1├── packages
2│   ├── ui
3│   ├── utils
4│   └── web
然后每个都执行 npm init ,假设每个 package 的 name 依次为 @test/ui @test/utils @test/web
json
1// packages/utils
2{
3  "name": "@test/utils", // <-----
4  "version": "1.0.0",
5  "description": "",
6  "main": "index.ts",
7  "author": "Innei",
8  "license": "MIT",
9  "dependencies": {}
10}
以 utils 为例,入口文件为 index.ts,首先建立这个文件。写入如下内容。
ts
1export const add = (a: number, b: number) => a + b
然后,执行
1pnpm i @test/utils -r --filter @test/ui
之后,打开 packages/ui/package.json 发现 dependencies 中多了一行。
json
1{
2  "name": "@test/ui",
3  "version": "1.0.0",
4  "description": "",
5  "main": "./index.tsx",
6  "scripts": {},
7  "author": "Innei",
8  "license": "MIT",
9  "dependencies": {
10    "@test/utils": "workspace:^1.0.0" // <--------
11  }
12}
由于是 workspace 管理的,所有有一个前缀 workspace。接下来则可以从 package/ui 中直接引入这个包了。
ts
1import {add} from '@test/utils'
当然,如果用 vscode ts server 提供的 auto import 会使用 relative path 引用。如下:
ts
1import {add} from '../utils'
其实只要用 vscode 打开这个文件夹,当成一个项目来写就行了。这也就暂时剥离 monorepo 这个概念了。
那么接下来的 package/web 就是整个项目的整体了。放置原来项目中的所有 src 下的代码。而一些原本通用的代码就从 src 下提取成包放在了 packages 下了。这样就好理解了。
Template:
Innei
https://github.com/Innei
/
pnpm-workspace-monorepo
https://github.com/Innei/pnpm-workspace-monorepo

文章标题: 使用 pnpm 构建 Monorepo 项目

文章作者: Innei

文章链接: https://innei.ren/posts/technology/pnpm-monorepo [复制]

最后修改时间: 2021年05月20日 11:11


商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接,未经站长允许不得对文章文字内容进行修改演绎。
本文采用创作共用保留署名-非商业-禁止演绎4.0国际许可证


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK