模塊
什麼是模塊
模塊是Node.js應用程序的基本組成部分,文件和模塊是一一對應的。換言之,一個Node.js文件就是一個模塊,這個文件可能是JavaScript代碼、JSON或者編譯過的C/C++擴展。
創建及加載模塊
- 創建模塊
在Node.js中,創建一個模塊非常簡單,因爲一個文件就是一個模塊,我們要關注的問題僅僅在於如何在其他文件中獲取這個模塊。Node.js提供了exports和require兩個對象,其中exports是模塊公開的接口,require用於從外部獲取一個模塊的接口,即所獲取模塊的exports對象。 - 單次加載
require不會重複加載模塊,也就是說無論調用多少次require,獲得的模塊都是同一個。(類似於java中獲得的對象是單例的) - 覆蓋exports
有時候我們只是想把一個對象封裝到模塊中,例如
//singleobject.js
function Hello(){
var name;
this.setName = function(thyName){
name = thyName;
};
this.sayHello = function(){
console.log('Hello '+ name);
};
};
exports.Hello = Hello;
此時,我們在其他文件中需要通過require(‘./singleobject’).Hello來獲取Hello對象,這略顯冗餘,可以用下面方法稍微簡化:
//hello.js
function Hello(){
var name;
this.setName = function(thyName){
name = thyName;
};
this.sayHello = function(){
console.log('Hello '+ name);
};
};
module.exports = Hello;
這樣就可以直接獲得這個對象了:
//gethello.js
var Hello = require('./hello');
hello = new Hello();
hello.setName('BYVoid');
hello.sayHello();
注意,模塊接口的唯一變化是使用module.exports = Hello代替了exports.Hello= Hello。在外部引用該模塊時,其接口對象就是要輸出的Hello對象本身,而不是原先的exports。
事實上,exports本身僅僅是一個普通的空對象,即{ },它專門用來聲明接口,本質上是通過它爲模塊閉包的內部建立了一個有限的訪問接口。因爲它沒有任何特殊的地方,所以可以用其他東西來替代,譬如我們上面例子中的Hello對象。
創建包
包是在模塊基礎上更深一步的抽象,Node.js的包類似於C/C++的函數庫或者Java/.Net的類庫。它講某個獨立的功能封裝起來,用於發佈、更新、依賴管理和版本控制。Node.js根據CommonJS規範實現了包機制,開發了npm來解決包的發佈和獲取需求。
Node.js的包是一個目錄,其中包含了一個JSON格式的包說明文件package.json。嚴格符合CommonJS規範的包應該具備以下特徵:
- package.json必須在包的頂層目錄下;
- 二進制文件應該在bin ;
- JavaScript代碼應該在lib目錄下;
- 文檔應該在doc目錄下;
單元測試應該在test目錄下。
Node.js對包的要求並沒有這麼嚴格,只要頂層目錄下有package.json,並符合一些規範即可。作文件夾的模塊
模塊和文件是一一對應的。最簡單的包,就是一個作爲文件夾的模塊。- package.json
Node.js在調用某個包時,會首先檢查包中package.json文件的main字段,將其作爲包的接口模塊,如果package.json活main字段不存在,會嘗試尋找index.js或index.node作爲包的接口。
package.json是CommonJS規定的用來描述包的文件,完全符合規範的package.json文件應該含有以下字段。 - name: 包的名稱,必須是唯一的,由小寫英文字母、數字和下劃線組成,不能包含空格。
- description:包的簡要說明。
- version:符合語義化版本識別規範的版本
- keywords:關鍵字數組,通常用於搜索。
- maintainers:維護者數組,每個元素包含name、email(可選)、web(可選)字段。
- contributors:貢獻者數組,格式與maintainers相同。包的作者應該是貢獻者數組的第一個元素。
- licenses:許可證數組,每個元素要包含type(許可證的名稱)和url(鏈接到許可證文本的地址)字段。
- repositories:倉庫託管地址數組,每個元素要包含type(倉庫的類型,如git)、url(倉庫的地址)和path(相對於倉庫的路徑,可選)字段。
- dependencies:包的依賴,一個關聯數組,由包名稱和版本號組成。