pnpm+turbo迅速搭建monorepo工程

关于monorepo

monorepo 并不是一个框架、一个包、一个依赖。而是一种单仓库多包管理模式,也是基于中心化思想的实践产物。

举个例子,假设我们现在有6个项目,传统的项目管理方式(Multirepo)会按照6个代码仓库去管理,如果我们要进行开发、维护和部署,就需要分别对这6个仓库进行"开刀"。

而使用 monorepo 思想,我们只需要在根项目下维护这6个项目,那么也可以同样维护一套编码标准、一套开发流程、一套代码规范甚至是一套统一的部署脚本。

优势

  • 对依赖统一管理
  • 模块引用方便
  • 跨项目/团队友好

劣势

  • 统一管理代码库体积很大
  • 统一版本控制降低灵活性
  • 不易统一进行权限管理
  • 需要一定开发成本和团队适应过程

什么场景适合monorepo

  • 项目之间代码引用过程较多,资源共享丰富。
  • 跨项目/团队需求较大,对接需求多。
  • 项目之间存在较多复用需求和依赖。

为什么要用pnpm

相信不少开发用了pnpm都会说"真香"!相比yarn、npm、cnpm这些包管理工具,pnpm做了很多优化,具备空间小、下载快和结构简单等优势。【官网地址】

空间小

如果多个工程存在统一的依赖,会创建一个相当于"快捷方式"的软链接,使用时通过寻址的方式进行复用,避免了重复安装依赖,节省磁盘空间。

下载快

安装的依赖有缓存有记录,之前若安装过就从存储区拿出来链接到node_modules,无需多余的下载任务执行。

结构简单

相比npm依赖结构相对简单,依赖中没有node_modules,而是以.pnpm统一管理,能够避免循环软链接。

为什么要用turbo

Turborepo是Vercel 推出的高性能JS/TS构建工具,尤其适合处理多包整合。其中也使用了缓存、增量构建、并行执行等优化手段,提升落地效率的同时也能够吃到性能红利。【官网地址】

搭建monorepo工程

其实我们可以借助 pnpm 的 workspace 支持,手动搭建 monorepo 工程,这样确实更灵活。但这里使用 pnpm + turbo 的方式搭建,当然 turbo方便是一个因素,更重要的是因为 turbo 更适合大型项目的 monorepo 方案落地,构建效率会高很多。

案例设计

这里简单搭建 monorepo 工程,子项目有两个,分别是 front 和 utils。其中 front 指代业务侧,用来调用 utils 中暴露的 add 和 mul 方法,达到子项目之间的引用效果。

前置要求

Node版本在18以上,pnpm版本在7以上。我这里使用的是22.17.0(Node)+ 10.33.0(pnpm)。

初始化项目

新建一个空的项目,可以使用命令:

bash 复制代码
pnpm init -y

使用 pnpm 包管理器,安装 turbo 依赖。

bash 复制代码
pnpm add turbo -d

在根目录创建 pnpm-workspace.yaml 配置文件,这个文件可以中可以配置 packages 属性,表示工作空间生效的文件区域,此处设置了业务侧(apps)和包侧(packages)。

在根目录创建 turbo.json 配置文件,其中 schema 为配置文件,这里引用的是官方 json 地址,真实的项目中可以拷贝到本地或者放到公司 CDN 服务器上进行托管,减少不确定因素。

javascript 复制代码
{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "dev": {
      "cache": false,
      "persistent": true
    },
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**"]
    }
  }
}

创建子项目utils

新建utils和front项目文件夹,每个项目都必须拥有一个package.json文件,配置name,命名规范格式为" @自定义项目空间名称 / 当前包名 "。

在utils项目中新建一个工具文件index.js,分别导出加减乘除的方法。

javascript 复制代码
export const add = (a, b) => a + b;
export const sub = (a, b) => a - b;
export const mul = (a, b) => a * b;
export const div = (a, b) => a / b;

创建子项目front

此处表示客户端业务侧,就创建一个基于 React 框架模板的 vite 工程,

bash 复制代码
pnpm create vite apps/front --template react

客户端项目初始化完成,我们得到了一个基于 vite 的 react 项目结构,现在我们希望在 front 工程中使用 utils 中的方法,需要进入 front 项目的 package.json 文件,在 dependencies 字段中声明要依赖的子项目名称和目标(这里的子项目名称就是 utils 中 package.json 中的 name 属性,值为"workspace:*"表示这个包的位置是从工作空间中引入的)。

我们简单引入一下 @my-mono/utils 的包中的 add 和 mul 方法,在 App.jsx 中使用。是否成功调用,那到时候看看页面上如果显示的是"3"和"6",那么就表示 add 和 mul 方法成功调用,也就意味着子项目之间的共享已经完成!

配置脚本

此时 cd 到根目录,使用 pnpm i 进行依赖安装。之后我们查看一下 front 目录的 node_modules 中若有 @my-mono 的包,相当于依赖已经引入成功。

现在配置根项目的 package.json,配置脚本运行 front 工程,使用 --filter front,就会命中 front 中的 package.json 的 scripts,从而达到启动子项目的效果。

javascript 复制代码
"dev:front": "turbo dev --filter front"

此时查看预览,发现出现了我们的预期"3"和"6",表示我们的 monorepo 工程搭建完成,并且也实现了子项目之间的共享和交互。

常见问题

报错 pipeline 找不到

这是因为安装的 turbo 是 2.x 版本,这个版本将之前的 pipeline 对象名改成了 tasks,所以在 turbo.json 中改成 tasks 就行了。

报错找不到 packageManager

这是因为 turbo2.x 版本强制要求了必须在 package.json 中显式定义包管理器,在 package.json 中加入 packageManager 就可以了。

相关推荐
weixin_3823952314 小时前
为小工厂量身打造:本地部署的物料管理系统带缺料计算
前端·制造
__zRainy__14 小时前
解决pnpm v10+不自动构建
前端·pnpm·工程化
猫猫不是喵喵.15 小时前
Vue3 Props 属性
前端·javascript·vue.js
醉城夜风~16 小时前
CSS元素显示模式(display)
前端·css
AI大模型-小华17 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
做前端的娜娜子19 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅19 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni20 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学21 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端