今天学习一下如果开发Node命令行工具(CLI)
目录
准备
没有Node环境的,自行去官网下载安装:下载 | Node.js
安装Node后,自带npm。以下是我的环境:
创建项目
创建项目并切换到项目目录
F:\Chen\Nodejs>mkdir baby && cd baby
初始化项目
npm init 初始化项目,-y或--yes,指定项目走默认配置
F:\Chen\Nodejs\baby>npm init -y
Wrote to F:\Chen\Nodejs\baby\package.json:
{
"name": "baby",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
创建可执行脚本
创建一个bin文件夹,用来存放可执行命令对应的文件
F:\Chen\Nodejs\baby>mkdir bin && cd bin
创建可执行命令文件 baby.js
#!/usr/bin/env node
// baby.js
console.log("There is a new baby.");
#! /usr/bin/env node 首行shebang语句,指定使用node解释程序执行脚本。
在不同的操作系统中,node 命令行的位置不同,因此使用 env node 找到路径并执行
注册命令行命令
使用node命令执行脚本(node [script],script需要指定脚本路径)
F:\Chen\Nodejs\baby\bin>node baby
There is a new baby.
直接使用node命令执行脚本,每次执行脚本都需要指定脚本的具体位置,这显然很不方便。
可以在 package.json 中添加bin字段映射命令关键字与可执行文件,如下:
{
...
"bin": {
"baby": "./bin/baby.js"
},
...
}
在通过npm install -g全局安装的时候,npm会symlink可执行文件到{prefix}文件夹(Windows系统),如果通过npm install本地安装的时候,npm会symlink可执行文件到./node_modules/.bin 文件夹。
但是npm install无论是全局安装还是本地安装,都是指从npm仓库下载并安装,我们开发的模块,并没有发布到npm仓库,如果想要调试或使用本地开发的模块,可以使用 npm link 安装本地模块。
F:\Chen\Nodejs\baby>npm prefix -g
C:\Users\cyinl\AppData\Roaming\npm
F:\Chen\Nodejs\baby>npm link
added 1 package, and audited 3 packages in 3s
found 0 vulnerabilities
F:\Chen\Nodejs\baby>dir C:\Users\cyinl\AppData\Roaming\npm
C:\Users\cyinl\AppData\Roaming\npm 的目录
2023/04/05 10:21 <DIR> .
2023/04/05 10:21 <DIR> ..
2023/04/05 10:21 318 baby
2023/04/05 10:21 330 baby.cmd
2023/04/05 10:21 825 baby.ps1
2023/04/05 10:21 <DIR> node_modules
F:\Chen\Nodejs\baby>dir C:\Users\cyinl\AppData\Roaming\npm\node_modules
C:\Users\cyinl\AppData\Roaming\npm\node_modules 的目录
2023/04/05 10:21 <DIR> .
2023/04/05 10:21 <DIR> ..
2023/04/05 10:21 <JUNCTION> baby [F:\Chen\Nodejs\baby]
在baby根目录下,执行npm link后,会在{prefix}/node_modules/<package>文件夹创建一个symlink链接,示例中是创建一个baby的symlink链接 F:\Chen\Nodejs\baby。同时会为package.json中bin字段指定的可执行文件创建一个可执行命令 存放在{prefix}/{name},示例中是 C:\Users\cyinl\AppData\Roaming\npm 的目录下的baby几个命令。
package.json 模块配置文件,各字段详细解释:package.json
bin 字段的详细用法,详细用法: package-json#bin
npm link 为本地模块创建全局链接,详细用法:npm-link
npm link 使用全局前缀,可以使用 npm prefix -g 查看全局前缀
npm prefix 详细用法:npm-prefix
关于npm使用的目录结构介绍,可参考:folders | npm Docs
此时我们就使用cmd窗口,在任何位置指定baby命令了,示例如下:
C:\Users\cyinl>baby
There is a new baby.
如果想取消链接,我们可以使用 npm unlink -g <package> 来删除链接,它会删除 npm link 生成的内容,当然你也可以手动删除这些文件,这里就不演示了。
命令行参数处理
我们使用过的很多命令行,都是可以接受参数,如 npm -v 可以查看安装的npm版本号,npm -h 可以查看npm的使用帮助信息。那么使我们自己的命令也有类型的功能呢?
在node脚本中,我们可以通过系统变量 process.argv 获取到命令行参数信息。
接下来验证下,修改下 baby.js 如下:
#!/usr/bin/env node
console.log(process.argv);
执行baby -v,输出信息如下:
C:\Users\cyinl>baby -v
[
'D:\\Program Files\\nodejs\\node.exe',
'C:\\Users\\cyinl\\AppData\\Roaming\\npm\\node_modules\\baby\\bin\\baby.js',
'-v'
]
其中process为node进程中的全局变量,process.argv为一数组,数组内存储着命令行的各个部分,argv[0]为node的安装路径,argv[1]为主模块文件路径,剩下为子命令或参数。
我们可以通过 package.json里的version拿到版本信息。再修改 baby.js 如下:
#!/usr/bin/env node
const pkg = require('../package.json');
const opt = process.argv[2];
switch (opt) {
case '-v':
console.log(pkg.version)