Node.js 从零开发并发布 CLI 工具:以天气查询为例

作者:岩茶时间:2026-10-22 19:59:06浏览:430

本文详细介绍如何使用 Node.js 从零构建并发布一个命令行工具(CLI)。内容涵盖项目初始化、bin 入口配置、本地调试技巧,以及利用 minimist 解析命令行参数。通过集成 axios 和心知天气 API 实现真实数据查询,并添加 ora 库优化用户交互体验,最终演示如何将工具发布至 npm 供全局使用。

Node.js CLI 工具开发概述

CLI(命令行界面)本质上是用户与程序交互的接口,通过接收指令和参数来获取反馈。优秀的 CLI 工具通常提供清晰的帮助信息,例如我们常用的 vue-cli 便是典型代表。本文将演示如何使用 Node.js 从零开始开发并发布一款用于查询天气的 CLI 工具。

项目运行效果如下图所示:

Node.js CLI 工具开发概述 

项目初始化与本地调试配置

配置项目

首先初始化项目:npm init -y 接着编写入口文件 index.js:


module.exports = function(){ 
	console.log('welcome to Anderlaw weather') 
}

创建 bin 目录

在 bin 目录下创建 index 文件:


#!/usr/bin/env node
require('../')()

在 package.json 中配置 bin 字段信息


{
 "name": "weather",
 "version": "1.0.0",
 "description": "",
 "main": "index.js",
 "bin": {
 "weather": "bin/index"
 }
}

随后在根目录(与 package.json 同级)执行 npm link,该命令会将当前项目的模块信息及 bin 指令以软链接形式注册到 npm 全局环境中:

  • 此时在 C:\Users\mlamp\AppData\Roaming\npm\node_modules 目录下会新增一个模块链接
  • 在 C:\Users\mlamp\AppData\Roaming\npm 目录下会生成一个名为 weather 的 cmd 文件。

这样做的好处是便于本地调试。打开终端输入:weather,即可看到 welcome to Anderlaw weather 的日志输出。

命令行参数解析与逻辑处理

解析命令与参数

此处我们选用 minimist 库来解析类似 npm --save、npm install 等命令的参数。

安装依赖库 npm i -S minimist

通过 process.argv 获取完整的输入信息

使用 minimist 进行解析,例如:


weather today === args:{_:['today']}
weather -h === args:{ h:true }
weather --location 'china' === args:{location:'china'}

首先实现查询今天和明天天气的功能,执行命令 weather today[tomorrow]


const minimist = require('minimist');
module.exports = ()=>{
 const args = minimist(process.argv.slice(2));//前两个是编译器相关路径信息,可以忽略
 let cmd = args._[0];
 switch(cmd){
 	case 'today':
 	console.log('今天天气不错呢,暖心悦目!');
 	break;
 	case 'tomorrow':
 	console.log('明天下大雨,注意带雨伞!');
 	break;
 }
}

上述代码中,若直接输入 weather 则会报错,因为未获取到有效参数。此外,目前尚未添加版本信息,因此需要进一步优化代码。


const minimist = require('minimist')
const edition = require('./package.json').version
module.exports = ()=>{
 const args = minimist(process.argv.slice(2));//前两个是编译器相关路径信息,可以忽略
 let cmd = args._[0] || 'help';
 if(args.v || args.version){
		cmd = 'version';//查询版本优先!
	}
 switch(cmd){
 	case 'today':
 	console.log('今天天气不错呢,暖心悦目!');
 	break;
 	case 'tomorrow':
 	console.log('明天下大雨,注意带雨伞!');
 	break;
 	case 'version':
 	console.log(edition)
 	break;
 	case 'help':
 	console.log(`
  	weather [command] <options>
 
		  today .............. show weather for today
		  tomorrow ............show weather for tomorrow
		  version ............ show package version
		  help ............... show help menu for a command
		`)
 }
}

集成天气 API 与交互优化

接入天气 API

截至目前,功能运行正常,但仅使用了手动输入的模拟数据(mock data),并未真正实现天气查询。要实现真实查询,必须借助第三方 API,这里选用心知天气提供的免费数据服务接口。

需先注册以获取 API Key 和 ID。发送请求时使用 axios 库(HTTP 客户端请求库)。

安装依赖:npm i -S axios 封装 http 模块


