参考(这几篇文章很重要,一定要看)
lerna(中文)
现代前端工程化-彻底搞懂基于 Monorepo 的 lerna 模块(从原理到实战)
Node.js 如何创建软链接,与硬链接有什么区别?
我们的项目用到了lerna管理包,在做了大概1年多的项目之后,重新用lerna来管理,为什么突然间要用呢?
因为我们有项目A(vue项目),对应后端的项目B(node.js),这两个项目都是对公司内部的,这两个项目里面有很多共同的utils,假设在项目A要找一个接口,并且要去看接口对应项目B的后端代码时,我们要打开两个项目,然而这些似乎不是很大的一个问题
后来要开发一个新的后端管理系统,给b端客户看,并且这个系统与我们A.B项目在接口上有很多需要互通的,
,对应项目项目C(vue项目),对应后端的项目D(node.js),这个时候就提出来了lerna管理包,因为A和c使用的包几乎一致,并且之前有在A上封装了不少项目内部的npm包发布到私服.B,D也是一致的,这时候
我们要解决的问题应该是,也是lerna能够解决的问题
1.同样的包不应该每个项目都下载,这样太占浪费了大量存储空间
2.私服的包虽然稳定,但是并不是一成不变的,如何调试更简单
3.相互联系的项目如何减少联调时间
4.一个项目依赖了多个 npm 包,当某一个子 npm 包代码修改升级时,都要对主干项目包进行升级修改。
(这个问题感觉是最烦的,可能一个版本号就要去更新一下代码并发布)
1.如何将已经存在的项目用lerna管理并运行
假设我有一个用vue-cli新建的project01项目(已存在)
1.1 新建lerna项目
mkdir lerna-repo && cd $_
npx lerna init
1.2 新建package
lerna create project01
将project01里所有的文件(除了package.json)放到packages/project01底下,再就将package.json内容复制到packages/project01/package.json里面,保留有用的信息
1.3 配置lerna.json文件以及package.json文件
yarn workspaces ,可以解决前面说的当不同的项目依赖不同的版本号问题, yarn workspaces会检查每个子项目里面依赖及其版本,如果版本不一致都会保留到自己的 node_modules 中,只有依赖版本号一致的时候才会提升到顶层。注意:这种需要在 lerna.json 中增加配置。
{
"packages": [
"packages/*"
],
"npmClient": "yarn",
"useWorkspaces": true,
"version": "independent"
}
顶层的 package.json配置
"workspaces":[
"packages/*"
],
注意lerna默认使用的是集中版本,所有的package共用一个version,如果需要packages下不同的模块 使用不同的版本号,需要配置Independent模式。命令行介绍时有提到这里 在json 中增加属性配置
如果是成熟的项目,合并到一起,用到了同一个包,不用的版本,可以采用Independent模式,我这里也用这个,因为我觉得这样更加灵活
1.4 yarn install
可以在lerna-repo地下进行安装,也可以在project底下进行安装
1.5 运行
cd packages
cd project01
npm run serve
2.如何在最顶级目录运行子项目
2.1在顶级的package.json里面配置
"scripts": {
"project01-dev": "lerna exec --scope project01 -- yarn serve"
}
不同的环境应该配置多个project01-XXX project01表示是packages地下的项目名,serve对应的是project01底下package.json里面的scripts项
2.2运行
npm run project01-dev
3. 如何调试私服的npm 项目
lerna create bingxixi-private-common-utils
将bingxixi-private-common-utils里所有的文件(除了package.json)放到packages/bingxixi-private-common-utils底下,再就将package.json内容复制到packages/bingxixi-private-common-utils/package.json里面,保留有用的信息, 一定要注意main的指向是对的.
在bingxixi-private-common-utils的文件夹上加上@号进行软链
yarn install
在project01的main.js里面引入
import { userPrivate, getNumBit } from 'bingxixi-private-common-utils'
Vue.prototype.$userPrivate = userPrivate
Vue.prototype.$getNumBit = getNumBit
在修改@bingxixi-private-common-utils里面的信息时,project01呈现的页面也会改变
4.测试2个相似的项目,相同的包会被提到最顶级的node_modules
在project01和project02都没有进行install的情况下,project02和project01的内容完全一致,不管是在任一个package里面运行以下,都会有公共的包会提到顶级的node_modules里面
以上解决了私服的包虽然稳定,但是并不是一成不变的,如何调试更简单
yarn install
这个也就是他主要的作用之一,解决了我们项目同样的包不应该每个项目都下载,这样太占浪费了大量存储空间
5.lerna clean
执行lerna clean,只会删除packages地下的项目的node_modules,并不会对最顶级的node_modules进行删除
6.测试同一个包,不同的版本
6.1错误的示范
bingxixi-common-title有7个版本
假设我的project01的package.json里面
假设我的project02的package.json里面
yarn install 之后
project01和project02里面都找不到bingxixi-common-title,而顶级的node_modules里面居然是"version": "1.0.7",这似乎与我们的猜想完全不符,是因为这里不应该加上^
表示安装大版本的最高中版本: ^版本,比如 "antd": "^3.1.4",
表示安装3.1.4及以上的版本,但是不安装4.0.0,也就是说安装时不改变大版本号。
意思就是平时我们用一个包,都说的n点m版本的,也许有比n更大的,也许有比n更小的,
而加上^就会安装n点max的版本,所以如果加上^我们测试不出来不同版本下lerna如何处理
6.2 正经测试(去掉上面提到的^符号)
1.先去掉上面提到的^符号
2.一定要进行lerna clean,不然测试出来的效果可能会乱
lerna clean --y
3.安装
yarn install
4.结果
顶级node_modules
project01的node_modules里面并没有bingxixi-common-title包
而project02的node_modules里面
在功能上确实是符合:所有的package共用一个version,如果需要packages下不同的模块 使用不同的版本号,需要配置Independent模式
经过多次测试,发现顶级的node_modules一直都是package.json里面最低版本的,而其他的稍高版本的会放到对应的项目模块底下,根据node的文件查询规则,不同的项目同一个包不同版本会被保留,按照最初的版本使用
3 关于independent模式的思考(希望大家来指正)
参考: lerna多包管理实践
lerna默认使用的是集中版本,所有的package共用一个version,如果需要packages下不同的模块 使用不同的版本号,需要配置Independent模式。
固定模式 --exact
固定模式,通过lerna.json的版本进行版本管理。当你执行lerna publish命令时,
如果距离上次发布只修改了一个模块,将会更新对应模块的版本到新的版本号,然后你可以只发布修改的库。
这种模式也是Babel使用的方式。如果你希望所有的版本一起变更, 可以更新minor版本号,
这样会导致所有的模块都更新版本。
独立模式 --independent
独立模式,init的时候需要设置选项 --independent. 独立模式允许管理者对每个库单独改变版本号,
每次发布的时候,你需要为每个改动的库指定版本号。这种情况下, lerna.json的版本号不会变化了,
默认为independent。
意思就是采用固定模式,任何一处改动,所有packages里面的项目的version号都会变,而且是一致的.
采用independent是packages里面的项目的version号只有在各自项目变化的时候才更新,我的理解就是:如果需要各个组件维护自身的版本号,那么就使用independent模式,假设你的私包作为你的npm包,开始是1.0.0版本,后续需要变化才顺序更新,可以采用independent
4.使用lerna的一点感悟(相比之前)
我们用lerna主要是为了节省了大量存储空间,如果统一私服的包管理,可以使用lerna publish,所以我们项目种并没有用到包发布这块
优点:
1. 节省了内存空间,比如常见了vue,element ui,egg等包,不用重复下载
2. 前后端联调更加简单,搜索接口,能快速找到对应的部分(以一个项目整体来看)
3. 比如搜索关键词,几个项目可能有很多相同,又可以单独运行来搜索
4. 修复bug的时候,可以多个项目一起修改,审核mr也是只用去看那一个项目
5. 减少代码的复用,可以将公共部分提取出来
6. 与npm私包软链更简单
缺点:
1.我们后面将6.7个项目都放到lerna管理,刚开始合并的过程是需要花费不少时间的,我所列举的是一小部分
2.yarn install还是要很长时间的