构建命令行工具
视频描述 跳转到标题
学习如何使用 Deno 标准库构建命令行工具。你将探索如何使用实用函数解析参数、处理标志并提供有用的消息。跟随我们构建一个滑雪场信息应用,优雅地处理错误,并将脚本编译成可在多个平台(包括 Windows、MacOS 和 Linux)上运行的可执行文件。观看完本视频后,你将了解如何充分利用 Deno 的功能来开发和分发你自己的 CLI 工具。
文本和代码 跳转到标题
Deno 标准库介绍 跳转到标题
如果你想创建一个命令行工具,可以使用 Deno 的标准库。它包含数十个稳定的库,提供有用的实用函数,可以涵盖在 Web 中使用 JavaScript 时的许多基本操作。该标准库还可以在多种运行时和环境中工作,例如 Node.js 和浏览器。
设置命令行工具 跳转到标题
我们将创建一个命令行工具,然后将其编译成可在多个不同平台上用作可执行文件的形式。
创建一个名为 main.ts
的新文件并解析这些参数(请记住,我们总是可以从 Deno.args
中获取它们),然后我们将它们输出到控制台。
const location = Deno.args[0];
console.log(`Welcome to ${location}`);
现在,如果我运行 deno main.ts
,然后提供一个滑雪场名称,比如 Aspen,它就会将该名称插入到字符串中,例如:
deno main.ts Aspen
## Welcome to Aspen
安装和使用标准库 跳转到标题
现在让我们安装其中一个标准库。在终端中运行:
deno add jsr:@std/cli
这将把 Deno 标准库中的 cli
库安装到我们的项目中,以便我们可以利用它的一些实用函数。
我们将在这里使用的实用函数叫做 parseArgs
。我们可以这样导入它:
import { parseArgs } from "jsr:@std/cli/parse-args";
然后我们可以更新代码以使用此函数,传递参数并移除零。我们的 main.ts
文件现在看起来像这样:
import { parseArgs } from "jsr:@std/cli/parse-args";
const args = parseArgs(Deno.args);
console.log(args);
让我们来试一下,在你的终端中运行:
deno main.ts -h Hello
我们可以看到 Hello
已添加到我们的 args 对象中。好的,这按预期工作。
构建滑雪场信息应用 跳转到标题
现在我们的应用将是一个滑雪场信息应用,所以我们希望先用一些数据来填充它。我们将创建一个名为 resorts
的值。这是一个包含几个不同键的对象,所以我们将设置 elevation
(海拔)、snow
(雪况)和 expectedSnowfall
(预期降雪)。然后我们直接复制粘贴这些,以便更快地进行操作。我们将 Aspen
的海拔设置为 7945
,雪况设置为 packed powder
(压实粉雪),预期降雪量为 15
。然后我们再添加一个,将 Vail
的海拔设置为 8120
,然后我们将预期降雪量设置为 25
。
const resorts = {
Whistler: {
elevation: 2214,
snow: "Powder",
expectedSnowfall: "20",
},
Aspen: {
elevation: 7945,
snow: "packed powder",
expectedSnowfall: 15,
},
Vail: {
elevation: 8120,
snow: "packed powder",
expectedSnowfall: 25,
},
};
我们这里有几个不同的滑雪场。最终,我们希望能够通过命令行参数运行我们的应用,提供滑雪场名称,然后让 CLI 工具返回该滑雪场的信息。
处理命令行参数 跳转到标题
那么,让我们继续向 parse args 传入另一个对象。在这里,我们将定义一个别名——所以我们会说“如果我传入 r
标志,我们希望它被认为是 resort
”。然后我们再使用默认值,我们将 default
resort
设置为 Whistler
。
const args = parseArgs(Deno.args, {
alias: {
resort: "r",
},
default: {
resort: "Whistler",
},
});
从这里开始,我们可以设置一个名为 resortName
的常量并将其设置为 args.resort
。然后获取滑雪场信息,使用 resorts[resortName]
(我们稍后会修复那个类型错误),并更新控制台输出:
const resortName = args.resort;
const resort = resorts[resortName];
console.log(
`Resort: ${resortName} Elevation: ${resort.elevation} feet Snow: ${resort.snow} Expected Snowfall: ${resort.expectedSnowfall}`,
);
为了测试它,我们可以使用:
deno main.ts -r Aspen
这将打印出 Aspen 的所有详细信息。
我们也可以不带任何参数运行,这应该会显示 Whistler 的详细信息,因为它被设置为默认值。
deno main.ts
我们的全名也是如此,所以我们可以这样说:
deno main.ts --resort Veil
这也应该提供那些详细信息。
改进错误处理 跳转到标题
现在,如果我尝试用一个不存在的滑雪场运行它,比如说 Bachelor
;会出现一个错误,这有点难看。它在尝试解析时遇到了无法找到的时刻。所以我们可以通过以下方式让它变得更好:如果我们的数据集中没有匹配输入的 resort
,我们就输出一个控制台错误信息,说“未找到滑雪场名称,请尝试 Whistler、Aspen 或 Vail”,然后我们使用 Deno.exit
退出该进程。
if (!resort) {
console.error(
`Resort ${resortName} name not found. Try Whistler, Aspen, or Veil`,
);
Deno.exit(1);
}
修复类型错误 跳转到标题
好的,这里看起来不太好,我们可以在 TypeScript 中查看这里的问题——它告诉我们这隐式地具有 any
类型,你可以查找更多关于这个错误的信息,但我会告诉你如何修复它。将 resortName
的类型更新为 resorts
的一个键。
const resortName = args.resort as keyof typeof resorts;
这样做是提取了 args.resort
的值,并断言数据中存在一个有效的键。
添加帮助和颜色输出 跳转到标题
让我们再进一步,我们将说如果 args.help
为真,我们将输出到控制台,然后给我们的用户一个简短的消息,告诉他们“嘿,这才是它的实际用法”,以防他们随时需要帮助,我们还会将这里的别名更新为 help
是 H
,最后我们会确保调用 Deno.exit
,以便我们一完成就退出进程。
const args = parseArgs(Deno.args, {
alias: {
resort: "r",
help: "h",
},
default: {
resort: "Whistler",
},
});
...
if (args.help) {
console.log(`
usage: ski-cli --resort <resort name>
-h, --help Show Help
-r, --resort Name of the ski resort (default: Whistler)
`);
Deno.exit();
}
你可以通过运行以下命令来测试你的帮助设置:
deno main.ts -h
接下来,让我们用颜色输出结果。Deno 支持使用 %C
语法来实现 CSS。
这将获取文本,并应用我们作为第二个参数传递给 console.log()
的样式。例如,这里我们可以将 color:blue
设置为第二个参数:
console.log(`
%c
Resort: ${resortName}
Elevation: ${resort.elevation} feet
Snow: ${resort.snow}
Expected Snowfall: ${resort.expectedSnowfall}
`, "color:blue"
);
Then run the program again:
```sh
deno main.ts -r Veil
你 E应该会看到所有内容都以蓝色显示。是不是很酷?!
为不同平台编译工具 跳转到标题
我也希望其他人能够享受这个应用。使用 Deno 将此工具编译成可执行文件非常容易。正如你可能想象的,运行此命令是 deno compile
,然后是我们的脚本名称。这将把代码编译为项目中的一个可执行文件。
deno compile main.ts
你 E应该会在项目文件夹中看到名为 MyDenoProject
的可执行文件。现在你可以使用 ./
将其作为可执行文件运行,例如:
./MyDenoProject --resort Aspen
所以这对我来说非常棒,但如果我想将它分享到其他平台怎么办?你所需要做的就是再次运行 deno compile
,这次传入一个 --target
标志来指定你想要编译到的目标平台。
假设我们想为 Windows 编译,我们会使用:
deno compile --target x86_64-pc-windows-msvc --output ski-cli-windows main.ts
或为 Mac:
deno compile --target x86_64-apple-darwin --output ski-cli-macos main.ts
或为 Linux:
deno compile --target x86_64-unknown-linux-gnu --output ski-cli-linux main.ts
你可以在 Deno 文档中查看所有用于编译应用的选项。有许多不同的标志可以根据你自己的特定用例使用。
回顾一下,我们始终可以使用 Deno 标准库,它提供了许多有用的函数。如果我们要创建一个命令行工具,就像我们在这里所做的,我们总是可以通过 Deno
全局命名空间访问这些参数。我们可以使用标准库 CLI 包中的 parseArgs
函数来解析参数,并且可以为所有平台运行编译,这样我们的应用就可以在任何地方使用。