想想你的团队会有一些重复性工做吗?思考一下,CLI 工具也许能够减小掉许多重复工做,统一合做规范,提高工做效率。node
Node 拥有最为庞大的生态社区,数十万的 Package,其中有许多 Package 是专门为建强大的 CLI 工具打造的。在社区生态的帮助下,你能够更快速构建更强大的 CLI 工具。同时,在 NPM、Yarn 等 Package 管理工具的帮助下,你也能够快速的分发的你的 CLI 工具,让你的用户更简单的使用你的 CLI 工具。git
初始化项目github
mkdir cli-tool && cd cli-tool
npm init --yes
复制代码
建立 src/cli.js
,写入以下内容:npm
// src/cli.js
module.exports = function cli() {
// 打印命令参数
console.log(process.argv);
};
复制代码
建立 bin/cli.js
文件,这是 CLI 工具的入口文件,写入以下内容:json
#!/usr/bin/env node
const cli = require("../src/cli");
cli();
复制代码
重点:修改 package.json
,写入 bin
字段,添加 cli
命令数组
{
"name": "cli-tool",
"version": "1.0.0",
"description": "",
"main": "src/cli.js",
"bin": {
"cli": "bin/cli.js"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
复制代码
在项目根目录下,运行:bash
npm link
复制代码
在终端中输入 cli
命令,便可打印出以下相似内容:app
[
'/Users/xx/.nvm/versions/node/v12.16.2/bin/node',
'/Users/xx/.nvm/versions/node/v12.16.2/bin/cli'
]
复制代码
至此,一个简单的 Node CLI 工具就完成了。工具
NPM 实现了将 Package 中的可执行文件添加全局 PATH 中的能力,当在 package.json
文件中添加 bin
字段时,NPM 会将 bin
声明的文件连接(软连接)到 bin
目录中(全局可用),或者 ./node_modules/bin/
(本地可用)。动画
以下面的 bin
建立 /usr/local/bin/myapp
到 cli.js
的软连接:
{ "bin" : { "myapp" : "./cli.js" } }
复制代码
同时,咱们要在 bin
声明的文件的开头添加 #!/usr/bin/env node
声明,确保系统会用 Node 执行此文件。
npm link
命令会建立当前 Package 到 Gloabl 的软连接,使当前 Package 在全局可用,相似虚拟的 npm i --global packae
命令,在本地调试时十分有用。
CLI 工具的基本能力就是要解析用户输入的 CLI 命令与参数,实现相关功能。Node 的 process.argv
数组包含了 Node
进程被启动时传入的命令行参数,经过解析 process.argv
数组便可,社区中相关的 Package 也比较多,如:yargs,minimist 等。
这里推荐使用 [commander](https://github.com/tj/commander.js)
构建你的 CLI 工具,commander 是一个较为完善的 Node CLI 解决方案,拥有解析输入参数、关联处理逻辑、输出命令提示等功能。只有当 commander 的功能没法知足你的需求时,才建议你尝试本身处理命令参数解析。
在某些状况下,CLI 工具可能须要使用交互式输入,如输入密码时,这种状况不适合直接经过参数输入。简单的输入时,能够直接 Node 的 readline
模块:
const readline = require("readline");
const question = ["请输入您的姓名", "请输入您的年龄"];
const result = [];
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
prompt: `?${question[0]} `,
});
rl.prompt();
rl.on("line", (line) => {
result.push(line.trim());
const max = result.length;
if (max === question.length) {
rl.close();
}
rl.setPrompt(`?${question[max]} `);
rl.prompt();
}).on("close", () => {
console.log(`谢谢参与问答 *** 姓名: ${result[0]} 年龄: ${result[1]}`);
process.exit(0);
});
复制代码
当须要比较复杂的交互时,如列表选择时,就须要使用社区中的 Package 了。这里推荐 enquirer,功能较为强大,以下:
最后,你能够经过 NPM 将你的 Node CLI 工具快速分发出去:
# 登录 npm
npm adduser
# 打 Tag
npm tag v1.0.0
# 发布
npm publish
复制代码