#关键词#
- Lerna
- 源码
- 本地调试
- yargs
#前期准备#
1、找到lerna github官方源码仓库:https://github.com/lerna/lerna.git
2、git clone 克隆源码到本地
3、打开IDE:VSCODE
4、npm install 安装依赖
5、切换到Tags-v3.22.1版本:根据自行需要切换
6、找到lerna入口文件:根目录的package.json里有提示,或者直接找到core/lerna目录下的package.json文件
7、vscode打开node调试工具进行本地断点调试:
其中调试按钮解析如下:
- continue:继续执行程序,直到遇到下一个断点为止
- step over:在普通代码行运行时,会逐行运行程序。若遇到调用自定义函数命令,且在该定义的函数里没有断点,则直接运行完该函数,不会进入该函数并逐行运行该函数内的代码
- step into:逐行顺序运行程序。若遇到自定义函数(def),则进入该函数,逐行运行该函数内的代码。即,该步骤会按顺序走程序里的每一步
- step out:当前运行在自定义函数(def)里时,如果在该自定义函数里没有断点,则会直接运行完当前自定义函数,停在调用函数的那一行
#源码阅读#
以执行lerna ls命令为例:
1:入口解读
- require('.'):类似于require('./index.js')的写法
- process.argv.slice(2):通过process.argv获取命令参数,前两个参数分别是process.execPath和当前执行的JavaScript文件路径,命令参数从第三个参数开始截取,此时截取到的是ls命令
2、 进入到index.js(如下图1)文件,找到exports出的main函数进行执行解读
- 进入@lerna/cli包(如下图2):exports出的lernaCLI()函数,是一个yargs对象,并传入globalOptions函数中返回经过一系列options配置后的yargs对象
- main函数执行:其中cli()返回的是yargs对象,通过yargs进行ls命令的注册
- ls命令注册:cli().command(listCmd)
图1
图2
3、npm 项目本地依赖引用方法
- 上章有讲过本地依赖调试引用是通过npm link的方式来实现的,存在很大的问题,需要手动进行操作,并且上线后要全部进行unlink,如果把项目里所有包都link到全局的node_modules下,占空间不说,还会导致全局的link关系变的特别复杂和混乱
- lerna项目本地依赖都是通过 file: 来引用(见下图1)
- lerna发布后会通过resolveLocalDependencyLinks方法将file: 相关的文件链接到实际的本地文件路径(见下图2)
图1
图2
#yargs快速入门#
1、安装yargs库:npm install yargs -s
2、代码示例:
#!/usr/bin/env node
const yargs = require('yargs/yargs');
const argv = process.argv.slice(2);
const cli = yargs();
const pkg = require('../package.json');
const context = {
hdkCliVersion: pkg.version
}
cli
// 使用说明
.usage('Usage: hdk-cli [command] <options>')
// 最少命令数
.demandCommand(1, "a command is required")
// 严格模式,不能识别命令时会有错误提示
.strict()
// 输错命令,找最相似的命令返回
.recommendCommands()
// 处理错误定制
.fail((err, msg) => {
console.log(err);
console.log(msg);
})
// 别名
.alias("h", "help")
.alias("v", "version")
// 定义命令宽度
.wrap(cli.terminalWidth())
// 结束语
.epilogue('footer')
.options({
debug:{
type: 'boolean',
describe: "debugger",
alias: 'd'
}
})
.option('registry', {
type: 'string',
describe: "define registry",
alias: 'r'
// hidden: true
})
// 命令分组
.group(['debug'], "dev options")
.command('init [name]', 'init project', (yargs) => {
yargs.option('name', {
type: 'string',
describe: 'name of project',
alias: 'n'
})
},(argv) => {
console.log(argv)
})
.command({
command:'list',
alias:['ls'],
describe: 'list project',
builder:(yargs) => {},
handler:(argv) => {}
})
// .argv; 合并注入参数
.parse(argv, context)