最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Node.js 使用命令行工具檢查更新

 更新時間:2017年06月08日 08:54:40   作者:KohPoll  
這篇文章主要介紹了Node.js 使用命令行工具檢查更新的方法,使用Node.js開發(fā)命令行工具是開發(fā)者應(yīng)該掌握的一項技能,適當(dāng)編寫命令行工具以提高開發(fā)效率,有需要的小伙伴可以參考下

隨著 Node.js 的“走紅”,使用 Node.js 開發(fā)命令行工具越來越簡單。一個成熟的命令行工具應(yīng)該從一開始就要考慮好之后的版本更新如何“優(yōu)雅”的告知用戶。最好的方法當(dāng)然是當(dāng)用戶在終端執(zhí)行命令時,將相關(guān)信息提示給用戶。

這篇文章將給出一個易用、高效、可定制的方法。源碼在這里: GITHUB ,歡迎大家順手點贊。接下來我將講解其實現(xiàn)思路。

使用

我們先簡單看看這個 npm 包的使用方法:

const updater = require('pkg-updater');
const pkg = require('./package.json'); // 命令行工具自己的 package 信息

updater({'pkg': pkg}) .then(() => { /* 在這里啟動命令行工具 */ });

updater({
 'pkg': pkg, 
 // 自定義 registry
 'registry': 'http://xxx.registry.com',
 // 自定義請求的 dist-tag,默認(rèn)是 latest
 'tag': 'next',
 // 自定義檢查間隔,默認(rèn)是 1h
 'checkInterval': 24 * 60 * 60 * 1000,
 // 自定義更新提示信息
 'updateMessage': 'package update from <%=current%> to <%=latest%>.',
 // 自定義強(qiáng)制更新的版本更新級別,默認(rèn)是 major
 'level': 'minor'
}).then(() => { /* 在這里啟動命令行工具 */ });

updater({
 'pkg': pkg,
 // 完全自定義版本更新時的邏輯
 'onVersionChange': function* (opts) {

 }
}).then(() => { /* 在這里啟動命令行工具 */ });

效果如圖:

實現(xiàn)

使用方法很簡單,我們一起來看看其實現(xiàn)方法。

需求

我們先來梳理下需求,一個命令行檢查更新器應(yīng)該至少提供如下功能:

能從遠(yuǎn)程獲取最新版本

能根據(jù)檢查結(jié)果進(jìn)行提示

在版本不兼容時可以直接退出,強(qiáng)制用戶升級程序

獲取版本

獲取最新版本這個功能看起來很簡單,就是發(fā)送一個請求從“某處”獲取信息。但是有一些問題需要我們考慮:

從哪里獲取版本信息?

獲取版本信息的策略是怎樣的?(什么時候獲?。揩@取的信息如何處理?)

從哪里獲取版本信息

我們的命令行工具一般都是使用 npm 進(jìn)行分發(fā),最簡便的方法就是直接通過 registry 獲取。通過請求 https://registry.npmjs.org/{name}/{dist-tag} 就可以得到 package 對應(yīng) tag 的版本信息。結(jié)果類似下面這樣:

// https://registry.npmjs.org/co/latest
{
 "name": "co",
 "version": "4.5.0"
}

在實際實現(xiàn)時,我們應(yīng)該允許調(diào)用者自定義 registry 地址、請求的 dist-tag 等,這樣可以有更多的定制性。

獲取版本信息的策略

首先想到的方法是用戶每次執(zhí)行命令時都去獲取一次版本信息,這樣的獲取策略應(yīng)該是最簡單和實時的。

但是這個策略其實并不合適:

每次執(zhí)行命令都要去發(fā)請求進(jìn)行檢查,如果網(wǎng)絡(luò)延遲,會阻塞命令執(zhí)行,影響用戶體驗

工具的版本更新其實并不會很頻繁,沒有必要進(jìn)行實時檢查

網(wǎng)絡(luò)請求的影響因素很多,不能保證每次都成功,應(yīng)該提供本地緩存機(jī)制來存儲請求成功的結(jié)果,避免版本信息的不可用

綜合上面的幾點,我們設(shè)計如下的獲取策略:

將發(fā)送網(wǎng)絡(luò)請求獲取版本信息的邏輯放在一個獨立的后臺進(jìn)程去執(zhí)行,保證不阻塞主命令執(zhí)行

請求成功后將版本信息、檢查時間緩存到用戶機(jī)器

每次執(zhí)行命令時,只是讀取本地緩存下來的版本信息,不去發(fā)送網(wǎng)絡(luò)請求

