什么是 Yargs

Yargs 是一个很好的命令行程序库,简单地说,它可以让创建一个在控制台中运行的应用程序的过程变得轻而易举。还有什么能让它变得更好呢?它是以海盗为主题的(它的名字叫 YARgs),让它正式成为有史以来最好的工具。
你可能知道其他的 CLI,比如 vue-cli,可以轻松设置一个 Vue.js 项目或 create-react-app,所以这个概念对大多数人来说应该很熟悉。
开始
mkdir yargs_practice
cd yargs_practice
touch yargs.js
初始化项目, 并安装 yargs
npm init -y
npm i yargs
package.json
如下所示:
{
"name": "yargs_practice",
"version": "1.0.0",
"description": "",
"main": "yargs.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"yargs": "^15.3.1"
}
}
使用 vscode 打开当前目录
code .
编辑 yargs.js
const yargs = require("yargs");
const argv = yargs.argv;
console.log(argv);
在终端中运行
node yargs.js add --new thing --old="stuff"
得到如下结果

yard 可以很方便的拿到命令行参数
继续修改 yargs.js
const yargs = require("yargs");
const argv = yargs
.command("add", "Add a new note")
.command("list", "List all notes")
.help().argv;
command
可以增加命令行信息help
方法可以显示帮助信息
在终端中运行
node yargs.js --help
显示如下信息

yargs
提供了快捷命令方法(alias)让一些命令更简洁
继续修改 yargs.js
const yargs = require("yargs");
const argv = yargs
.command("add", "Add a new note")
.command("list", "List all notes")
.help()
.alias("help", "h").argv;
在终端中运行
node yargs.js -h
会得到和--help
一样的结果
TODO:: option 没看明白
const yargs = require("yargs");
const argv = yargs
.command("add", "Add a new note")
.command("list", "List all notes")
.help()
.alias("help", "h").argv;

yargs
还支持子命令 用法如下
const yargs = require("yargs");
const argv = yargs
.command("add", "Add a new note", {
title: {
describe: "Title of note",
alias: "t",
demandOption: true,
},
body: {
describe: "Body of note",
alias: "b",
demandOption: true,
},
})
.command("list", "List all notes")
.help()
.option("find")
.alias("help", "h").argv;
在 add
这个命令增加了子命令 title
describe
是这条命令的描述alias
是这条命令的简写demandOption
表示title
必须传递参数
当我们在终端中执行
node yargs.js add -h

注意这里有别于 node yargs.js -h
这里展示的是 add
这条命令的具体帮助信息
实例
我们通过一个小的实例来看 yargs 如何使用
我们需要对这个package.json
文件做一些调整,因为我们要创建一个 CLI。现在看起来应该是这样的。
{
"name": "yargs_practice",
"version": "1.0.0",
"description": "",
"main": "yargs.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"bin": {
"line-count": "./line-count"
},
"keywords": ["cli"],
"preferGlobal": true,
"author": "",
"license": "ISC",
"dependencies": {
"yargs": "^15.3.1"
}
}
以下是需要注意的重要改动。
我们添加了一个 bin 值,它将我们稍后创建的条目文件映射到它的可执行文件名上(你可以设置为任何你想要的名字 我们已经将 preferGlobal 设置为 true,这意味着我们的软件包希望被全局安装(例如通过 npm install -g)。 其他的调整包括改变描述、删除已使用的脚本、添加作者名称等。
创建一个基本的 CLI
Yargs 让解析命令行参数变得非常简单,很多例子项目可以在这里找到。
我们将创建一个基本的 CLI,它可以接收一个文件作为参数并计算它的行数。
要做到这一点,首先创建一个主脚本文件。
touch line-count
编辑这个文件
#!/usr/bin/env node
const argv = require("yargs")
.usage("Usage: $0 <command> [options]")
.help("h")
.alias("h", "help").argv;
让我们把所有的代码逐条逐句的说说。
#!/usr/bin/env node
是一个 shebang 行的实例,它告诉我们的系统用什么解释器来执行该文件.usage('Usage: $0 <command> [options]')
设置当调用 --help 命令时将显示的 CLI 的用法信息。.help('h')
将帮助命令绑定到选项h
上。.alias('h', 'help')
为选项-h
创建了一个别名,即--help
。
与你所见,这第一步是非常简单的,yargs 的语法很直观。
接下来我们要添加count
命令。
只需在你已有的 CLI 中添加以下几行。
.command("count", "Count the lines in a file")
.example("$0 count -f foo.js",
"count the lines in the given file")
逐行看看:
-
.command("count", "count the lines in a file")
创建了一个新的命令,名称为 count,并设置了一个描述。 -
.example("$0 count -f foo.js", "count the lines in the given file")
创建一个带有描述的例子,当用户调用 --help 选项或者当他们忘记这个命令时,它将显示出来。
这些都很好,但现在运行node line-count
计数并没有什么作用,接下来我们需要一个文件名,通过计数并显示其行数来完成 CLI。
添加如下信息
.alias("f", "file")
.nargs("f", 1)
.describe("f", "Load a file")
.demandOption(["f"])
line-count
最后应该是这样的样子。
#!/usr/bin/env node
const argv = require("yargs")
.usage("Usage: $0 <command> [options]")
.command("count", "Count the lines in a file")
.example("$0 count -f foo.js", "count the lines in the given file")
.alias("f", "file")
.nargs("f", 1)
.describe("f", "Load a file")
.demandOption(["f"])
.help("h")
.alias("h", "help").argv;
逐行,解释下新添加的代码
-
.alias("f", "file")
为-f 选项创建别名 --file。 -
.nargs("f", 1)
为该选项设置一个参数(文件名),否则显示 --help 菜单。 -
.description("f", "Load a file")
为该选项添加一个描述。 -
.demandOption([["f"])
,因为我们需要一个文件名,所以我们要求选项-f。
最后,让我们把程序的逻辑加上。
// Create stream with the file
const s = fs.createReadStream(argv.file);
var lines = 0;
s.on("data", (buf) => {
// Get the number of lines
lines += buf.toString().match(/\n/g).length;
});
s.on("end", () => {
// Display the number of lines
console.log(lines);
});
就这样,我们来试试。

到现在为止,我们的程序一直是这样运行的,但如果直接调用它,就会报错。

我们可以通过使用 npm link
命令将二进制文件(我们之前在 package.json 中定义为 bin)进行全局注册来解决这个问题。
在当前目录下执行
npm link
恭喜 🎉,你现在可以像这样在本地运行你的脚本了。
line-count count -f package.json

发布 CLI 到 NPM
在部署之前,我们需要在 package.json
中添加一些信息。
"homepage": "YOUR GITHUB REPO OR SITE HERE",
"repository": {
"type": "git",
"url": "git+YOUR GITHUB REPOSITORY HERE"
},
"engines": {
"node": ">=8"
},
- homepage 和 repository 要填写你自己的 GitHub 项目地址
- engines 确认
nodejs
版本号,简单地定义了你的项目应该在最小版本的节点上工作。 版本号取决于你用了那些版本的特性。
下面是接下来的步骤。
- 在
npmjs.com
上创建一个账户(可选,如果有可以忽略) - 运行
npm login
命令并输入你的信息 - 运行
npm publish
命令,它将在几分钟内自动发布。
就是这样! 如果你想在将来更新你的项目,你需要在 package.json
文件中修改它的版本号,然后再次运行发布命令。