北京的野桃花也开了,又是一年春草绿。
技术日新月异,似乎一眨眼间一年、三年、五年抑或十年、二十年就这么过去了。
人在江湖,看人来人往,是否也有这样一个问题从你脑海掠过——远望前路,什么东西,或可抵岁月漫长?
是外力吗?肯定不是,至少外力不可持续依赖。
是激情吗?未必,火热的东西往往来得快去得也快。
是毅力吗?那么毅力又因何而来的呢?
真正催人奋进的,应该是一个接一个的所谓梦想吧。
——题记
一、初始化项目
首先执行如下命令:
mkdir test-lerna
cd test-lerna
lerna init
这时,我们得到初始目录结构如下,并发现在根目录下生成了lerna.json。
接着,我们在packages目录下新建两个文件夹: package1 和 package2,其中通过npm init
各生成一个package.json文件,并把package.json中的name分别改为:'@dennis/package1' 和 '@dennis/package2'。文件内容如下。
package1/package.json:
{
"name": "@dennis/package1",
"version": "0.1.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "MIT"
}
package2/package.json:
{
"name": "@dennis/package2",
"version": "0.1.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "MIT"
}
这时目录结构如下:
不过,其实创建package有可以直接使用的命令,比如执行lerna create @dennis/package3
就可以在packages目录下创建一个package3,生成的package的目录如下所示:
二、给某一package添加依赖
执行:
lerna add typescript --scope=@dennis/package1 -D
添加后package1/package.json如下所示:
{
"name": "@dennis/package1",
"version": "0.1.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "MIT",
"devDependencies": {
"typescript": "^4.2.3"
}
}
我们发现,devDependencies中添加了typescript这一依赖项。并且,typescript依赖也被安装到了package1文件夹下的node_modules目录下。如下图所示:
其中,
--scope 参数用于指定单独为某个package添加一个依赖;
-D 参数和npm install -D
中的-D所表示的含义一样(-D也可改成--dev),即将该依赖添加到devDependencies中。如果不指定-D的话,这个依赖默认会被添加到dependencies中。
三、让packages下的package1依赖package2
如果想让packages下的package1依赖package2,怎么实现呢?
注意,这个时候不需要将package2先发布到NPM。
首先,先执行:
lerna add @dennis/package2 --scope=@dennis/package1@^0.1.0
这样会把@dennis/package2加入到package1的denpendencies中。另外,我们会发现执行该命令后package1/node_modules目录下已经“安装”上了@dennis/package2这个依赖。如下图所示:
其中,@^0.1.0用于指定@dennis/package1的版本号。
当指定的版本号与@dennis/package2的package.json中真实的版本号不相匹配时,会出现如下错误提示:
接下来,我们来给package1和package2写点代码,测试下依赖是否能正常使用。
package2/index.js:
module.exports = {
log: function(str) {
console.log(str);
}
}
package1/index.js:
const { log } = require('@dennis/package2');
log('Hello, world!');
然后再切换到test-lerna/packages/package1目录下执行node index.js
,可在控制台看到输出了
Hello, world!
这表明依赖是可以正常工作的。
接下来,我们来测试下如果package2/index.js进行了修改会怎么样。
我们把package2/index.js的内容改成如下(即在原有的基础上添加的sayHi方法):
module.exports = {
log: function(str) {
console.log(str);
},
sayHi: function() {
console.log('Hi!');
}
}
同时把package1/index.js的内容改成如下:
const { log, sayHi } = require('@dennis/package2');
log('Hello, world!');
sayHi();
然后再切换到test-lerna/packages/package1目录下再次执行node index.js
,可在控制台看到输出了
Hello, world!
Hi!
表明package2的更新会自动作用过来,并不需要做什么类似对package2进行再次添加依赖之类的工作。
四、给所有package添加同一依赖
如果想给packages目录下的所有pakcage都添加同一依赖(比如underscore)应该怎么做呢?可以执行如下命令:
lerna add underscore
这样就会给packages目录下的所有pakcage都添加上underscore这一依赖。相比于上面讲过的给某一package添加依赖,区别就是没有指定--scope选项。
但这样处理有个问题,那就是会在每个package下的node_modules中安装一份underscore模块。package和package之间并不是共用的。怎么做到共用呢?
首先我们执行lerna clean
将packages目录下所有的packages下每个package下面的node_modules全部清除,并通过手工方式将package-lock.json都删除,同时将package.json的dependencies中的underscore依赖项删除。
然后我们test-lerna目录下的package.json修改成:
{
"name": "root",
"private": true,
"devDependencies": {
"lerna": "^3.22.1"
},
"workspaces": [
"packages/*"
]
}
同时把test-lerna目录下的lerna.json修改成:
{
"version": "0.0.0",
"npmClient": "yarn",
"useWorkspaces": true
}
然后再次执行lerna add underscore
就会发现,如下图所示underscore被安装到了下test-lerna/node_modules目录中,实现了多个package中共用这一份:
五、执行某个package下的命令
使用:
lerna run serve --scope=@dennis/package1
效果相当于:
cd packages/package1
npm run serve
六、lerna的一些其它常用命令
lerna bootstrap
:等同于 lerna link
+ yarn install
,用于创建符合链接并安装依赖包;
lerna run
:会像执行一个 for 循环一样,在所有子项目中执行 npm script 脚本,并且,它会非常智能的识别依赖关系,并从根依赖开始执行命令;
lerna exec
:像 lerna run
一样,会按照依赖顺序执行命令,不同的是,它可以执行任何命令,例如 shell 脚本;
lerna publish
:发布代码有变动的 package,因此首先您需要在使用 Lerna 前使用 git commit
命令提交代码,好让 Lerna 有一个 baseline;
Lerna 还提供了一些参数满足我们更灵活的需求,例如:
--concurrency :参数可以使 lerna 利用计算机上的多个核心,并发运行,从而提升构建速度。