根據(jù)緩存下來的檢查時間和當(dāng)前時間,在一個間隔之內(nèi)不去額外創(chuàng)建后臺檢查進(jìn)程

將上面的策略翻譯成代碼大概就是下面這樣:

// 讀取本地緩存的檢查結(jié)果
const checkInfo = yield updater.readCheckInfo(opts);
const lastCheck = checkInfo.lastCheck;
const lastVersion = checkInfo.lastVersion;

// 根據(jù)版本信息提示用戶
// ...

// 在時間間隔內(nèi),直接返回
if (Date.now() - lastCheck < opts.checkInterval) {
 return;
}

// 創(chuàng)建后臺檢查進(jìn)程
try {
 require('child_process').spawn(
 process.execPath,
 [require('path').join(__dirname, '_check.js'), JSON.stringify({
  'pkg': opts.pkg, // package 信息
  'tag': opts.tag, // 檢查的 dist-tag
  'logFile': opts.logFile, // 緩存文件路徑
  'registry': opts.registry // registry 地址
 })],
 {'stdio': ['ignore', 'ignore', 'ignore'], 'detached': true}
 ).unref();
} catch(e) {}

后臺進(jìn)程執(zhí)行的 _check.js 文件也很簡單,如下所示:

const opts = JSON.parse(process.argv[2]);

let lastVersion = '';
try {
 // 發(fā)送請求獲取最新版本
 const url = normalizeUrl(opts.registry + '/' + opts.pkg.name + '/' + (opts.tag || 'latest'));
 const res = yield got.get(url, {
 'json': true,
 'timeout': 60 * 1000
 });
 if (res && res.body && res.body.version) {
 lastVersion = res.body.version;
 }
} catch(e) {}

// 如果獲取失敗了,最新版本就是當(dāng)前版本(package.version)
if (!lastVersion) {
 lastVersion = opts.pkg.version;
}

let data = yield util.readJson(opts.logFile);
if (!data[opts.pkg.name]) {
 data[opts.pkg.name] = {};
}
data[opts.pkg.name].lastVersion = lastVersion; // 最新版本
data[opts.pkg.name].lastCheck = Date.now(); // 檢查時間

// 寫入緩存
yield util.writeJson(opts.logFile, data);

提示

當(dāng)版本更新了,我們應(yīng)該在終端提示用戶。這里有兩個問題:

提示文案的問題

提示文案顯示間隔的問題(一直顯示?每隔一段時間顯示?)

這里我們采取的策略是:

提供默認(rèn)提示文案,清晰的說明當(dāng)前版本、最新版本、更新方法,允許調(diào)用者自定義提示文案

只要有更新就一直顯示提示文案,因為我們希望用戶經(jīng)常的進(jìn)行更新

實現(xiàn)代碼大概如下:

// 比對版本
const type = updater.diffType(opts.pkg.version, lastVersion, opts.level);
if (type) {
 // 根據(jù)模板渲染提示信息
 const str = updater.template(opts.updateMessage || updater.defaultOpts.updateMessage)({
 'colors': updater.colors,
 'name': opts.pkg.name,
 'current': opts.pkg.version,
 'latest': opts.lastVersion,
 'command': 'npm i -g ' + opts.pkg.name
 });
 // 進(jìn)行提示
 console.log(
 updater.boxen(str, {
  'padding': 1,
  'margin': 1,
  'borderStyle': 'classic'
 })
 );
}

強(qiáng)制升級

對于 npm 模塊來說,版本 a.b.c 的更新一般有三種情況:

patch:c 位,小版本更新,一般是 bug 修復(fù)

minor:b 位,中版本更新,一般增加新功能、bug 修復(fù)

major,a 位,大版本更新,一般是不兼容的升級

我們希望當(dāng)遠(yuǎn)程版本的更新如果是 major 形式,命令行工具將直接退出,強(qiáng)制用戶進(jìn)行升級后才能使用。這可以保證我們推送一個大版本后,所有的用戶都能夠馬上更新掉,而不是繼續(xù)使用老版本,造成版本碎片的問題。

實現(xiàn)代碼大致如下:

// 比對版本
const type = updater.diffType(opts.pkg.version, lastVersion, opts.level);
if (type) {
 // 根據(jù)模板渲染提示信息
 const str = updater.template(opts.updateMessage || updater.defaultOpts.updateMessage)({
 'colors': updater.colors,
 'name': opts.pkg.name,
 'current': opts.pkg.version,
 'latest': opts.lastVersion,
 'command': 'npm i -g ' + opts.pkg.name
 });
 // 進(jìn)行提示
 console.log(
 updater.boxen(str, {
  'padding': 1,
  'margin': 1,
  'borderStyle': 'classic'
 })
 );

 // 不兼容的更新,直接讓進(jìn)程退出
 if (type == 'incompatible') {
 process.exit(1);
 }
}

