大家好,我是程序员柏风,AI 最全的 Vibecoding 学习地图 http://coderoadmap.cn 作者。
命令行应用
Node 擅长 一次性脚本与内部 CLI:读参数、处理 stdin、写 stdout/stderr、返回退出码。本课对应 roadmap command-line-apps——在 node-runtime 的 process 基础上做完整工具。
学习目标
- 解析 argv 与子命令结构
- 处理 stdin/stdout 管道
- 包装 async main 与错误退出(衔接 nva-errors)
参数解析
轻量:手写 process.argv 或使用 Node 20+ 内置 parseArgs:
import { parseArgs } from "node:util";
const { values, positionals } = parseArgs({
options: {
dryRun: { type: "boolean", short: "n" },
file: { type: "string", short: "f" },
},
allowPositionals: true,
});
复杂子命令(import run、import validate)可引入 commander 或 yargs——nva-practice 会用到。
stdin / stdout 管道
import { createInterface } from "node:readline";
const rl = createInterface({ input: process.stdin });
for await (const line of rl) {
process.stdout.write(line.toUpperCase() + "\n");
}
Unix 哲学:CLI 只做一件事,用管道组合——例如 cat ids.txt | my-import --dry-run。
标准流与日志
| 流 | 用途 |
|---|---|
| stdout | 正常输出(可被管道消费) |
| stderr | 日志、警告、错误 message |
| exit code | CI 判断成败 |
用户-facing 进度条写 stderr,结构化结果写 stdout,便于 my-tool > out.json。
main 包装模板
export async function main(argv = process.argv.slice(2)) {
// ...
}
if (import.meta.url === `file://${process.argv[1]}`) {
main().catch((err) => {
console.error(err.message);
process.exitCode = 1;
});
}
可测试:测试里 main(['--file', 'x.json']) 不断言 process.exit(见 test-intro 单元测试分层)。
与 Spring Boot 对照
| Node CLI | Spring Boot | |
|---|---|---|
| 启动 | 毫秒级进程 | JVM + 容器 |
| 适用 | 批处理、迁移、生成 | 长驻 API |
| 配置 | env、flag | application.yml |
数据导入脚本常用 Node CLI + postgresql-essentials 驱动,API 仍走 Nest。
练习
- 实现
echo-lines:读 stdin 行数并 stderr 打印计数 -
--help输出用法(哪怕手写字符串) - 为 main 写一个不 spawn 进程的单元测试
小结
argv 解析、stdin 管道、stdout 结构化、stderr 说人话。 下一课 Inquirer 与 prompts 做交互式输入。