前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用 pnpm 构建 Monorepo 项目

使用 pnpm 构建 Monorepo 项目

作者头像
Innei
发布2021-12-28 10:48:33
3.7K1
发布2021-12-28 10:48:33
举报
文章被收录于专栏:静之森

monorepo 是什么

monorepo 是把多个项目的所有代码放到一个 git 仓库中进行管理,多个项目中会有共享的代码则可以分包引用。整个项目就是有 root 管理的 dependencies 加上多个 packages,每个 package 也可以在自己的作用域引入自己的 dependencies。

项目结构如下:

代码语言:javascript
复制
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

COPY

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?

为什么要使用 monorepo

使用 monorepo 可以把原本一个项目的多个模块拆分成多个 packages,在 packages 之间相互引用,也可以单独发布成包,极大地解决了项目之间代码无法重用的痛点。在项目打包或者编译操作时也可重用一套配置,通吃所有 packages。

https://cdn.jsdelivr.net/gh/Innei/img-bed@master/2021/0520184441.png
https://cdn.jsdelivr.net/gh/Innei/img-bed@master/2021/0520184441.png

开始

首先需要安装 pnpm,就不用多说了。然后 init 一个项目。

在 root 目录新建 pnpm-workspace.yaml,内容如下

yaml

代码语言:javascript
复制
1packages:
2  # all packages in subdirs of packages/ and components/
3  - 'packages/**'

COPY

我们所有的 packages 都放在 packages 目录下。

用 pnpm 安装全局共用的包,比如 react, react-dom。

sh

代码语言:javascript
复制
1pnpm install react react-dom -w

COPY

注意这里使用 -w 表示把包安装在 root 下,该包会放置在 <root>/node_modules 下。当然也可以把把安装在所有 packages 中,使用 -r 代替 -w。你必须使用其中一个参数。例如把 dayjs 装入 packages/web 下,packages/web 中的 package.json name 为 @test/web。需要执行:

sh

代码语言:javascript
复制
1pnpm i dayjs -r --filter @test/web

COPY

使用 --filter 后面接子 package 的 name 表示只把安装的新包装入这个 package 中。


接下来,我们在 packages 中新建以下几个目录。

代码语言:javascript
复制
1├── packages
2│   ├── ui
3│   ├── utils
4│   └── web

COPY

然后每个都执行 npm init ,假设每个 package 的 name 依次为 @test/ui @test/utils @test/web

json

代码语言:javascript
复制
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}

COPY

以 utils 为例,入口文件为 index.ts,首先建立这个文件。写入如下内容。

ts

代码语言:javascript
复制
1export const add = (a: number, b: number) => a + b

COPY

然后,执行

代码语言:javascript
复制
1pnpm i @test/utils -r --filter @test/ui

COPY

之后,打开 packages/ui/package.json 发现 dependencies 中多了一行。

json

代码语言:javascript
复制
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}

COPY

由于是 workspace 管理的,所有有一个前缀 workspace。接下来则可以从 package/ui 中直接引入这个包了。

ts

代码语言:javascript
复制
1import {add} from '@test/utils'

COPY

当然,如果用 vscode ts server 提供的 auto import 会使用 relative path 引用。如下:

ts

代码语言:javascript
复制
1import {add} from '../utils'

COPY

其实只要用 vscode 打开这个文件夹,当成一个项目来写就行了。这也就暂时剥离 monorepo 这个概念了。

https://cdn.jsdelivr.net/gh/Innei/img-bed@master/2021/0520190325.png
https://cdn.jsdelivr.net/gh/Innei/img-bed@master/2021/0520190325.png

那么接下来的 package/web 就是整个项目的整体了。放置原来项目中的所有 src 下的代码。而一些原本通用的代码就从 src 下提取成包放在了 packages 下了。这样就好理解了。

https://cdn.jsdelivr.net/gh/Innei/img-bed@master/2021/0520190604.png
https://cdn.jsdelivr.net/gh/Innei/img-bed@master/2021/0520190604.png

Template:

Innei

/

pnpm-workspace-monorepo

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-05-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • monorepo 是什么
  • pnpm 是什么
  • 为什么要使用 monorepo
  • 开始
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档