25 年上半年总结以及关于pnpm monorepo 的一些使用记录

背景

我上半年在工作上做的一些项目架构优化工作,包括:

  1. 微前端进行了 pnpm + monorepo 的改造,将主应用及多个子应用应用于此架构。
  2. 将组件库、请求库迁移进上述 monorepo 架构中,并且设计了cicd 流程,只要这些包发生更新,便使依赖这些包的前端服务重新编译部署,也是因为 monorepo,让关联的更新操作自动化,不像以前那样要逐个前端服务下手动 npm i $包名@latest 这般操作使来更新。
  3. 在请求库中使用了 openapi-ts-request 这个工具,自动生成请求函数,再也不用重复地手写请求函数了
  4. 组件库里集成了 Storybook 这个在线文档技术来做文档和 demo,不过只是跑通了,还没深入地使用,在组里面推广这项技术也碰到了阻力。

为什么要用 monorepo 架构?

因为部门的项目,前端用了微前端实现的,背景大概是这篇文章,而微前端里面的子应用,其实有很多可以复用的配置文件,包括像:

  1. Dockerfile、有规律地创建唯一的子应用目录,比如像 /a-web/ 、/b-web/;
  2. nginx 的配置、每一个前端服务的 nginx 配置里,都要写跨域配置;
  3. 子应用的通信交互逻辑,包括像子应用接收用户、权限数据,接收要跳转的路由数据

像上述的这些文件,每个子应用都有,而每个子应用又对应一个代码仓库,就比较零散不好管理,对新人也不友好。我认为更合理的做法是,主应用和子应用放在一起,配置集中管理,优化,上下文能更加清晰,开发也更加方便,因为开发也是要主,子应用一起启动的。

为什么要用 pnpm + monorepo 来改造?

因为很久以前就有看到过相关的文章,比方说babel库就是用了lerna 来进行管理,但是可能是本人比较愚笨,好几次尝试着用lerna 来建项目,始终有各种问题,跑不起来,最终还是搁置了。

但是今年发现pnpm竟原生支持monorepo 的特性,而且搭起来异常的简单,所以就上手用 pnpm 来将公司的分散的微前端应用集中起来了。

总结了一些常见用法(持续增加中)

一份pnpm monorepo配置如下:

yaml 复制代码
packages:
  - 'apps/*'
  - 'packages/**/*'

catalogs:
  vue3:
    vue: ^3.2.13
    vue-router: ^4.5.0
    vuex: ^4.1.0
    '@arco-design/web-vue': ^2.57.0

上面的 packages 字段声明了包的位置,比如apps/a-webpackages/ui/vue-components,这两个目录下,只要存在package.json 文件,就会被pnpm 认定是一个包

下面的catalogs.vue3 这个是版本变量声明,可以把它当做是一个依赖的变量,在 a-web/和 b-webpackage.json 里面,依赖可以这么写:

json 复制代码
"vue": "catalog:vue3",
"vue-router": "catalog:vue3",
"vuex": "catalog:vue3"

假设,apps/a-web 依赖packages/ui/vue-components,并且vue-component的包名(package.json.name) 是vue-components,那么在apps/a-webpackage.json可以这么写:

json 复制代码
"vue-components": "workspace:*",

或者也可以用命令加入:

bash 复制代码
pnpm add "vue-components@workspace:*" --filter a-web

注意,当包含@符号时,要用双引号包裹包名。

怎么针对某个子包执行 dev 命令,注意这个包的package.json.namea-web

bash 复制代码
pnpm --filter a-web dev

怎么对多个应用执行 dev 命令?

bash 复制代码
pnpm --filter a-web --filter b-web dev

列出当前的pnpm 所有包,可用于快速查看所有包名

bash 复制代码
pnpm list -r

解决了一些问题:

  • Docker 编译速度太慢

在 monorepo 架构下,假设场景为,a-web前端服务,依赖 services 请求库、vue-components 组件库,那么就会出现下面这种 Dockerfile 写法:

dockerfile 复制代码
...
COPY pnpm-workspace.yaml ./
COPY pnpm-lock.yaml ./
COPY package.json ./
COPY packages/services ./packages/services
# 假设依赖 请求库, vue-components 组件库
COPY packages/services ./packages/services
COPY packages/ui/vue-components ./packages/ui/vue-components
COPY apps/a-web ./apps/a-web
RUN pnpm install
...

这么写能用,但是有个问题,就是pnpm install 命令这个层,会随着这几个库或者前端服务的代码改变,而始终没办法缓存起来,导致每次编译,都要执行pnpm install,影响了编译的速度。 优化如下:

dockerfile 复制代码
...
RUN mkdir -p apps/a-web packages/services packages/ui/vue-components
COPY package.json ./
COPY pnpm-workspace.yaml ./
COPY pnpm-lock.yaml ./
COPY apps/ds-server-gateway2-web/package.json ./apps/ds-server-gateway2-web/package.json
COPY packages/services/package.json ./packages/services/package.json
COPY packages/ui/vue-components/package.json ./packages/ui/vue-components/package.json
RUN pnpm install --registry $私有仓库地址
COPY packages/services ./packages/services
COPY packages/ui/vue-components ./packages/ui/vue-components
COPY apps/a-web ./apps/a-web
...

也就是前置各个包的 package.json 拷贝操作,pnpm install 操作,来命中Docker的层缓存机制。

持续更新中。

相关推荐
树上有只程序猿22 分钟前
终于有人把数据库讲明白了
前端
猩兵哥哥28 分钟前
前端面向对象设计原则运用 - 策略模式
前端·javascript·vue.js
司宸28 分钟前
Prompt设计实战指南:三大模板与进阶技巧
前端
RoyLin30 分钟前
TypeScript设计模式:抽象工厂模式
前端·后端·typescript
华仔啊36 分钟前
Vue3+CSS 实现的 3D 卡片动画,让你的网页瞬间高大上
前端·css
江城开朗的豌豆44 分钟前
解密React虚拟DOM:我的高效渲染秘诀 🚀
前端·javascript·react.js
vivo互联网技术1 小时前
拥抱新一代 Web 3D 引擎,Three.js 项目快速升级 Galacean 指南
前端·three.js
江城开朗的豌豆1 小时前
React应用优化指南:让我的项目性能“起飞”✨
前端·javascript·react.js
会飞的青蛙1 小时前
GIT 配置别名&脚本自动化执行
前端·git