当前位置: 首页 > news >正文

Monorepo系列:Pnpm Workspace 搭建 Monorepo

近期,团队在做技术升级,新的模式下我们选择 pnpm workspace 搭建 monorepo 的方式来管理前端业务代码,一个业务方向的多个项目使用统一 git 仓库,具备依赖共享、构建统一等优势。结构如下:

my-business/
├── apps/
│   ├── web/          # 前端应用
│   └── mobile/       # 移动端应用
├── packages/
│   ├── ui/           # 组件库
│   └── utils/        # 工具库
|── pnpm-workspace.yaml
└── package.json

使用 Monorepo 管理的好处:

  • 一致的工具链:整个仓库使用统一的工具和配置,如构建工具、代码风格、测试框架等;一次修改,所有相关项目都能受益。
  • 统一的版本管理:所有项目使用同一套依赖版本,便于管理,减少因版本不一致导致的问题【借助 pnpm Catalog 特性】。
  • 简化依赖管理:内部依赖可以直接通过工作空间链接,而不需要发布到包管理器【借助 pnpm workspace 工作空间协议】。

项目选型使用了 pnpm workspace:

  • 节省磁盘空间:依赖会被存储在内容可寻址的存储中,而不是每个项目单独存储,从而节省磁盘空间。
  • 提升构建速度:安装过的依赖项都会直接从存储区中获取并链接到 node_modules。
  • 非扁平的 node_modules 目录:禁止幽灵依赖,未声明依赖无法被偷偷使用。

Workspace 工作空间

工作空间根目录必须有一个 pnpm-workspace.yaml 文件

# pnpm-workspace.yaml
packages:- "packages/*"- "apps/*"

在工作空间内,一个包可以依赖另一个包,使用 workspace:* 协议(如 web 项目引用了 ui 包)。

{"name": "web","version": "0.1.0","dependencies": {"ui": "workspace:*"}
}
  • 在根目录运行 pnpm install,它会安装所有包的依赖,并链接工作空间内的包;
  • 可以使用 pnpm run --filter <package_name> <script> 来在特定包中运行脚本或者使用 pnpm -r run <script> 在所有包中运行脚本。

Catalogs 将依赖项版本定义为可复用常量

在根目录声明 catalog:,即可为团队钉住一组“可被采用”的依赖版本。子包写 "react": "catalog:" 即自动对齐,不再在每个 package.json 里手动同步版本号。

有两种定义方式:

  1. 使用 (单数) catalog 字段创建名为 default 的目录。
  2. 使用 (复数) catalogs 字段创建任意命名的目录。
# pnpm-workspace.yaml
catalogs:# 可以通过 "catalog:react18" 引用react18:react: 18.2.0react-dom: 18.2.0# 可以通过 "catalog:umi" 引用umi:"@umijs/max": "4.4.12""@umijs/utils": "4.4.12"
// apps/web/package.json
{"dependencies": {"@umijs/max": "catalog:umi" # 等价于 4.4.12}
}

优势:

  • 维护唯一版本:通常希望在工作空间中共同的依赖项版本一致。 Catalog 让工作区内共同依赖项的版本更容易维护。 减少重复的依赖关系可能的冲突及重复依赖项打包体积增大。
  • 易于更新:升级或者更新依赖项版本时,只需编辑 pnpm-workspace.yaml 中的目录,而不需要更改所有用到该依赖项的 package.json 文件。 这样可以节省时间 — 只需更改一行,而不是多行。
  • 减少合并冲突:由于在升级依赖项时不需要编辑 package.json 文件,所以这些依赖项版本更新时就不会发生 git 冲突。

需要注意的是:要更新 pnpm-workspace.yaml 中定义的依赖项,需要手动选择较新的版本范围(pnpm update 暂不支持)。

peerDependencies 共享宿主环境的依赖

// packages/ui/package.json
{"peerDependencies": {"react": "^18.0.0","react-dom": "^18.0.0"}
}

对等依赖(Peer Dependencies) 是一种特殊的依赖关系,这里用于组件库&工具库之间共享相同的核心依赖(如 React、ReactDOM 等)。

filter 指定包运行脚本

  1. 可以使用 pnpm run --filter <package_name> <script> 来在特定包中运行脚本
# 运行 web 项目的 dev 脚本
pnpm run --filter web dev
  1. 执行某包及依赖包的脚本(执行 web 及 ui、utils 项目的 dev 脚本)
# 运行 web 及其依赖项的 build 脚本
pnpm --filter web... build

注意:pnpm --filter 的默认行为是:串行执行,前一个任务不退出,下一个不会开始。

pnpm --filter web... dev

并不会按顺序执行完成,原因是:前一个 dev 不退出,导致下一个不会开始。

PS:其他匹配方式,详见官方文档:https://www.pnpm.cn/filtering

上述 dev 怎么并行执行?

方式一:使用 package.json 的 pre 和 post 钩子

{"scripts": {"dev": "pnpm --filter web dev","predev": "pnpm --filter ui dev"}
}

方式二:使用第三方包 concurrently

{"scripts": {"dev": "concurrently \"pnpm --filter web dev\" \"pnpm --filter ui dev\""}
}

[推荐]方式三:使用 turbo 管理

{"scripts": {"dev": "turbo run dev --filter web --filter ui"}
}

PS:后续文章专门介绍 turbo 管理 monorepo 项目。

http://www.dtcms.com/a/520607.html

相关文章:

  • 有没有专门做字体排版设的网站实时热点新闻事件2021
  • 【开题答辩全过程】以 基于BS模式的图书馆管理系统为例,包含答辩的问题和答案
  • Java循环结构全解析:从基础用法到性能优化(含经典案例)
  • C 位域:核心地带,引领技术前沿
  • 鹤壁专业做网站公司前端培训心得
  • python-87-Pyinstaller打包在没有安装Python的电脑上运行
  • 海北高端网站建设多少钱网站后台登陆密码破解
  • CrewAI 核心概念(Knowledge)篇
  • 预检查和表单提交
  • [MySQL] 数据库设计
  • 数据处理像搭乐高?详解 RAGFlow Ingestion Pipeline
  • 模仿网站属于侵权吗做网站视频是什么专业
  • 汽车转向控制 / 线控转向介绍——控制技术——智能驾驶专栏
  • 基于KSP密钥管理系统的汽车 ECU JTAG 调试接口动态授权与安全管控
  • 世界经理人网站手机版学生网页网站制作软件大全
  • 企业网站带新闻发布功能的建站wordpress文章显示颜色
  • SpringBoot-Web开发之Web原生组件注入
  • Spring Cloud - Spring Cloud 本地配置(本地配置概述、本地配置实现)
  • 青岛商城网站建设长春建设平台网站的公司
  • 这几年做网站怎么样wordpress adsense主题
  • 做视频网站服务器怎么选择12306网站开发时间
  • 如何做家教网站赚钱如何申请国外网站
  • 淄博做网站建设云南网站建设方案
  • 实用指南--多账号矩阵防封控
  • 前端框架Vue(Vue 的挂载点与 data 数据对象)
  • pycharm 远程连接服务器添加github copilot
  • 金融智能体的技术底座解析:AI Agent如何实现“认知+执行”闭环?
  • PostgreSQL 选择数据库:深入解析与最佳实践
  • 木材模板.网站黄山网站建设推广
  • 临沧永德网站建设电子商务公司个人博客网站制作论文