Node
多进程开发JavaScript
对面对象的实战技巧Node
多进程原理Command
和 Package
类Node
多进程实现动态命令加载和执行Node
多进程 child_process
源码分析Class
完成 JavaScript
面向对象编程Node
多进程 - 深入 Node
多进程原理安装依赖
lerna add commander core/cli/
// core\cli\lib\index.js
// 引入封装的 init 命令
const init = require('@hzw-cli-dev/init');
// 创建一个 commander 实例
const program = new commander.Command();
/**
* @description: 注册命令
* @param {*}
* @return {*}
*/
function registerCommand() {
// 注册 debug 模式
program
.name(Object.keys(pkg.bin)[0])
.usage('<command> [options]')
.version(pkg.version)
.option('-D, --debug', '是否开启调试模式', false);
// 注册命令
program
.command('init [projectName]')
.option('-f, --force', '是否强制初始化项目')
.action(init);
// 获取参数
const params = program.opts();
// 注册 debug 命令
program.on('option:debug', () => {
if (params.debug) {
process.env.LOG_LEVEL = 'verbose';
} else {
process.env.LOG_LEVEL = 'info';
}
// 设置 log 的等级
log.level = process.env.LOG_LEVEL;
log.verbose('test debug');
});
// 监听未注册的所有命令
program.on('command:*', (obj) => {
const commands = program.commands.map((cmd) => cmd.name());
log.info(colors.red('未知的命令 ' + obj[0]));
if (commands.length > 0) {
log.info(colors.blue('支持的命令 ' + commands.join(',')));
}
});
//解析参数
program.parse(process.argv);
// 判断是否输入命令 显示帮助文档
if (program.args && program.args.length < 1) {
program.outputHelp();
console.log();
}
}
新建一个包,把 init
命令的业务代码抽离处理,方便后续维护。
lerna create @hzw-cli-dev/init
// command\init\lib\index.js
function init(projectName, cmdObj) {
console.log('init', projectName, cmdObj);
}
module.exports = init;
当前脚手架架构如下图
这样的架构设计已经可以满足一般的脚手架需求,但是有以下的问题
package
都集成在 cli
里,因此当命令较多时,会减慢脚手架的安装速度。init
命令只能使用 @hzw-cli-dev/init
包,对于大公司而言,每个团队的 init
命令可能都各不相同,可能需要 init
命令动态化,如:@hzw-cli-dev/init-a
作为初始化模块@hzw-cli-dev/init-b
作为初始化模块@hzw-cli-dev/init-c
作为初始化模块 这个时候对我们的架构设计提出了挑战,要求我们能够动态加载 init
模块,这将增加架构的复杂度,但大大提升脚手架的可扩展性,将脚手架框架和业务逻辑解耦。
当前脚手架执行流程如下图
优化后流程图如下