• 作者:老汪软件技巧
  • 发表时间:2024-08-27 17:03
  • 浏览量:

本文由体验技术团队Kagol原创。你的项目是不是正在不断膨胀,构建速度越来越慢,包体积越来越大,性能越来越慢了?

想拆分到不同的仓库中分开维护,又担心代码不方便复用?

你可能需要将项目改造成 Monorepo 啦!

我将带大家把一个现有项目改造成 Monorepo 方式,便于扩展和多项目复用。

如果你也有类似的需求,可以点赞、收藏下本文,关键时刻也许能帮上忙。

1 为什么需要做 Monorepo 改造

使用 monorepo 方式组织代码的前提是:

你有多个项目,并且需要在多个项目中复用组件和逻辑。

如果每个项目都是完全独立的,没有什么共用的代码(几乎不太可能),那也许你就不需要用 monorepo 啦。

1.1 Monorepo 的好处

使用 Monorepo 方式组织项目代码,至少有以下好处:

便于代码复用:多个仓库都会用到的组件、工具函数、类型声明、样式等,可以放到 common 子包中,需要的仓库直接 npm install 这个子包就行,就跟 npm install 一个 npm 包一样容易。独立构建和部署:每个子包都是一个独立的项目,有自己的 package.json 文件,独立安装依赖、独立端口和本地启动、独立测试、独立构建和部署,互不影响。降低切换成本:由于只有单一仓库,clone 代码、切换分支、安装依赖比较方便,不用在不同文件夹之间切换。节约磁盘空间:pnpm 天然具备 monorepo 能力,支持全局依赖管理,所有子包之间共享依赖,节约磁盘空间。方便提交PR:由于是单仓库,增加新组件或给组件增加新特性,只需要提交一个 MR、编写一次 MR 描述、关联一次需求/缺陷单。方便代码检视:一个完整的特性只需要统一在一个 MR 中检视,不用在多个仓库/多个 MR 之间切换。灵活便于扩展:后续增加新的工程只需要在 packages 下增加一个子包,不需要申请新的代码仓库,也降低后续仓库维护成本,比如:配置保护分支 / GitHub Actions / 仓库标签等。1.2 如果不用 Monorepo 会怎么样?

这样做的好处是所有代码都在一起,代码复用方便,直接../就行;而且不用创建和维护仓库,不用配置一堆流水线。

坏处也显而易见,就是项目会不断膨胀,本地启动调试会越来越慢、构建打包越来越慢,包体积越来越大,项目越来越卡,最后用户受不了纷纷弃坑。

好处是项目之间相互独立,不容易耦合,维护起来方便。

坏处就是增加了仓库维护成本、流水线创建成本,并且不方便项目之间复用代码。

不管是以上哪种方式,后续项目的演进都是麻烦不断,要么代码量膨胀、性能下降,要么重复劳动、一堆重复代码。

Monorepo 可以你帮助减少麻烦,快乐工作!

我们一起来看看具体怎么改造吧!

2 现有工程改造成 Monorepo 的步骤

假如我们已经有了一个 Vite + Vue3 工程,可以通过 npm run dev 本地启动,npm run build 进行构建。

基本步骤:

增加 packages 目录用于存放子包,增加 portal 子包把现有工程的 src / public / package.json / vite.config.ts / tsconfig.xx.json / index.html / README.md 等项目启动和构建相关的目录和文件全部剪切到 packages/portal 目录中增加 pnpm-workspace.yaml 文件配置多包路径根目录增加 package.json 文件执行 pnpm i 安装依赖,执行 pnpm -F portal dev 本地启动将本地启动命令放到根目录的 packages.json scripts中,方便启动2.1 创建子包

第一步就是在根目录创建 packages 目录,增加项目子包,比如项目叫:portal

root
├── packages
|  └── portal
|     ├── ... // 项目文件和目录

2.2 现有项目文件放进子包里

把现有工程的 src / public / package.json / vite.config.ts / tsconfig.xx.json / index.html / README.md 等项目启动和构建相关的目录和文件全部剪切到 packages/portal 目录中

root
├── packages
|  └── portal
|     ├── index.html
|     ├── package-lock.json
|     ├── package.json
|     ├── public
|     ├── README.md
|     ├── src
|     ├── tsconfig.app.json
|     ├── tsconfig.json
|     ├── tsconfig.node.json
|     └── vite.config.ts

