【译】 Lerna + yarn Workspaces 管理 Monorepo 入门指南

Source: jsilvax. A Beginner's Guide to Lerna with Yarn Workspaces. Oct/6/2018node

当结合在一块儿时,Lerna和Yarn Workspaces能够简化和优化对多包仓库的管理。 Lerna 经过提供有用的实用命令来处理跨多个包的任务执行,使版本管理和将包发布到NPM Org中成为一种轻松的体验。 Yarn Workspaces 管理咱们的依赖关系。它不须要多个node_modules目录,而是智能地优化了依赖关系,将他们一并安装,并容许在一个monorepo中交叉连接依赖关系。Yarn Workspaces提供了像Lerna这样的工具来管理多包仓库。git

为了开始,让咱们启用Yarn Workspaces吧github

yarn config set workspaces-experimental true
复制代码

如今咱们能够经过建立一个模拟项目来讲明这些概念了npm

mkdir my-design-system && cd my-design-system
复制代码

而后,咱们初始化项目json

yarn init
复制代码

并将Lerna添加为开发依赖。bootstrap

yarn add lerna --dev
复制代码

而后你会想要初始化Lerna,这将建立一个lerna.json和一个包目录缓存

lerna init
复制代码

为了设置Lerna开启Yarn工做空间,咱们须要配置lerna.json。 让咱们添加yarn做为咱们的npm客户端,并指定咱们使用yarn工做空间。在本教程中,咱们将独立地版本化咱们的包。markdown

// lerna.json
{
  "packages": ["packages/*"],
  "version": "independent",
  "npmClient": "yarn",
  "useWorkspaces": true
}
复制代码

此时咱们应该只有一个根 package.json。在这个根 package.json中,咱们须要添加workspaces和private为true。将private设置为true将阻止根项目被发布到NPM。并发

// package.json
{
  "name": "my-design-system",
  "private": true,
  "workspaces": [
     "packages/*"
  ]  
}
复制代码

建立一个新包的流程

须要在包目录下建立新的包。让咱们建立一个模拟表单包app

cd packages
复制代码

一旦咱们进入了正确的目录,咱们就能够建立并cd到咱们的新包中了

mkdir my-design-system-form && cd my-design-system-form
复制代码

而后咱们经过运行 yarn init 来建立一个新的package.json

yarn init
复制代码

新包的名称应该遵循咱们的NPM Org scope命名方式,例如:@my-scope-name。 一样重要的是,新的包要从0.0.0这样的版本开始,由于一旦咱们使用Lerna进行第一次发布,它就会发布成0.1.0或1.0.0。

// package.json
{
  "name": "@my-scope-name/my-design-system-form",
  "version" : "0.0.0",
  "main" : "index.js"
}
复制代码

若是您有一个支持私有包的NPM Org帐户,您能够在您的模块的独立包.json中添加如下内容。

"publishConfig": {
    "access": "restricted"
}
复制代码

将本地的兄弟依赖关系添加到特定的包中

如今咱们知道了建立新包的流程,假设说咱们最后的结构是这样的。

my-design-system/
    packages/
        my-design-system-core/
        my-design-system-form/
        my-design-system-button/
复制代码

若是咱们想把my-design-system-button做为依赖关系添加到my-design-system-form中,并让Lerna将它们进行符号连接,咱们能够经过cd到该包中来实现。

cd my-design-system-form 
复制代码

而后运行如下内容。

lerna add @my-scope-name/design-system-button --scope=@my-scope-name/my-design-system-form
复制代码

这将更新@my-scope-name/my-design-system-form的package.json。 咱们的package.json应该是这样的。

// package.json
{
  "name": "@my-scope-name/my-design-system-form",
  "version": "1.0.0",
  "main": "index.js",
  "dependencies": {
    "@my-scope-name/my-design-system-button": "^1.0.0"
  }
}
复制代码

如今,你能够在index.js中引用这个本地依赖关系,如

import Button from '@my-scope-name/my-design-system-button';
复制代码

为全部的包添加一个 "共同 "的依赖关系

