使用lerna创建库
monorepo、lerna是什么?
Monorepo 是管理项目代码的一个方式,指在一个项目仓库 (repo) 中管理多个模块/包 (package),不同于常见的每个模块建一个 repo。
Lerna是一种Monorepo的解决方案
Lerna是一个用来优化托管在 git\npm 上的多 package 代码库的工作流的一个管理工具,可以让你在主项目下管理多个子项目,从而解决了多个包互相依赖,且发布时需要手动维护多个包的问题。
典型场景描述
- 有一个业务组件仓库,里边有 N个 业务组件
- 每个业务组件是一个 单独 的 npm 包
- 作为一个 包管理者
- 每一次仓库的更新,都意味极有可能需要发一遍包
lerna处理机制
lerna 对于包的管理,有两种模式:固定模式(fixed)、独立模式(independent)。
- 固定模式(fixed):所有包是统一的版本号,每次升级,所有包版本统一更新
lerna 的配置文件 lerna.json 中永远会存在一个确定版本号
{"version": "0.0.1"}
- 独立模式(independent):每个包是单独的版本号,每次lerna 触发发布命令,每个包的版本都会单独变化.
lerna 的配置文件 lerna.json 中没有一个确定版本号
{"version": "independent"}
Lerna 初始化
安装lerna
$ npm i lerna -g
项目初始化
$ cd lerna-first# 默认是 fixed 模式$ lerna init# 创建的项目多数采用 independent 模式$ lerna init -i #或者 lerna init --independent
生产目录结构
└── lerna-pro/├── packages/├── lerna.json└── package.json
创建package包
lerna create lvue //创建一个新的由 lerna 管理的包lvue
执行的配置命令采用默认
package name: (lvue)version: (1.0.0)description:keywords:homepage:license: (ISC)entry point: (lib/lvue.js)git repository: (https://gitee.com/shenshuai89/lerna-first.git)About to write to /Users/shuai/Desktop/code/nodeapp/lerna-pro/lerna-second/packages/lvue/package.json:{"name": "lvue","version": "1.0.0","description": "> TODO: description","author": "shuai <shenshuai89@qq.com>","homepage": "","license": "ISC","main": "lib/lvue.js","directories": {"lib": "lib","test": "__tests__"},"files": ["lib"],"repository": {"type": "git","url": "https://gitee.com/shenshuai89/lerna-first.git"},"scripts": {"test": "echo \"Error: run tests from root\" && exit 1"}}Is this OK? (yes)lerna success create New package lvue created at ./packages/lvue
同样创建其它两个包
lerna create lreactlerna create lnode
此时项目目录结构
├── lerna.json├── package.json└── packages├── lnode│ ├── README.md│ ├── __tests__│ │ └── lnode.test.js│ ├── lib│ │ └── lnode.js│ └── package.json├── lreact│ ├── README.md│ ├── __tests__│ │ └── lreact.test.js│ ├── lib│ │ └── lreact.js│ └── package.json└── lvue├── README.md├── __tests__│ └── lvue.test.js├── lib│ └── lvue.js└── package.json
查看项目下所有包
lerna list# lerna info versioning independent# lnode# lreact# lvue# lerna success found 3 packages
添加包的依赖
使用lerna add packageName
给所有 package 安装依赖,执行下面命令后给三个包的package.json 添加了axios包依赖
lerna add axios
给指定 package 安装依赖
# 给lvue安装vuelerna add vue --scope=lvue# 或 lerna add vue packages/lvue# 或 lerna add vue **/lvue# 给lreact安装reactlerna add react --scope=lreact# 给lnode安装lodashlerna add lodash --scope=lnode
workspace 之间的依赖 命令执行完成后
lreact/package.json lnode/package.json# lreact添加lnode依赖lerna add lnode --scope lreact# lnode添加lvue依赖lerna add lvue --scope lnode
"dependencies": {"axios": "^0.21.4","lnode": "^1.0.1","react": "^17.0.2"}
"dependencies": {"axios": "^0.21.4","lodash": "^4.17.21","lvue": "^1.0.1"}
执行包的命令
lerna exec [command]
将三个包下的package.json中的scripts添加start命令,用来执行入口文件
"scripts": {"start": "node lib/lnode.js"}
修改lreact包下的/lib/lreact.js
// 引入lnode包const lnode = require("lnode");module.exports = lreact;function lreact() {// TODOconsole.log("lreact");// 执行lnode包lnode();}lreact();
修改lnode包下的/lib/lnode.js
module.exports = lnode;const lvue = require("lvue");const _ = require('lodash')function lnode() {// TODOconsole.log("lnode");console.log(_.flattenDeep([1, [2, [3, [4]], 5]]));lvue();}lnode();
修改完成后,可以执行,该命令会执行三个包中的所有yarn run start脚本
lerna exec -- yarn run start
单独执行不同包下的脚本
lerna exec --scope=lnode -- yarn run startlerna exec --scope=lreact -- yarn run start
删除包中的依赖node_modules
lerna clean
从所有包中删除 node_modules 目录。不会删除项目最外层的根 node_modules
发布包到npm
发布之前需要先登录npm,使用npm adduser进行登录。
执行发布包 命令
lerna publish
