Lerna+Yarn workspace管理多npm

背景

我们在管理项目常遇到这些问题:

  1. 新建项目需要重新配置各种工具,繁琐,虽然也可以用脚手架生成,但后期涉及到依赖的升级也麻烦
  2. babel、eslint-config、stylelint等配置希望可以多项目共享。

其实为了解决上述问题,我们可以项目内使用** lerna + yarn workspaces**

Monorepo 和 Multirepo

multirepo

multirepo也就是我们常见的做法,也就是每一个package都单独用一个仓库去管理。例如,Webpack, babel…
这样可以多元化发展(各项目都有自己的构建工具,依赖管理策略,单元测试)。
但是多个npm导致复用的时候就要关心版本号,不好找出问题。
image.png

monorepo

monorepo是把所有相关package都放在一个仓库里进行集中管理,减少项目间的差异带来的各种成本。
所以我们开发的时候把一些可以共用的配置,比如eslint,babel,rollup等,可以统一的管理这些开发配
,开发者只需要关心业务代码,不需要关心复用方式

image.png

monorepo的项目结构,一般都会配合 yarn workspace 来管理包的依赖。

yarn workspaces – 管理包

使用yarn workspaces的项目,根目录我们叫它workspace root(工作区根目录)。

如何开启?

  • 在项目根目录的 package.json 中添加这段代码
// 项目提交到 github 或发布到 npm 的时候,禁止提交当前根目录的内容。
// 当组件库开发完毕后,要发布到 NPM。工作区的根目录一般是脚手架,不需要发布。
// private 是为了防止意外把内容暴露出去。
"private": true,
// 存储要管理的所有包的路径
"workspaces": [
  "packages/*"
]
复制代码

依赖管理

  1. workspace依赖 —— 也就是package与package之间互相引用
# lerna add <package>[@version] [--dev] [--exact]
npx lerna add xxx --scope yyy
复制代码
  1. package依赖 —— 具体某个包的依赖
# yarn workspace <workspace_name> [add xx][remove xx]
yarn workspace www add vue
复制代码
  1. 公共依赖 – 比如babel,eslint等工具依赖,需要共享配置
# 在根目录下进行
yarn add vue -D -W
复制代码

lerna – 统一发布项目中的所有包

Lerna 是一个管理多个 npm 模块的工具,是 Babel 自己用来维护自己的 Monorepo 并开源出的一个项目。优化维护多包的工作流,解决多个包互相依赖,且发布需要手动维护多个包的问题。

如果使用了Lerna,那么仓库结构会变成:
image.png

常用步骤

1. 安装

  1. 全局安装
npm i -g lerna
复制代码
  1. 项目内安装 – 在 package.json 中添加开发依赖(保证其他开发者使用时安装了lerna)
yarn add lerna --dev
复制代码
{
  //...
  "devDependencies": {
  	//...
    "lerna": "^3.22.1",
  }
}
复制代码

2. 创建项目

  1. 初始化
lerna init
复制代码

初始化后:

  1. 如果当前项目没有被 git 管理,会进行 git 初始化
  • 在项目根目录创建一个 lerna.json 的配置文件
// lerna.json
{
  // 所要管理的包的路径,默认是["packages/*"],不是从 package.json 获取的
  // 如果根目录中没有 packages,就会自动创建该目录
  "packages": [
    "packages/*"
  ],
  // 当前项目初始化版本
  "version": "0.0.0"
}
复制代码
  1. 启动yarn workspaces
// 在lerna.json内增加如下内容以在lerna内启用yarn workspaces
{
  "npmClient": "yarn"
  "useWorkspaces": true
}
复制代码

3. 添加子包

环境初始化好,需要添加一个子包,命令

lerna create <pkgName>
复制代码

子包默认的目录结构如下:
image.png

4. 打版本

lerna的version_bump和changelog生成都依赖于conventional-commit,因此需要保证commit-msg符合规范。

version_bump

发版的时候需要更新版本号,这时候如何更新版本号就是个问题,好的办法是根据 git 的提交记录自动更新版本号,实际上只要我们的 git commit message 符合Conventional commit 规范,即可通过工具根据 git 提交记录,更新版本号。
简单的规则如下:

  • 存在 feat 提交: 需要更新 minor 版本。
  • 存在 fix 提交: 需要更新 major 版本。
  • 存在BREAKING CHANGE提交: 需要更新大版本。

步骤:

  1. 添加@commitlint/cli和@commitlint/config-conventional和husky以及git-cz添加git-cz,支持commit-msg提示。
yarn add -W -D @commitlint/cli @commitlint/conventional-commit lint-staged husky commitizen cz-conventional-changelog
复制代码
  1. 配置commitlint
// commmitlint.config.js
module.exports = {
  extends: [
    "@commitlint/config-conventional"
  ]
};
复制代码
  1. 在package.json配置commit-msg的hooks
{
  "scripts": {
    "commit": "git-cz"
  },
  "config": {
    "commitizen": {
      "path": "cz-conventional-changelog"
    }
  },
  "husky": {
    "hooks": {
      "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
    }
  }
}
复制代码

这样后续commit,就可以使用yarn commit进行commit,其会自动做出如下提示
图片[1]-Lerna+Yarn workspace管理多npm-一一网
其自动生成的commit-msg如下

5. 发布

  1. 修改lerna.json配置文件
{
	...
  "command": {
    "publish": {
      "ignoreChanges": ["*.md"],
      "registry": "https://registry.npmjs.org/",
      "verifyAccess": false, // 内网发包需开启
      "verifyRegistry": false, // 内网发包需开启
      "message": "chore: publish" // 修改默认的publish的commit msg
    }
  }
}
复制代码
  1. 配置发版的策略,我们积极convention-commit来发版
{
   "scripts": {
    // 生成changelog文件以及根据commit来进行版本变动,不提示用户输入版本
    "versions": "lerna version --conventional-commits  --yes" 
  },
	 "publishConfig": {
    "access": "public"
  }
}
复制代码
lerna publish from-git
复制代码

发布npm包是需要登录npm账号的,这里有个要注意的问题。
图片[2]-Lerna+Yarn workspace管理多npm-一一网
原因是没登录npm,其实原因很简单,想发布个东西总得让人家知道你是谁吧,好的,现在解决问题只需要两步。

  1. 切换到npm源(切记记得记得)
npm config set registry=https://registry.npmjs.org
复制代码
  1. 登录 / 添加用户
npm adduser/ npm login
复制代码

image.png

5. 维护依赖

当我们维护这个项目时,新拉下来仓库的代码后,需要为各个 package 安装依赖包。
当我们为某个packagea安装的包都放到了这个package目录下的node_modules。
这样如果多个package机会有多个node_modules。
image.png
我们使用 –hoistba把每个依赖包提升到跟目录,降低安装以及管理的成本。

lerna bootstrap --hoist
复制代码

也或者我们不想每次都输入–hoist参数,可以在lerna.json配置:

{
 ...
  "command": {
    "bootstrap": {
      "hoist": true
    }
  },
 	...
}
复制代码

配置好后,对于之前依赖包已经被安装到各个 package 下的情况,我们只需要清理一下安装的依赖即可:

lerna clean
复制代码

执行 lerna bootstrap 即可看到 package 的依赖都被安装到根目录下的 node_modules 中了。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享