作法和前面的命令相似。不过这是针对/packages/* 的。无论你要加的依赖是本地的同级依赖仍是来自NPM的依赖,都不要紧。

lerna add the-dep-name
复制代码

若是你有常见的开发依赖,最好在 workspace 的 root package.json中指定。例如,能够是Jest、Husky、Storybook、Eslint、Prettier等依赖项

yarn add husky --dev -W
复制代码

*添加-W标志,就能够明确表示咱们要把依赖关系添加到工做区根目录。

删除依赖

若是有一个全部包都使用的依赖,但你想删除,Lerna有exec命令,能够在每一个包中运行一个任意命令。有了这些知识,咱们就可使用exec来删除全部包的依赖关系。

lerna exec -- yarn remove dep-name
复制代码

运行测试

Lerna提供了run命令,它将在每一个包含了npm脚本的包中运行该脚本。 例如,假设咱们全部的包都遵循my-design-system-form的结构。

my-design-system-form/
    __tests__/
        Form.test.js
复制代码

在每一个package.json中,咱们都有测试的npm脚本。

"name": "@my-scope-name/my-design-system-form",
"scripts": {
    "test": "jest"
}
复制代码

而后Lerna能够经过运行每一个测试脚原本执行。

lerna run test --stream
复制代码

*-stream 这个flag提供子进程的输出。

发布到NPM

手动

首先,你须要确保你已经登陆了。你能够经过如下操做来验证你是否已经登陆。

npm whoami // myusername
复制代码

若是你没有登陆,请运行如下内容并按照提示操做。

npm login
复制代码

登陆后,您能够经过运行Lerna发布。

lerna publish
复制代码

Lerna会提示你更新版本号。

自动

Lerna支持使用Conventional Commits Standard在CI环境中自动进行语义版本管理。 这使开发人员可以像下面这样提交

git commit -m "fix: JIRA-1234 Fixed minor bug in foo"
复制代码

而后在CI环境中,包的版本能够根据上面的提交更新并发布到NPM。这能够经过配置你的CI环境来完成。

lerna publish --conventional-commits --yes 
复制代码

若是你不想传递flag,能够在你的lerna.json文件中添加如下内容。

"command": {
    "publish": {
       "conventionalCommits": true, 
       "yes": true
    }
}
复制代码

强制执行 Conventional Commits

若是你想强制执行 Conventional Commits 标准,我建议在项目的ROOT中加入Commitlint。

yarn add @commitlint/cli @commitlint/config-conventional husky cross-env --dev
复制代码

而后在根package.json中建立一个发布脚本

"scripts": {
    "release": "cross-env HUSKY_BYPASS=true lerna publish"
}
复制代码

这个发布脚本将在CI环境中运行。请注意,咱们在 lerna.json 文件中配置了传统的提交和 "yes "标志。因为这个CI环境将会把版本的变动提交,咱们不但愿触发提交消息的inting。咱们经过添加一个名为HUSKY_BYPASS的环境变量来实现,咱们将使用cross-env将其设置为true。 咱们还须要在root package.json中添加进一步的配置。

"husky": {
    "hooks": {
    "commit-msg": "[[ -n $HUSKY_BYPASS ]] || commitlint -E HUSKY_GIT_PARAMS"
    }
},
"commitlint": {
    "extends": ["@commitlint/config-conventional"]
}
复制代码

对于husky,咱们添加了一个commitlint/config-conventional的commit-msg钩子,它将检查咱们在上面添加的HUSKY_BYPASS环境变量,若是这个变量是假的,那么咱们经过@commitlint/config-conventional来精简提交消息。

分离版本控制与发布

若是出于任何缘由,你想彻底掌控版本控制,Lerna有能力将版本控制和发布分红两个命令。 你能够手动运行。

lerna version
复制代码

而后按照提示更新各个版本号。 而后你就能够有一个步骤,读取最新的标签(是手动更新的)发布到NPM。

lerna publish from-git --yes
复制代码

多贡献者参与的本地开发

每当有新的贡献者对你的项目进行git克隆,或者你须要拉取你团队的最新变化时,你必须运行yarn命令。

yarn
复制代码

在大多数的Lerna教程中,提倡使用lerna bootstrap命令,然而当启用yarn工做空间时,这是没必要要的,也是多余的

lerna bootstrap when you're using Yarn workspaces is literally redundant? All lerna bootstrap --npm-client yarn --use-workspaces (CLI equivalent of your lerna.json config) does is call yarn install in the root. — Issue 1308
复制代码

更多信息见github.com/lerna/lerna…

跨项目的本地开发

在咱们的例子中,咱们正在构建一个多包设计系统。若是开发人员想在设计系统中建立一个新的组件,但在发布以前也要在本地客户端应用程序中进行测试,他们能够经过使用yarn的连接命令来实现。

创建本地依赖关系的symlink

假设咱们想在my-client-app中使用咱们本地的my-design-system-core。 咱们先cd到咱们要在另外一个项目中用到的软件包。

cd ~/path/to/my-design-system/my-design-system-core
复制代码

而后咱们建立一个symlink

yarn link
复制代码

你应该看到这样的输出

success Registered "@my-scope-name/my-design-system-core".
info You can now run `yarn link "@my-scope/my-design-system-core"` in the projects where you want to use this module and it will be used instead.
复制代码

如今咱们的包已经有了符号连接,咱们能够进入my-client-app中使用。

cd ~/path/to/my-client-app 
yarn link @my-scope-name/my-design-system-core
复制代码

/packages/my-design-system-core 中的任何变化都会反映在my-client-app中。如今,开发人员能够很容易地在两个项目上进行本地开发,并看到它的反映。

解除本地依赖关系的连接

当开发者完成后,再也不想使用本地的包时,咱们须要解除连接。 cd到入咱们要解除连接的包中

cd ~/path/to/my-design-system/my-design-system-core
复制代码

运行unlink删除本地symlink

yarn unlink
复制代码

你会看到这样的输出

success Unregistered "@my-scope-name/my-design-system-core".
info You can now run `yarn unlink "@my-scope-name/my-design-system-core"` in the projects where you no longer want to use this module.
复制代码

如今,咱们能够cd到my-client-app中解除连接。

cd ~/path/to/my-client-app
yarn unlink @my-scope-name/my-design-system-core
复制代码

总结

Lerna与Yarn Workspaces是一个很好的组合。Lerna 在 Yarn Workspaces 的基础上增长了实用功能,用于处理多个包。纱线工做空间使得全部的依赖关系能够一块儿安装,使得缓存和安装速度更快。它让咱们能够经过一个命令轻松地在NPM上发布依赖关系,当依赖关系的版本发生变化时,自动更新兄弟依赖关系的package.json,通常来讲,安装、版本管理和发布都是一种无痛的体验。

相关文章
相关标签/搜索