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 就可以了。

相关推荐
半生过往8 分钟前
前端学 Java 课程笔记
java·前端·笔记
广州华水科技44 分钟前
2026年单北斗GNSS变形监测系统推荐,破解水库安全监测难题
前端
独爱香菜1 小时前
Next.js 15 + Cloudflare Workers 实战:零中间件多语言 SEO 站点架构
前端
计算机魔术师1 小时前
DeepSeek、Qwen3比肩GPT-5,本地跑大模型的时代来了
前端
xcyxiner1 小时前
flutter wsl2安装记录(使用宿主机虚拟机)
前端·flutter
前端炒粉1 小时前
长会话虚拟滚动与渲染优化
前端·javascript·vue.js
谙忆10242 小时前
图片裁剪总是跑偏?用 object-fit、object-position 和真实像素把坐标对齐
javascript·css·图像识别
花归去2 小时前
ant的a-table更改表格的高度
前端·javascript·html
sibylyue2 小时前
基于 Vben Admin 框架的 Vue 3 前端项目配置文件及常用命令
前端·javascript·vue.js
知几蜗牛2 小时前
0 后端 · 0 数据库 · 0 备案:用 AI 两天搓出的股票管理系统,开源了
前端·后端·llm