likes
comments
collection
share

Node.js 知识体系(七): 开发脚手架流程与 yargs 框架解析本篇文章深入解析了如何开发前端脚手架,介绍了开发

作者站长头像
站长
· 阅读数 25

本篇文章深入解析了如何开发前端脚手架,介绍了开发流程和关键步骤,并结合 yargs 框架,帮助读者理解如何通过命令行工具实现更灵活、更高效的项目开发。

脚手架 CLI 项目的创建与调试流程

作为前端开发者,你可能已经习惯使用各种脚手架工具,比如 Vue CLI、Create React App 等。但有时候,你可能想要一些更符合自己项目需求的定制化工具。今天,我们就来一起搭建一个属于自己的前端脚手架工具,并且让它在任何终端都能使用!

Node.js 知识体系(七): 开发脚手架流程与 yargs 框架解析本篇文章深入解析了如何开发前端脚手架,介绍了开发

第一步:创建项目目录并初始化

首先,老规矩,创建一个工程目录并初始化项目。

  1. 在终端里,创建一个新目录,比如 colion-cli,然后进入这个目录:
mkdir colion-cli
cd colion-cli
  1. 使用 pnpm init 或者 npm init 初始化项目:
pnpm init

这一步会生成一个 package.json 文件,里面包含了项目的基本信息。

第二步:创建可执行文件

接下来,咱们需要让脚手架能“说话”,也就是实现它的执行逻辑。为此,你需要创建一个 bin 目录,并且在里面放一个 index.js 文件。

  1. 创建 bin 目录:
mkdir bin
  1. 在 bin 目录下,创建 index.js 文件,并且写入以下内容:
#!/usr/bin/env node

console.log("my cli");

注意:第一行的 #!/usr/bin/env node 很关键,这是为了告诉系统,我们的这个文件是通过 node 运行的脚本程序。没有它,你的脚本可能无法正确执行。

  1. 保存后,确保文件具有可执行权限:
chmod +x bin/index.js

第三步:配置 package.json

到这里,我们的脚手架还无法通过命令来执行。要实现这个功能,你需要在 package.json 中配置 bin 字段,让 npm 知道我们在执行 colion 命令时应该运行哪个文件。

打开 package.json,找到一个合适的位置,添加以下配置:

{
  "name": "@colion/cli",
  "version": "1.0.0",
  "bin": {
    "colion": "./bin/index.js"
  }
}
  • "name": "@colion/cli":这里命名了我们的包名为 @colion/cli。
  • "bin":这是关键部分。我们告诉 npm,当执行 colion 命令时,实际上是去运行 ./bin/index.js 这个文件。

第四步: 测试脚手架工具

现在让我们测试一下这个脚手架能不能用了。

  1. 在项目的根目录下执行以下命令,安装我们刚刚定义的 CLI 工具:
pnpm install
  1. 然后执行 colion 命令:
colion

如果你看到 my cli 打印在终端中,恭喜你,你的脚手架工具已经可以在项目中使用了!

Node.js 知识体系(七): 开发脚手架流程与 yargs 框架解析本篇文章深入解析了如何开发前端脚手架,介绍了开发

第五步:让脚手架在全局可用

虽然在项目中可以跑这个脚手架了,但我们还想要在任何地方都能执行 colion 命令,比如在终端中不管在哪个目录下都能用。这怎么实现呢?接下来,我们会利用软链接(symbolic link)来解决这个问题。

  1. 首先,找到你系统的 node 命令所在位置:
which node

这条命令会返回 node 的安装路径,比如 /usr/local/bin/node。

  1. 进入 node 安装路径所在的 bin 目录
cd /usr/local/bin
  1. 使用 ln -s 命令创建一个软链接,把你脚手架的 index.js 文件链接到全局 bin 目录下。命令的格式是:
ln -s {脚手架项目的绝对路径}/bin/index.js colion

比如:

ln -s /Users/username/colion-cli/bin/index.js colion
  1. 完成后,你可以在任何地方执行 colion 命令了。试试看:
colion

最后一步:进一步扩展脚手架工具

到这里,我们已经有了一个最简单的脚手架工具,它能够在全局使用并且执行一个命令。虽然现在的功能只是简单的 console.log("my cli"),但接下来你可以根据自己的项目需求,往脚手架中加入更多实用功能,比如自动化配置、文件生成等。

脚手架命令注册和参数解析

  • 目标1: 注册一个命令 colion init
  • 目标2: 实现参数解析 --version 和 init --name

命令行参数解析:实现 CLI 命令与参数功能

 #!/usr/bin/env node
console.log('Welcome to the Colion/CLI!');

// 注册一个命令 colion init
console.log(process.argv);
// 实现参数解析 --version 和 init --name

process.argv 打印的数组包含当前 Node.js 进程的启动参数。

第一个参数是 Node.js 可执行文件的路径,

第二个参数是当前执行的脚本文件路径,

第三个及之后的参数是用户在命令行中输入的实际命令或参数(如 init)。这些参数可以用于脚本中处理不同的命令和选项。

 #!/usr/bin/env node
