monorepo,lerna,yarn workspace

Monorepo

Monorepo 是管理项目代码的一个方式,指在一个项目仓库 (repo) 中管理多个模块/包 (package),不同于常见的每个模块建一个 repo

├── packages
|   ├── pkg1
|   |   ├── package.json
|   ├── pkg2
|   |   ├── package.json
├── package.json

monorepo 最主要的好处是统一的工作流和Code Sharing。比如我想看一个 pacakge 的代码、了解某段逻辑,不需要找它的 repo,直接就在当前 repo;当某个需求要修改多个 pacakge 时,不需要分别到各自的 repo 进行修改、测试、发版或者 npm link,直接在当前 repo 修改,统一测试、统一发版。只要搭建一套脚手架,就能管理(构建、测试、发布)多个 package。
但是 repo 的体积较大。因为各个 package 理论上都是独立的,所以每个 package 都维护着自己的 dependencies,而很大的可能性,package 之间有不少相同的依赖,而这就可能使install时出现重复安装。目前最常见的 monorepo 解决方案是 Lerna 和 yarnworkspaces 特性。

lerna

lerna是一款js代码库管理软件, 用来对一系列相互耦合比较大、又相互独立的js git库进行管理。解决各个库之间修改混乱、难以跟踪的问题。

lerna管理的项目结构
- packages
  - project1
    - src
      - index.ts
    - package.json
  - project2
    - src
      - index.ts
    - package.json
  - project3
    - src
      - index.ts
    - package.json
- lerna.json
- package.json

不会变化了, 默认为independent。

lerna.json解析
{
  "version": "1.1.3",
  "npmClient": "npm",
  "command": {
    "publish": {
      "ignoreChanges": [
        "ignored-file",
        "*.md"
      ]
    },
    "bootstrap": {
      "ignore": "component-*",
      "npmClientArgs": ["--no-package-lock"]      
    }
  },
  "packages": ["packages/*"]
}
  • version , 当前库的版本
  • npmClient , 允许指定命令使用的client, 默认是 npm, 可以设置成 yarn
  • command.publish.ignoreChanges , 可以指定那些目录或者文件的变更不会被publish
  • command.bootstrap.ignore , 指定不受 bootstrap 命令影响的包
  • command.bootstrap.npmClientArgs , 指定默认传给 lerna bootstrap 命令的参数
  • command.bootstrap.scope , 指定那些包会受 lerna bootstrap 命令影响
  • packages , 指定包所在的目录

yarn workspace

yarn 作为包管理器的同学,可以在 package.json 中以 workspaces 字段声明 packages,yarn 就会以 monorepo 的方式管理 packages。相比 lerna,yarn 突出的是对依赖的管理,包括 packages 的相互依赖、packages 对第三方的依赖,yarn 会以 semver 约定来分析 dependencies 的版本,安装依赖时更快、占用体积更小;但欠缺了「统一工作流」方面的实现。

workspace的作用:

(1)能帮助你更好地管理多个子project的repo,这样你可以在每个子project里使用独立的package.json管理你的依赖,又不用分别进到每一个子project里去yarn install/upfrade安装/升级依赖,而是使用一条yarn命令去处理所有依赖就像只有一个package.json一样
(2)yarn会根据就依赖关系帮助你分析所有子project的共用依赖,保证所有的project公用的依赖只会被下载和安装一次。
开启 workspace 的功能也比较简单,只需要在 package.json 里面将 private 设置为 true,并且规定好 workspaces 字段里面的子项目就好了。

{
    ...
    private: true,
    workspaces: [
      "packages/*"
    ]
}
yarn workspace 命令

yarn workspace 提供了一些常用的命令。
一般来说,执行某个项目下面的某个命令都用 yarn workspace project run xxx。
执行所有项目下面的某个命令要用 yarn workspaces run xxx。

举例

用 monorepo 的形式来管理这个仓库。

由于他们使用了相同的技术栈,那么 eslint、prettier,甚至 webpack 配置都可以提取到最外面,不用维护在每个项目里面。

以 create-react-app eject 之后的配置为例:

- node_modules 
   - react
   - react dom   
   - redux  
   - lodash   
- packages   
  - project1    
    - package.json  
  - project2   
     - package.json   
 - config  
    - webpack.config.js 
    - webpack.dev.config.js  
- scripts 
  - create.js 
  - bin.js  
  - build.js 
  - start.js 
- .eslintrc.js
- .prettierrc
- commitlint.config.js
- jest.config.js
- tsconfig.js
- package.json
- yarn.lock

我们可以看到,通用配置都被提取到了最外层。
如果运行或者构建子项目,只需要在子项目的 package.json 里面这么配置。在外面执行 yarn workspace project run build 就行了。

 "start": "node ../../scripts/start.js", 
 "build": "node ../../scripts/build.js",
 "test": "node ../../scripts/test.js

由于 yarn workspace 和 lerna 有较多的功能重叠,这里重叠的部分优先使用 workspace 。最后就是只有发布管理使用了 learn 其它使用 workspace

你可能感兴趣的:(monorepo,lerna,yarn workspace)