用node開發併釋出一個cli工具

AndyLaw發表於2019-01-02

cli本質是一種使用者操作介面,根據一些指令和引數來與程式完成互動並得到相應的反饋,好的cli還提供幫助資訊,我們經常使用的vue-cli就是一個很好的例子。本文將使用nodejs從頭開發併發布一款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的log資訊

解析命令與引數

此處我們使用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

截止目前工作順利進行,我們還只是手工輸入的一些mock資訊,並沒有真正的實現天氣的查詢。 要想實現天氣查詢,必須藉助第三方的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,發現有結果了:

在這裡插入圖片描述

修修補補,新增loading提示和預設指令

截止當前,基本完成了功能開發,後續有一些小問題需要彌補一下,首先是一個進度提示,使用起來就更加可感知,我們使用ora庫.

其次我們需要當使用者輸入無匹配指令時給予一個引導,提供一個預設的log提示。

安裝依賴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包幫助理解npm


本文完!

相關文章