///ajax.js
const axios = require('axios')
module.exports = async (location) => {
 const results = await axios({
 method: 'get',
 url: 'https://api.seniverse.com/v3/weather/daily.json',
 params:{
  key:'wq4aze9osbaiuneq',
  language:'zh-Hans',
  unit:'c',
  location
 }
 })
 return results.data
}

该模块接收地理位置信息,并返回今天、明天及后台的天气数据。

例如查询上海今天的天气:weather today --location shanghai

修改入口文件,添加 async标志 异步标志


const minimist = require('minimist')
const ajax = require('./ajax.js')
const edition = require('./package.json').version
module.exports = async ()=>{
 const args = minimist(process.argv.slice(2));//前两个是编译器相关路径信息,可以忽略
 let cmd = args._[0] || 'help';
 if(args.v || args.version){
		cmd = 'version';//查询版本优先!
	}
 let location = args.location || '北京';
 let data = await ajax(location);
 data = data.results[0];
	let posotion= data.location;
 let daily = data.daily;
 switch(cmd){
 	case 'today':
 	//console.log('今天天气不错呢,暖心悦目!');
 	console.log(`${posotion.timezone_offset}时区,${posotion.name}天气,${posotion.country}`)
  console.log(`今天${daily[0].date}:白天${daily[0].text_day}夜晚${daily[0].text_night}`)
 	break;
 	case 'tomorrow':
 	//console.log('明天下大雨,注意带雨伞!');
 	console.log(`${posotion.timezone_offset}时区,${posotion.name}天气,${posotion.country}`)
  console.log(`今天${daily[1].date}:白天${daily[1].text_day}夜晚${daily[1].text_night}`)
 	break;
 	case 'version':
 	console.log(edition)
 	break;
 	case 'help':
 	console.log(`
  	weather [command] <options>
 
		  today .............. show weather for today
		  tomorrow ............show weather for tomorrow
		  version ............ show package version
		  help ............... show help menu for a command
		`)
 }
}

输入命令 weather today --location shanghai,此时可以看到查询结果:

Node.js CLI 工具开发概述 

完善细节,添加加载提示和默认指令处理

当前功能基本完成,后续需补充一些细节。首先是进度提示,以提升用户感知度,这里使用 ora 库。

其次,当用户输入未匹配的指令时,需提供引导信息,即默认的日志提示。

安装依赖 npm i -S ora

编写 loading 模块:


const ora = require('ora')
module.exports = ora()
// method start and stop will be use

修改入口文件


const minimist = require('minimist')
const ajax = require('./ajax.js')
const loading = require('./loading')
const edition = require('./package.json').version
module.exports = async ()=>{
 const args = minimist(process.argv.slice(2));//前两个是编译器相关路径信息,可以忽略
 let cmd = args._[0] || 'help';
 if(args.v || args.version){
		cmd = 'version';//查询版本优先!
	}
 let location = args.location || '北京';
 loading.start();
 let data = await ajax(location);
 data = data.results[0];
	let posotion= data.location;
 let daily = data.daily;
 switch(cmd){
  case 'today':
 	//console.log('今天天气不错呢,暖心悦目!');
 	console.log(`${posotion.timezone_offset}时区,${posotion.name}天气,${posotion.country}`)
  console.log(`今天${daily[0].date}:白天${daily[0].text_day}夜晚${daily[0].text_night}`)
  loading.stop();
  break;
  case 'tomorrow':
  
 	//console.log('明天下大雨,注意带雨伞!');
 	console.log(`${posotion.timezone_offset}时区,${posotion.name}天气,${posotion.country}`)
  console.log(`今天${daily[1].date}:白天${daily[1].text_day}夜晚${daily[1].text_night}`)
  loading.stop();
 	break;
  case 'version':
  
  console.log(edition)
  loading.stop();
 	break;
 	case 'help':
 	console.log(`
  	weather [command] <options>
 
		  today .............. show weather for today
		  tomorrow ............show weather for tomorrow
		  version ............ show package version
		  help ............... show help menu for a command
  `)
  loading.stop();
  default:
  console.log(`你输入的命令无效:${cmd}`)
  loading.stop();
 }
}

工具发布与全局使用

发布

发布至 npm 仓库后,可直接通过 npm i -g weather 全局安装我们发布的 CLI 工具,并在任意位置输入 weather 命令查询天气。

若不清楚发布流程,可参考我的另一篇文章《发布一款 npm 包》以加深理解。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

作者最新文章