// 引入 chalk 模块, 使用 v4 版本, 再高版本是 esmodule 的, 不支持 commonjs
const chalk = require('chalk');
// 引入 utils 模块
const { Command } = require('@colion/utils');
console.log('Welcome to the Colion/CLI!');

// 注册一个命令 colion init
const argv = process.argv;
const command = argv[2];
if (command) {
  if (Command[command]) {
    Command[command]();
  } else {
    console.log(chalk.red('无效的命令'));
  }
} else {
  console.log(chalk.red('请输入命令'));
}

// 实现参数解析 --version 和 init --name

在这段代码中,我们使用了 chalk 模块美化终端输出,同时通过 process.argv 解析命令行参数,实现了一个简单的 CLI 命令注册功能。当用户输入命令时,程序会根据输入的命令进行相应的执行。如果输入无效的命令,则会输出红色提示信息。此外,还为后续解析 --version 和 init --name 参数功能做好了基础准备。

支持参数

🍀 cli $ colion init --name vue-test
Welcome to the Colion/CLI!
[  '/Users/user/.volta/tools/image/node/18.16.0/bin/node',  '/Users/user/apps/colion/node_modules/@colion/cli/bin/index.js',  'init',  '--name',  'vue-test']
Colion CLI 执行init流程

基础版参数解析实现

解析单个参数

 // 获取命令行参数列表  const argv = process. argv ; console . log (argv); // 打印所有的命令行参数   // 获取命令,通常是第 3 个参数(因为前两个是 node 路径和脚本路径)  const command = argv[ 2 ];  // 获取命令行参数中除命令以外的选项部分,从第 4 个参数开始  const options = argv. slice ( 3 ); console . log (options); // 打印所有的选项部分   // 解构获取第一个选项(例如 --name)和它的参数(例如 "value")  let [option, param] = options;  // 去掉选项前的横杠,允许单个或多个“-”号(如 -v 或 --version)  option = option. replace ( /^-+/ , '' );  // 打印解析后的选项和参数  console . log (option, param); 

执行命令

🍀 cli $ colion init --name vue-test
Welcome to the Colion/CLI!
[  '/Users/user/.volta/tools/image/node/18.16.0/bin/node',  '/Users/user/apps/colion/node_modules/@colion/cli/bin/index.js',  'init',  '--name',  'vue-test']
[ '--name', 'vue-test' ]
name vue-test
Colion CLI 执行init流程
解析一系列参数该怎么办呢?

解析一系列参数时,手动处理会涉及大量代码,因此推荐使用专门的库来简化这个过程。在后续的文章中,我们将详细介绍如何使用这些库来高效处理命令行参数。

全局参数处理机制:解析 –version

在解析命令时,--version 属于全局参数,需要单独处理。通过检测命令是否以 -- 或 - 开头,我们可以将其识别为全局参数,并相应地进行处理。例如,当检测到 --version 或 -V 时,动态输出 CLI 的版本号。此外,其他命令如 create 仍会正常执行。

if (options.length > 1) {
// 执行 create 等命令
}
// 实现参数解析 --version 和 init --name
if (command.startsWith('--') || command.startsWith('-')) {
  const globalOptions = command.replace(/--|-/g, '');
  console.log(globalOptions);
  if (globalOptions === 'version' || globalOptions === 'V') {
console.log(chalk.green('Colion CLI 版本号: 1.0.0'));
  }
}

脚手架框架 yargs

Yargs 是一个用于简化 Node.js 命令行参数解析的工具,帮助开发者轻松构建命令行应用程序。

最基本的 yargs 框架使用

#!/usr/bin/env node
// 引入 yargs 库和辅助函数 hideBin,用于处理命令行参数
const yargs = require('yargs/yargs');
const { hideBin } = require('yargs/helpers');

// 使用 hideBin 过滤掉 process.argv 中的前两个参数 (Node.js 可执行文件路径和脚本路径)
// 返回的数组 `arg` 是实际的命令行参数, 例如 colion --help 返回[ '--help' ]
const arg = hideBin(process.argv);

// 初始化 yargs 并传入命令行参数进行解析
// `.argv` 使 yargs 解析参数并生成一个包含解析结果的对象
yargs(arg).argv;

Node.js 知识体系(七): 开发脚手架流程与 yargs 框架解析本篇文章深入解析了如何开发前端脚手架,介绍了开发

yargs 框架的常用方法

在构建命令行工具时,Yargs 是一个非常强大的框架,它可以帮助我们轻松解析命令行参数。下面我们通过一些常见的用法来了解如何使用 Yargs。

const yargs = require('yargs/yargs');
const { hideBin } = require('yargs/helpers');
const arg = hideBin(process.argv);
yargs(arg).argv;

这段代码是 Yargs 的基本起手式,通过 hideBin(process.argv) 过滤掉命令行参数中的执行文件路径,然后通过 yargs() 对参数进行解析。然后通过链式调用来配置 yargs

常用配置项介绍

yargs.usage()

用于设置 CLI 工具的使用说明。你可以通过 yargs.usage('Usage: $0 [options]') 来定义提示信息。

