Node.js 知识体系(七): 开发脚手架流程与 yargs 框架解析本篇文章深入解析了如何开发前端脚手架,介绍了开发
本篇文章深入解析了如何开发前端脚手架,介绍了开发流程和关键步骤,并结合 yargs 框架,帮助读者理解如何通过命令行工具实现更灵活、更高效的项目开发。
脚手架 CLI 项目的创建与调试流程
作为前端开发者,你可能已经习惯使用各种脚手架工具,比如 Vue CLI、Create React App 等。但有时候,你可能想要一些更符合自己项目需
求的定制化工具。今天,我们就来一起搭建一个属于自己的前端脚手架工具,并且让它在任何终端都能使用!
第一步:创建项目目录并初始化
首先,老规矩,创建一个工程目录并初始化项目。
- 在终端里,创建一个新目录,比如 colion-cli,然后进入这个目录:
mkdir colion-cli
cd colion-cli
- 使用 pnpm init 或者 npm init 初始化项目:
pnpm init
这一步会生成一个 package.json 文件,里面包含了项目的基本信息。
第二步:创建可执行文件
接下来,咱们需要让脚手架能“说话”,也就是实现它的执行逻辑。为此,你需要创建一个 bin 目录,并且在里面放一个 index.js 文件。
- 创建 bin 目录:
mkdir bin
- 在 bin 目录下,创建 index.js 文件,并且写入以下内容:
#!/usr/bin/env node
console.log("my cli");
注意:第一行的 #!/usr/bin/env node 很关键,这是为了告诉系统,我们的这个文件是通过 node 运行的脚本程序。没有它,你的脚本可能无法正确执行。
- 保存后,确保文件具有可执行权限:
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 这个文件。
第四步: 测试脚手架工具
现在让我们测试一下这个脚手架能不能用了。
- 在项目的根目录下执行以下命令,安装我们刚刚定义的 CLI 工具:
pnpm install
- 然后执行 colion 命令:
colion
如果你看到 my cli 打印在终端中,恭喜你,你的脚手架工具已经可以在项目中使用了!
第五步:让脚手架在全局可用
虽然在项目中可以跑这个脚手架了,但我们还想要在任何地方都能执行 colion 命令,比如在终端中不管在哪个目录下都能用。这怎么实现呢?接下来,我们会利用软链接(symbolic link)来解决这个问题。
- 首先,找到你系统的 node 命令所在位置:
which node
这条命令会返回 node 的安装路径,比如 /usr/local/bin/node。
- 进入 node 安装路径所在的 bin 目录
cd /usr/local/bin
- 使用 ln -s 命令创建一个软链接,把你脚手架的 index.js 文件链接到全局 bin 目录下。命令的格式是:
ln -s {脚手架项目的绝对路径}/bin/index.js colion
比如:
ln -s /Users/username/colion-cli/bin/index.js colion
- 完成后,你可以在任何地方执行 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;
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