Node模組化及CommonJS規範
前面幾篇播客使用過內建fs模組,http模組, 而這些模組都不是我們寫的, 都是直接拿過來使用, 那麼我們能不能自己寫一個模組, 應該怎麼寫, 有哪些規矩, 如果我們自己寫了一個模組, 能不能提供給其他程式設計人員直接使用, 應該怎麼用?
Electron 跨平臺的桌面應用框架: https://electronjs.org/
CommonJS規範的由來
JS 的表現的表現能力取決於宿主環境提供的API, 在web1.0 時代, W3C 組織提供了瀏覽器的規範支援, 在web2.0 時代, 隨著HTML5的發展, 更多的標準API 出現在了瀏覽器中, 但是, 在後端 JS 中標準的制定紋絲不動 ;
由 Mozilla 工程師Kevin Dangoor於2009年1月提出名為 ServerJS 的規範; 2009年8月,更名為CommonJS,以顯示 API 的更廣泛適用性。
我在這裡描述的不是技術問題。這是一個人們聚在一起並決定前進並開始建立更大和更冷的東西的問題 --Kevin Dangoor
CommonJS 的模組規範
CommonJS對模組的定義十分簡單,主要分為:
1、模組引用:
使用 require()
方法引入一個模組API ;
2、模組定義:
在模組中使用 exports 物件匯出當前模組資料或方法;
在模組中還存在一個module物件,它代表模組自身,module物件有一個exports 屬性,用於資料匯出;
其實exports 物件就是module.exports 的引用; exports === module.exports
3、模組標識:
其實就是模組的檔名,必須符合小駝峰法命名規則,使用require()
引入時使用 . 或 ..
開頭的相對路徑或`/開頭的絕對路徑,引入時可以不寫檔案字尾名;
重點注意 : 模組中的方法和變數的作用於盡在模組內部,每個模組具有獨立的空間,互不干擾;
CommonJS 構建的模組機制中的引入與匯出是我們完全不用考慮變數汙染或者替換的問題。
模組載入的順序和規則
在 CommonJS 規範中,使用 require()
載入(引入) 模組時,模組標識必須使用相對路徑或絕對路徑指明模組位置,但是在node的實現中,我們可以不指明模組路徑;如: require('fs')、require('moment')
;
如果沒有指明路徑,那就是載入核心模組或第三方模組,指明載入路徑一般就是載入自定義模組;
不管載入什麼模組,都是優先從快取中載入:
Node 載入模組時,如果這個模組已經被載入過了,則會直接快取起來,將來再次引用時不會再次載入這個模組(即:如果一個模組被載入兩次,則模組中的程式碼只會被執行一次)
而核心模組和第三方模組的的載入順序就是:
先載入核心模組,核心模組的內容都是在安裝node時已經編譯好的可執行的二進位制程式碼,載入執行的速度,僅次於快取載入,如果核心模組中沒有,則載入第三方模組
第三方模組的載入規則:
- 先在當前檔案的模組所屬目錄去找 node_modules目錄
- 如果找到,則去該目錄中找 模組名的目錄 如 : moment
- 如果找到 moment 目錄, 則找該目錄中的 package.json檔案
- 如果找到 package.json 檔案,則找該檔案中的 main屬性
- 如果找到main 屬性,則拿到該屬性對應的檔案
- 如果找到 moment 目錄之後,
- 沒有package.json
- 或者有 package.json 沒有 main 屬性
- 或者有 main 屬性,但是指向的路徑不存在
- 則 node 會預設去看一下 moment 目錄中有沒有 index.js --> index.json--> index.node 檔案
- 如果找不到index 或者 找不到 moment 或者找不到 node_modules
- 則進入上一級目錄找 node_moudles 查詢(規則同上)
- 如果上一級還找不到,繼續向上,一直到當前檔案所屬磁碟的根目錄
- 如果到磁碟概目錄還沒有找到,直接報錯
Node對CommonJS的實現 (Node模組化,自定義模組)
model1.js
var a = 1;
function add(value1, value2) {
return value1 + value2;
}
//變數匯出
exports.a = a;
//方法匯出
exports.add = add;
test.js
//匯入當前路徑下的自定義模組model1
var model = require('./model1');
console.log(model.a);
console.log(model.add(3,4));
執行結果
以上程式碼就是自定義模組的基本規則 這是重點
注意:
module.exports 可以直接賦值,值就會被匯出
但是exports直接賦值,不能匯出; 必須使用exportsd.xx
// module.exports = {name:123};
// exports.data = {};
// module.exports 可以直接賦值,值就會被匯出
// 但是exports直接賦值,不能匯出; 必須使用exportsd.xx
//還可以使用這種匿名匯出,類似於構造方法
// module.exports = function(){
// return 123;
// }
module.exports = {
name:'lisi',
fun:function(){
console.log(123456);
}
}