總結(jié)

命令行檢查更新看似簡單,其實仔細(xì)思考,還是有很多細(xì)節(jié)。希望這篇文章對你有所啟發(fā)。

相關(guān)文章

  • nodejs 十六進(jìn)制字符串型數(shù)據(jù)與btye型數(shù)據(jù)相互轉(zhuǎn)換

    nodejs 十六進(jìn)制字符串型數(shù)據(jù)與btye型數(shù)據(jù)相互轉(zhuǎn)換

    這篇文章主要介紹了nodejs 十六進(jìn)制字符串型數(shù)據(jù)與btye型數(shù)據(jù)相互轉(zhuǎn)換,需要的朋友可以參考下
    2018-07-07
  • nodejs+mongodb aggregate級聯(lián)查詢操作示例

    nodejs+mongodb aggregate級聯(lián)查詢操作示例

    這篇文章主要介紹了nodejs+mongodb aggregate級聯(lián)查詢操作,結(jié)合實例形式分析了基于nodejs的mongodb數(shù)據(jù)庫級聯(lián)查詢相關(guān)操作技巧,需要的朋友可以參考下
    2018-03-03
  • vscode調(diào)試node.js的實現(xiàn)方法

    vscode調(diào)試node.js的實現(xiàn)方法

    這篇文章主要介紹了vscode調(diào)試node.js的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • TypeScript開發(fā)Node.js程序的方法

    TypeScript開發(fā)Node.js程序的方法

    這篇文章主要介紹了TypeScript開發(fā)Node.js程序的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • websocket+node.js實現(xiàn)實時聊天系統(tǒng)問題咨詢

    websocket+node.js實現(xiàn)實時聊天系統(tǒng)問題咨詢

    最近新學(xué)習(xí)websocket,做了一個實時聊天。用Node.js搭建的服務(wù):serevr.js. 兩個相互通信頁面:client.html 和server.html 但是就是有很多問題,下面通過本文給大家分享下
    2017-05-05
  • 淺析node應(yīng)用的timing-attack安全漏洞

    淺析node應(yīng)用的timing-attack安全漏洞

    本篇文章給大家通過原理的原因分析了node應(yīng)用的timing-attack安全漏洞問題,有興趣的朋友閱讀參考下。
    2018-02-02
  • nodejs socket實現(xiàn)的服務(wù)端和客戶端功能示例

    nodejs socket實現(xiàn)的服務(wù)端和客戶端功能示例

    這篇文章主要介紹了nodejs socket實現(xiàn)的服務(wù)端和客戶端功能,結(jié)合具體實例形式分析了nodejs基于socket通信實現(xiàn)的服務(wù)端與客戶端功能相關(guān)操作技巧,需要的朋友可以參考下
    2017-06-06
  • 微信小程序搭載node.js服務(wù)器的簡單教程

    微信小程序搭載node.js服務(wù)器的簡單教程

    小程序是一種全新的連接用戶與服務(wù)的方式,它可以在微信內(nèi)被便捷地獲取和傳播,同時具有出色的使用體驗,下面這篇文章主要給大家介紹了關(guān)于微信小程序搭載node.js服務(wù)器的簡單教程,需要的朋友可以參考下
    2022-12-12
  • Nodejs新特性async和await的使用詳解

    Nodejs新特性async和await的使用詳解

    這篇文章主要介紹了Nodejs新特性async和await的使用,主要包括Es6常見語法的使用及Async、Await和Promise的示例代碼,需要的朋友可以參考下
    2022-09-09
  • xtemplate node.js 的使用方法實例解析

    xtemplate node.js 的使用方法實例解析

    這篇文章主要介紹了xtemplate node.js 的使用方法實例說明,非常不錯,介紹的非常詳細(xì),具有參考借鑒價值,需要的朋友可以參考下
    2016-08-08

最新評論

颍上县| 景洪市| 阿克陶县| 彭泽县| 如皋市| 山东省| 宜川县| 高邑县| 双鸭山市| 汶上县| 南澳县| 伊吾县| 赫章县| 宣武区| 武山县| 肃宁县| 涞水县| 兴仁县| 吉安县| 邢台县| 团风县| 海口市| 奈曼旗| 西宁市| 方山县| 湟源县| 嘉善县| 凌云县| 台东县| 开原市| 邵阳县| 淳化县| 景宁| 康平县| 洪江市| 伊川县| 华容县| 开平市| 罗平县| 叶城县| 东丰县|