yargs.demandCommand()

强制要求至少输入一个命令,否则会报错。比如 yargs.demandCommand(1, '必须输入一个命令!')。

yargs.strict()

启用严格模式,防止用户输入未定义的命令或参数时工具崩溃。可以通过 yargs.strict() 开启。

yargs.alias()

为命令或参数提供别名,简化输入。比如 yargs.alias('v', 'version'),让用户可以使用 -v 来代替 --version。

yargs.wrap()

设置输出信息的宽度限制,使长信息自动换行。yargs.wrap(80) 设置最大宽度为 80 字符。

yargs.epilogue()

添加 CLI 的补充说明或结尾信息。比如 yargs.epilogue('更多信息请访问 google.com')。

yargs.options()

自定义命令行参数选项。你可以通过 yargs.options({ name: { alias: 'n', describe: 'your name', type: 'string' } }) 来定义命令行参数。

yargs.group()

将多个参数分组显示,方便分类展示。比如 yargs.group(['name', 'age'], 'User Info')。

定义命令

yargs.command()

定义一个命令及其处理逻辑。比如:

yargs.command('init', '初始化项目', () => {}, (argv) => {
    console.log('正在初始化项目...');
});

推荐命令 (yargs.recommendCommands())

当用户输入错误的命令时,Yargs 会推荐最接近的正确命令。

通过这些配置项和功能,你可以快速创建一个功能强大、用户友好的命令行工具。Yargs 的灵活性和强大的解析能力能够满足大部分 CLI 项目的需求。

打造一个基础的 Yargs CLI 脚手架

我们定义了常见的命令行参数处理方式,提供了全局参数、命令别名、分组选项等功能,同时还处理了命令执行失败时的错误信息。该脚手架具备良好的扩展性,可以根据项目需求进一步定制。

#!/usr/bin/env node

const chalk = require('chalk');
// 引入 yargs 库和辅助函数 hideBin,用于处理命令行参数
const yargs = require('yargs/yargs');
const { hideBin } = require('yargs/helpers');
const dedent = require('dedent'); // dedent 解决多行字符串缩进问题, 去除多余空格

// 使用 hideBin 过滤掉 process.argv 中的前两个参数 (Node.js 可执行文件路径和脚本路径)
const arg = hideBin(process.argv);

// 初始化 yargs 并传入命令行参数进行解析
yargs(arg)
  .usage('Usage: colion [command] <options>')  // 用法说明
  .demandCommand(1, 'A command is required. Pass --help to see all available commands and options.') // 至少一个命令
  .strict()  // 严格模式,防止未定义的命令
  .recommendCommands()  // 推荐相近命令
  .alias('h', 'help')  // 帮助别名
  .alias('v', 'version')  // 版本别名
  .wrap(120)  // 设置行宽,超出后自动换行
  .epilogue(dedent`For more information, you can visit URL_ADDRESS`)  // 结尾提示
  .options({
    debug: {
      type: 'boolean',
      description: 'Run in debug mode',  // 运行调试模式
      alias: 'd',
      default: true,  // 默认值
    },
    ci: {
      type: 'boolean',
      hidden: true,  // 隐藏选项,内部使用
    },
    registry: {
      type: 'string',
      description: 'Specify the registry to use',  // 指定 registry
      alias: 'r',
    },
  })  // 增加全局选项
  .group(['debug'], 'Dev Options')  // 将 debug 分组到开发选项
  .group(['registry'], 'Prod Options')  // 将 registry 分组到生产选项
  .command('init [name]', 'Initialize a project', (yargs) => {
    yargs.options('name', {
      type: 'string',
      description: 'Specify the project name',  // 指定项目名称
      alias: 'n',
    });
  }, (argv) => {
    // 解析参数后的逻辑
    console.log(argv);
    console.log(`Project name: ${argv.name}`);
  })
  .command({
    command: 'list',
    aliases: ['ls', 'la', 'll'],  // 命令别名
    description: 'List all available commands',  // 列出所有可用命令
    builder: (yargs) => {},  // 构建命令时的处理逻辑
    handler: (argv) => {
      console.log('List all available commands');
      console.log(argv);
    },
  })  // 定义命令的第二种方式
  .fail((err, msg) => {
    console.log(`Error: `, chalk.red(err));  // 打印错误信息
    console.log(`Error Msg: `, chalk.red(msg));  // 错误信息提示
  })
  .argv;  // 解析命令行参数并执行命令

主要功能点:

  • 全局参数:如 --help 和 --version 别名。
  • 命令解析:支持 init 和 list 命令,并提供额外的选项如 --name。
  • 命令分组:根据使用场景将选项分为开发选项和生产选项。
  • 错误处理:当输入的命令错误时,会打印出红色的错误提示。

结语

通过这篇文章,读者能够掌握前端脚手架的开发流程,理解 yargs 框架在处理命令行输入中的应用。脚手架不仅提升了项目的开发效率,还为团队协作提供了标准化工具。

转载自:https://juejin.cn/post/7415967952268083212
评论
请登录