【架构师(第十篇)】脚手架之注册命令及架构优化

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情

脚手架之命令注册和执行过程开发

将收获什么

  • 如何设计一个高性能脚手架
  • Node 多进程开发
  • JavaScript 对面对象的实战技巧
  • Node 多进程原理

主要内容

  • 图解高性能脚手架架构设计方法

  • 封装通用的 CommandPackage

  • 基于缓存 + 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;
复制代码

当前脚手架架构痛点分析

当前脚手架架构如下图

image.png

这样的架构设计已经可以满足一般的脚手架需求,但是有以下的问题

  • 脚手架安装速度慢: 所有 package 都集成在 cli 里,因此当命令较多时,会减慢脚手架的安装速度。
  • 灵活性差: init 命令只能使用 @hzw-cli-dev/init 包,对于大公司而言,每个团队的 init 命令可能都各不相同,可能需要 init 命令动态化,如:
    • A 团队使用 @hzw-cli-dev/init-a 作为初始化模块

    • B 团队使用 @hzw-cli-dev/init-b 作为初始化模块

    • C 团队使用 @hzw-cli-dev/init-c 作为初始化模块

这个时候对我们的架构设计提出了挑战,要求我们能够动态加载 init 模块,这将增加架构的复杂度,但大大提升脚手架的可扩展性,将脚手架框架和业务逻辑解耦。

脚手架架构优化

当前脚手架执行流程如下图

image.png

优化后流程图如下

week4_01.png

脚手架命令动态加载功能架构设计图

123.png

猜你喜欢

转载自juejin.im/post/7083658316131336222