monorepo 真香

358 阅读2分钟

在讲 monorepo 之前,我们先思考个问题,多个项目之间如何复用代码?

代码复用

当公司的项目越来越多,项目中的配置文件、业务组件、Hooks、Utils 如何在多个项目中复用?

npm

复用文件抽离成 npm 包的方式在不同项目中引用

缺点
1、npm 包中一般不写业务逻辑,而我们大部分业务逻辑是需要共用的
2、一旦 npm 包发布新版本,所有项目都要重新下载最新版本

git submodule

复用文件单独放在一个git,其他项目使用 git submodule 复用代码

缺点
如果公共 git 中有文件更新,其他所有仓库也需要手更新最新的 commitId

以上两种都可以解决代码复用,但如果有几十个、上百个项目,则需要去每个项目中去更新 npm 版本、以及 git commitId,过程漫长且繁,很容易出现问题

有没有更好的复用方式? 答案就是我们今天的主题 monorepo

mono-repo

monorepo 可以使用 turborepo、lerna、yarn、pnpm 来管理,我们今天讲 pnpm 如何管理 monorepo 项目,为什么选择 pnpm,大家可以看下我的往期文章,有详细的 pnpm 介绍,链接地址: pnpm

创建项目

1、这里默认都有 pnpm 环境,首先初始化项目

pnpm init

生成 package.json 文件

{
  "name": "monorepo-pnpm",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

2、创建pnpm-workspace.yaml文件,定义工作空间的根目录为 packages

packages:
 - 'packages/**'

3、在工作空间 packages 下创建多个子项目

├── package.json
├── packages
│   ├── components
│   │   ├── index.js
│   ├── hooks
│   │   ├── index.js
│   └── project
│       ├── index.js
└── pnpm-workspace.yaml

4、初始化子项目,这里以 project 为例,执行pnpm init生成package.json文件

{
  "name": "@packages/project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

项目之间复用

project 项目中复用 components,在根目录下执行

pnpm add @packages/components@* --filter @packages/project

执行完后的package.json

{
  "name": "@packages/project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@packages/components": "workspace:*"
  }
}

可以看到已经将 components 作为依赖项,其中workspace:*将在发布中转换成最新版本

"dependencies": {
    "@packages/components": "workspace:*"
}
// pnpm publish 后会被转换成
"dependencies": {
    "@packages/components": "1.0.0"
}

这样我们修改了 @packages/components,所有子项目都会自动同步最新版本代码

当然monorepo的好处不仅仅是方便的做代码复用,它还可以更好的统一编码规范,以及减少开发一个需求在多个 git 仓库之间的频繁切换,减少心智负担