2.3 配置 pnpm-workspace.yaml

根目录创建pnpm-workspace.yaml文件。

packages:
  - packages/**

2.4 配置 package.json

项目原来的 package.json 属于子包,需要放到 portal 子包中。

项目根目录需要创建一个新的 package.json 文件。

{
  "name": "root",
  "private": true
}

2.5 改造前后目录结构对比

2.6 验证本地启动和构建命令

_Monorepo:让你的项目脱胎换骨,既能代码复用,又能独立部署_Monorepo:让你的项目脱胎换骨,既能代码复用,又能独立部署

执行 pnpm i 安装依赖

执行 pnpm -F portal dev 本地启动

执行 pnpm -F portal build 项目构建

如果以上命令都正常,说明本次 Monorepo 改造成功!

2.7 增加便捷命令

将本地启动命令放到根目录的 packages.json scripts 中,方便启动。

{
  "name": "root",
  "private": true,
+  "scripts": {
+    "dev": "pnpm -F portal dev",
+    "build": "pnpm -F portal build",
+    "preview": "pnpm -F portal preview"
+  }
}

后续启动项目:pnpm dev

构建项目:pnpm build

3 增加一个新项目 admin

在 packages 目录下执行 npm create vite admin,选择 React 框架。

执行 pnpm i 安装依赖

执行 pnpm -F admin dev 本地启动 admin 新项目

执行 pnpm -F admin build 构建 admin 新项目

两个项目同时启动了。

实现了 portal / admin 两个项目分开启动、分开构建、分开管理依赖、分开测试,互不影响,而且 portal 是 Vue 技术栈,admin 是 React 技术栈。

可以在根目录的 package.json scripts 增加对应的便捷命令。

{
  "name": "root",
  "private": true,
  "scripts": {
    "dev": "pnpm -F portal dev",
    "build": "pnpm -F portal build",
    "preview": "pnpm -F portal preview",
+    "dev:admin": "pnpm -F portal dev",
+    "build:admin": "pnpm -F portal build",
+    "preview:admin": "pnpm -F portal preview"
  }
}

改造后的 Monorepo 项目目录结构,看起来和原来差异不大,就是包了一层 packages,其实整个项目已经脱胎换骨,变成了一个更加让人“省心”的项目,项目之间的代码复用更加方便,后续维护和扩展也是非常轻松。

root
├── package.json
├── packages
|  ├── admin
|  |  ├── eslint.config.js
|  |  ├── index.html
|  |  ├── package.json
|  |  ├── public
|  |  ├── README.md
|  |  ├── src
|  |  ├── tsconfig.app.json
|  |  ├── tsconfig.json
|  |  ├── tsconfig.node.json
|  |  └── vite.config.ts
|  └── portal
|     ├── index.html
|     ├── package-lock.json
|     ├── package.json
|     ├── public
|     ├── README.md
|     ├── src
|     ├── tsconfig.app.json
|     ├── tsconfig.json
|     ├── tsconfig.node.json
|     └── vite.config.ts
├── pnpm-lock.yaml
└── pnpm-workspace.yaml

如果有些逻辑 portal / admin 都用到了,我们可以新加一个子包:common

然后在 portal / admin 中引入 common。

pnpm -F portal i common
pnpm -F admin i common

安装之后直接 import 进行使用即可。

4 总结

本文主要给大家分析了 Monorepo 方式组织项目代码的好处,以及不使用 Monorepo 可能带来的麻烦;

然后以一个 Vite + Vue3 项目为例,手把手带大家一起将它改造成 Monorepo 项目;

在此基础上,如何扩展一个新项目,并且新项目技术栈用的是 React,却可以和原来的 Vue 项目共同代码逻辑。

别犹豫了,动手实践起来吧!

最近我们新开源了一个基于 Quill 2.0 的富文本编辑器:Fluent Editor。

Fluent Editor:一个基于 Quill 2.0 的富文本编辑器,功能强大、开箱即用!

如果你正在寻找一款功能强大、开箱即用、易于扩展的开源富文本,不妨尝试下!

关于 OpenTiny

GitHub:/opentiny/ti… (欢迎 Star ⭐)

官网:opentiny.design/tiny-vue

B站:/15284299