monorepo|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

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

    推荐阅读