pnpm workspace管理monorepo项目使用过程详解
作者:观炎
本文记录使用 monorepo 方案 pnpm workspace 的过程。
monorepo
首先要清楚,为什么要用到 monorepo
?对于我来说,手上负责公司内部的多个项目,其中除了业务模块单独使用外,例如系统管理、中间库、工具等都是共用的。
而在开发的过程中,共用的模块想要添加或修改,为了保持多项目一致性,那么就需要不断地复制粘贴,这个过程不说有多繁琐,还有可能造成依赖错误。
为了解决这个问题,对比了 learn+yarn / npm
等方案后,决定采用 pnpm workspace
方案对项目进行管理。
下面将通过一个例子初步学会 pnpm workspace
。
随便找个文件夹创建 workspace 项目
D: && cd project/monorepo mkdir demo2 && cd demo2
新建 pnpm-workspace.yaml 文件并填入相关内容以启用 workspace
packages: - packages/* - apps/* - demo
首行 packages
代表 workspace
包,且该 workspace
由以下项目组成;而带有 -
前缀的字符串,代表项目目录,具体可通过 pnpm
官方文档查看
完善项目目录及包配置
现在的文件夹应当只有一个 pnpm-workspace.yaml
文件,接下来我们手动添加相关文件/文件夹和配置
新建相关文件夹
mkdir packages && cd packages mkdir components utils hooks space-play cd .. && mkdir apps && cd apps && mkdir play1
为文件夹新建 package.json 文件
// ./package.json { "description": "A pnpm workspace example." } // ./packages/components/package.json { "name": "@space-play/components", "version": "0.0.1" } // ./packages/utils/package.json { "name": "@space-play/utils", "version": "0.0.1" } // ./packages/hooks/package.json { "name": "@space-play/hooks", "version": "0.0.1" } // ./packages/space-play/package.json { "name": "space-play", "version": "0.0.1" } // ./apps/play1/package.json { "name": "play1", "version": "0.0.1" }
可以从上面的内容中看出, packages
文件夹里面除了 space-play
的 package.json
文件,其他文件夹里面的 name
命名都带有一个 @space-play
前缀,那么这个是什么意思呢?这是代表 npm
发包后的安装命名,也代表这些包都归属于 space-play
包。
此时的项目目录应该是这样的:
demo2 | apps | play1 | package.json | packages | components | package.json | hooks | package.json | utils | package.json | space-play | package.json | pnpm-workspace.yaml | package.json
一个简陋的 monorepo
已经完成,通过相关 pnpm add
指令,我们可以进行本地包的调用。
例如我们想要在 apps/play1
包里调用所有的本地包,可以先在 space-play
包里安装其它本地包,再安装该包行。
尝试一下:
在 workspace
里查找 packages/space-play
,并在该包里安装 @space-play/components @space-play/hooks @space-play/utils
等依赖包
pnpm -r --filter ./packages/space-play add @space-play/components @space-play/hooks @space-play/utils
在 space-play
新建 index.ts
文件夹并导出所有依赖包
// packages/space-play/index.ts import type { App } from 'vue' export * from '@space-play/components' export * from '@space-play/hooks' export * from '@space-play/utils' export default { install(app: App) { console.log('已使用 space-play 包,但该包里什么都没有') }, version: '0.0.1' // 这里只是作为示例,实际应该获取 package.json 里的版本 }
到 apps/play1
里使用 space-play
包
pnpm -r --filter ./apps/play1 add space-play
在 apps/play1
新建一个简单的项目结构并安装相关依赖
demo1/apps/play1 | app.vue | index.html | index.ts | package.json | vite.config.ts
可以看到,这个项目里面用到 vue、vite
,这两个依赖在 monorepo 里面的其它项目包里都会用到,所以我们在根目录里面进行安装,同时安装 vite
解析 vue
的插件
pnpm add -w vue pnpm add -w -D vite @vitejs/plugin-vue
可以看到这里用了两条命令并在第二条命令中多了个 -D
参数,因为 vite
在编译后不需要,而 vue
是需要的,所以一个安装在常用依赖,一个开发依赖
打开 ./apps/play1/package.json
,对他加点料,文件内原本的参数不动,这里只显示添加的,后续也如此
{ ..., "scripts": { "dev": "vite" } }
文件 app.vue
和 index.html
<!-- app.vue --> <template> <div>打开了 app.vue</div> </template> <!-- index.html --> <!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <div id="app"></div> <script type="module" src="./index.ts"></script> </body> </html>
文件 apps/play1/index.ts
和普通 vue
项目的 main.ts
基本一致
import { createApp } from 'vue' import SpacePlay from 'space-play' import App from './app.vue' createApp(App).use(SpacePlay).mount('#app')
文件 apps/play1/vite.config.ts
和普通 vue
项目的 main.ts
基本一致
import { defineConfig } from "vite"; import vue from "@vitejs/plugin-vue"; export default defineConfig({ plugins: [vue()], });
到这里,一个基于 pnpm workspace
的 monorepo
项目基本完成,剩下的不过是在该项目内的填充。
注意!项目目前还不能够正常运行,因为在 packages/components
packages/hooks
packages/utils
还没有新建 index.ts
文件并这这些目录下的 package.json
配置 main
入口
如果你在上面过程中发现了这个问题并手动创建并配置了,那么完成根目录的 scripts
配置后就可以运行项目试试效果了。
{ ..., "scripts": { "play1": "pnpm -C apps/play1 dev" } }
pnpm run play1 ? Local: http://localhost:5173/
通过浏览器打开,我们可以看到页面显示符合预期的内容
以上就是pnpm workspace管理monorepo项目使用过程详解的详细内容,更多关于pnpm workspace管理monorepo的资料请关注脚本之家其它相关文章!