Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lerna 和 yarn workspace 的 monorepo 工作流 #73

Open
pfan123 opened this issue Jul 20, 2020 · 0 comments
Open

lerna 和 yarn workspace 的 monorepo 工作流 #73

pfan123 opened this issue Jul 20, 2020 · 0 comments

Comments

@pfan123
Copy link
Owner

pfan123 commented Jul 20, 2020

什么是 monorepo?

monorepo 是一种将多个 package 放在一个 repo 中的代码管理模式,摒弃了传统的多个 package多个 repo的模式。
目前 BabelReactAngularEmberMeteorJest 等许多开源项目都使用该种模式来管理代码。

解决的问题

  1. 多个 repo 难以管理,编辑器需要打开多个项目;
  2. 某个模块升级,依赖改模块的其他模块需要手动升级,容易疏漏;
  3. 公用的 npm 包重复安装,占据大量硬盘容量,比如打包工具 webpack 会在每个项目中安装一次;
  4. 对新人友好,一句命令即可完成所有模块的依赖安装,且整个项目模块不用到各个仓库去找;

带来的问题

  1. 所有 package 代码集中在一个项目,单个项目体积较大;
  2. 所有 package 代码对所有人可见,无法做权限管理;

如何实现 monorepo?

目前业界最佳实践是采用 yarn workspace + lerna 来实现。

yarn workspace 可以实现在一个项目中实现多个模块的依赖新增和共用,而lerna的功能则更完善,不仅可以管理多个模块,还有清除模块 node_modules,发布模块到 npm,自动更新模块间版本依赖,并支持全量发布和根据改动单独发布等功能。

yarn workspace 可以共享同一个 node_modules 目录,提升开发效率和降低磁盘空间占用

yarn 官方推荐用 yarn 来处理依赖安装,用 lerna 来处理依赖更新和发布问题。

yarn workspace

配置 workspace,package.json

{
  "private": true, // 项目根目录下的 private 必须设置成 true,否则 workspace 不会被启用
  "workspaces": [  // 指定需要管理的模块
      "packages/*"
  ],
}

常用命令

// 根目录安装依赖 yarn 使用 workspace 模式安装 npm 包时必须加 -W 参数
yarn add -W -D rollup typescript jest prettier

// yarn install 命令既可以在 workspace-root 目录下执行,也可在任何一个 workspace 目录下执行
yarn install

// workspace 不受 Yarn Workspace 管理,只需在此 workspace 目录下添加 .yarnrc 文件
workspaces-experimental false

// 指定 workspace 执行 command
yarn workspace <workspace_name> <command>

// 每个 workspace 下执行 <command>
yarn workspaces <command>

// 显示当前各 workspace 之间的依赖关系树
yarn workspaces info [--json]

lerna

Lerna 是一个工具,它优化了使用git和npm管理多包存储库的工作流。为开发人员提供了一种管理多packages 项目的方式:

  • 自动解决packages之间的依赖关系

  • 通过git 检测文件改动,自动发布

  • 根据git 提交记录,自动生成 CHANGELOG

工作的两种模式

  • Fixed/Locked mode (default) ,会在publish 依赖过程中根据 lerna.jsonversion

vue,babel都是用这种,在publish的时候,会在lerna.json文件里面"version": "0.1.5",,依据这个号,进行增加,只选择一次,其他有改动的包自动更新版本号。

  • Independent mode
lerna init --independent`初始化项目。 `lerna.json`文件里面`"version": "independent",

每次publish时,您都将得到一个提示符,提示每个已更改的包,以指定是补丁、次要更改、主要更改还是自定义更改。

lerna.json 设置 "useWorkspaces": true 防止与 yarn workspace 冲突

hoist

lerna bootstraphoist 功能 在 bootstrap 命令中,lerna 会自动检测 package 中相同的依赖,并将其安装在根目录下的node_modules 中,减少依赖安装次数,提升速度。

在新版的 lerna(v3.19.0) 中,当 npmClientyarn 时加上 hoist 参数时执行会报错:--hoist is not supported with --npm-client=yarn, use yarn workspaces insteadlernahoist 功能与 npmClientyarn 不兼容。由于 yarn 本身提供了较 lerna 更好的依赖分析与 hoisting 的功能。yarnhoisting算法

开启 yarn workspace

当使用 yarn workspace,并在 lerna 中开启该功能时,lerna bootstrap 命令由 yarn install 代理,等价于在 workspace 的根目录下执行 yarn install

配置 lerna.json

{
  "npmClient": "yarn",
  "useWorkspaces": true,
}

配置 package.json

{
  "workspaces": [
    "packages/*"
  ],
}

默认情况下,yarn 会开启 hoist 功能,也可以通过设置 nohoist选项 手动关闭,配置 package.json

{
  "workspaces": {
    "packages": [
      "Packages/*",
    ],
    "nohoist": [
      "**"
    ]
  }
}

有些 npm 依赖,不适合 hoist,我们可以很方便设置 nohoist,具体参考 yarn nohoist,可能也会遇到相关问题参考

常用命令

// 创建一个包 name 包名,locate 位置可选
lerna create < name > [locate]

// 增加本地或者远程 package 做为当前项目 packages 里面的依赖
lerna add [@version] [--dev] [--exact]

// 会把所有包的依赖安装到根 node_modules
lerna bootstrap

// 列出所有的包
lerna list

// 导入本地已经存在的包
lerna import

// 运行所有包里面的有这个script的命令
lerna run < script > -- [..args]

// 项目包建立软链,类似npm link
lerna link

// 删除所有包的node_modules目录
lerna clean

// 列出下次发版lerna publish 要更新的包
lerna changed

lerna publish

Other Resource

lerna/bootstrap 具体使用文档

Lerna的依赖管理及hoisting浅析

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant