NodeJS模塊全面指南

2018-06-09 17:15 更新

NodeJS模塊

所謂的NodeJS模塊其實就是指NodeJS package,即nodejs包。

在使用NodeJS進行開發(fā)的時候,往往需要用到各種各樣的第三方包。當然,很多時候我們在實際開發(fā)的時候自己也會按照功能或者需求來封裝一個本地的包。

那么問題來了,NodeJS模塊究竟是什么?

什么是NodeJS模塊?

在說這個問題之前,我們有必要先提出一個概念,即模塊規(guī)范。關于模塊規(guī)范可以參與之前的這篇文章從CommonJS到Sea.js。

所以,現(xiàn)階段Javascript領域大體上有三種比較流行的模塊規(guī)范,一種是AMD規(guī)范,一種是CMD規(guī)范,還有一種就是CommonJS規(guī)范。NodeJS采用的規(guī)范就是CommonJS規(guī)范。這三種規(guī)范中,前兩者專注于客戶端,即瀏覽器端的規(guī)范標準,而后者而其實是服務器端的規(guī)范。

CommonJS規(guī)范說,一個單獨的文件其實就是一個模塊。在NodeJS中,一個模塊可以是一個單獨的文件,也可以是一個包含多個文件(子模塊)的目錄。與此同時,CommonJS規(guī)范還要求模塊都采用統(tǒng)一的格式exports或者module.exports導出模塊接口。

NodeJS包和模塊

上面我們已經知道了模塊的概念,那么包其實就是包含多個模塊目錄。同時,還要附加一個重要的package.json文件。那么這個package.json文件是個什么情況呢?如下圖,

這個json文件可以配置的很簡略,也可以配置的很復雜。關于各個字段的具體含義可以參閱官方文檔或者漢化文檔。

其實package.json就是用來聲明NodeJS包的,包括包名字,版本,作者,包入口信息,依賴等信息。

其中有兩個字段這里稍微提一下,dependenciesdevDependencies字段。前者表明包在生產環(huán)境需要的第三方依賴,而后者表明包在開發(fā)階段所需要的第三方依賴(比如構建、測試等第三方包等)。

npm包管理器

NPM是NodeJS包管理器,可以看成類似Java中的Maven或者Ruby中gem。

現(xiàn)在的npm是在最初的版本上改版而來的,界面更好看了,對包信息的展示更加人性化了。而且目前除了用于面向普通開發(fā)者提供服務之外,還提供私有包倉庫和企業(yè)級包倉庫。聽說馬上再一次改版的npm3.0也要到來了,提供了眾多的優(yōu)化和新特性,詳情請參閱這篇文章。

創(chuàng)建包

前面我們說package.json是NodeJS包的標識或者說配置文件。所以,任何一個NodeJS包都是從新建package.json文件開始的。

這里我們一般不會傻傻的手動去新建一個package.json文件,而是通過npm工具來生成。


$ cd YOUR_PROJECT_DIR
$ npm init

在命令行中鍵入npm init后,CLI將會出現(xiàn)一些互動的提示來引導你完成package.json的生成。如下圖,

當然CLI只會詢問你一些package.json文件必須的字段,而且它會智能的給出一些默認值(括號中的內容),最后它會向你確認是否可行。

package.json中有一個字段為main,此字段為意為包的入口。如果留空的話,NodeJS會默認將包目錄下的index.js作為入口文件。

導出包接口

NodeJS模塊使用的是CommonJS規(guī)范,使用exports或者module.exports導出模塊準備暴露的接口。比如,


exports.sayHello = function() {
    // your code
};
exports.sayGoodbye = function() {
    // your code
};

或者,


module.exports = function People() {
    // your code
};

那么,exportsmodule.exports這兩種方式到底有什么區(qū)別呢?

其實在NodeJS內部,模塊真正返回的是module.exports對象,而exports只是module.exports的引用而已。如下,


exports = module.exports = {};

如果你直接賦值一個函數(shù)(function)或者一個對象({})給exports,這樣的話就破壞了exportsmodule.exports的引用關系了,而模塊將會返回空對象。所以當我們需要暴露一個函數(shù)或者一個對象時,應該直接賦值給module.exports而不是exports。

本博客前面有一篇文章如何導出NodeJS模塊就是闡述NodeJS如何返回接口的。

發(fā)布包

好了,在我們完成模塊的編寫之后。我們希望將自己的包發(fā)布到NPM上,成就自己的同時又方便他人。該怎么做呢?

其實很簡單。npm同樣提供了相應的接口,npm addusernpm publish


$ npm adduser

npm會向你索要npmjs.com用戶名,密碼以及Email。如果沒有問題,接下來就可以執(zhí)行npm publish了。

這里提一下執(zhí)行npm publish時經常會遇到的兩個問題。

第一,提示你沒有權限發(fā)布。這種情況往往是你的包名已經在npm倉庫中被占用了。所以這種情況你需要給你的包換個名字。
第二,提示你必須更新版本。這種情況一般是你是在本地更新了包,然后想更新npm倉庫時卻出現(xiàn)了這種錯誤。造成這個錯誤的原因其實很簡單,因為已經發(fā)布在npm倉庫中的包不允許不改變版本號的情況下就改變包代碼。所以這種情況你需要改動package.json中的version字段。

額外的問題

我們說整個NodeJS社區(qū)都是一片欣欣向榮的景象,npm倉庫的包數(shù)量很多,社區(qū)也很活躍。這些都是好現(xiàn)象,而且我個人也非??春肗odeJS在未來的發(fā)展。

但是,就我個人使用NodeJS的經驗,遇到兩個可能存在一些隱患的地方。

第一,npm倉庫上的第三方包質量參差不齊,有的包基本就是垃圾,給使用者可能會造成一些損失。
第二,有些第三方包本身升級了,但是其周邊插件包的更新卻跟不上,有時候你為了向插件包妥協(xié),不得不放棄新版本而使用低版本。
第三,因為第三方包是可以直接在服務器端運行的,有時候可能需要考慮一些安全因素。

創(chuàng)建命令行工具包

通過npm install -g xxx命令安裝的部分第三方包后,就可以直接在命令行上運行相關命令了。比如下圖,

這種效果是如何做的呢?

添加bin字段

我們可以在package.json文件中添加一個叫做bin的字段。比如,npm cli中就是這樣的,


{
    "bin": {
        "npm" : "./cli.js"
    }
}

然后你在命令行中輸入npm,NodeJS就會去執(zhí)行對應的NodeJS模塊。

如果你只有一個可執(zhí)行命令,并且還和包名一致,那么package.json中你可以這么寫,


{
    "name": "my-package",
    "version": "1.2.5",
    "bin": "./bin/my-package"
}

然后,你需要在bin/my-package文件的第一行添加如下代碼,


#!/usr/bin/env node

命令行參數(shù)的解析

我們通過命令行使用部分第三方包時,有時候包會提供各種命令和參數(shù),如下圖,

從圖中可以看出,這個harp提供四個命令以及兩個參數(shù),并且簡略的展示了Usage。

那么這種比較完備的命令行包是如何做的呢?

這里我們一般會有兩個方案去做成這件事,第一就是使用原生的progress.argv來解析,另一種方案就是使用commander.js。后面我會專門寫篇文章來闡述commander.js的用法。

參考示例

bullhead是作者隨便寫的一個小玩意兒,主要目的是用來聯(lián)系npm包創(chuàng)建及發(fā)布等操作。有興趣可以參考。

參考列表



以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號