使用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 lreact
lerna 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安装vue
lerna add vue --scope=lvue
# 或 lerna add vue packages/lvue
# 或 lerna add vue **/lvue
# 给lreact安装react
lerna add react --scope=lreact
# 给lnode安装lodash
lerna 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() {
// TODO
console.log("lreact");
// 执行lnode包
lnode();
}
lreact();
修改lnode包下的/lib/lnode.js
module.exports = lnode;
const lvue = require("lvue");
const _ = require('lodash')
function lnode() {
// TODO
console.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 start
lerna exec --scope=lreact -- yarn run start
删除包中的依赖node_modules
lerna clean
从所有包中删除 node_modules 目录。不会删除项目最外层的根 node_modules
发布包到npm
发布之前需要先登录npm,使用npm adduser进行登录。
执行发布包 命令
lerna publish