node 模組引入主要會經歷如下3個步驟:
在 node 中,模組分為核心模組和檔案模組。
核心模組是 node 提供的模組。其中部分模組在 node 原始碼編譯時直接生成二進位制執行檔案,在 node 程序啟動時被載入到記憶體中,因此當這部分模組引入時,會只直接跳過檔案定位和編譯執行,且在路徑分析中優先判斷,它的載入速度最快。
檔案模組是使用者編寫的模組。檔案模組在執行時動態載入,需要完整的路徑分析、檔案定位、編譯執行過程,速度比核心模組慢。
跟瀏覽器會快取靜態指令碼檔案以提高效能一樣,node 對引入的模組也會進行快取,以減少二次引入的開銷。不同之處在於,瀏覽器是快取檔案,而 node 是快取編譯和執行之後的物件。
不論是核心模組還是檔案模組,require()
方法對相同的模組的二次載入一律採用快取優先的方式。
require()
方法接受乙個識別符號作為引數,識別符號有幾種形式,根據不同的識別符號,模組的查詢和定位有不同的差異。
模組識別符號主要分為以下幾類:
核心模組
核心模組的優先順序僅次於快取載入。
如果要載入乙個與核心模組識別符號相同的自定義模組,那是不會成功的。如果要載入必須選擇乙個不同的識別符號或換成路徑方式。
路徑形式的檔案模組
以 .、… 和 / 開頭的識別符號,這裡都被當作檔案模組處理。在分析檔案模組時,require()
方法會將路徑轉為真實路徑,並以真實路徑作為索引,將編譯後的結果存放到快取中。
由於檔案模組給 node 指明了確切的檔案位置,所以在查詢過程中可以節約大量時間,其載入時間慢於核心模組。
自定義模組
自定義模組是一種特殊的檔案模組,可以是乙個檔案或者包的形式。這類模組的查詢是最費時的,是所有方式中最慢的。
在介紹自定義模組的查詢方式之前,需要先介紹一下模組路徑這個概念。
模組路徑是 node 在定位檔案模組的具體檔案時制定的查詢策略,具體表現為乙個路徑組成的陣列。關於這個路徑的生成規則,我們可以手動嘗試一番。
(1) 建立 module_path.js 檔案,其內容如下:
console.
log(module.paths)
;
(2) 將該檔案放到任意乙個目錄中,然後執行如下命令:
node module_path.js
在 linux 下,你可能得到如下的陣列輸出:
[
'/home/user/demo/node_modules'
,'/home/user/node_modules'
,'/home/node_modules'
,'/node_modules'
]
在 windows 下,可能是這樣:
[
'c:\\demo\\node_modules'
,'c:\\node_modules'
]
可以看出,模組路徑的生成規則如下所示:
當前檔案目錄下的 node_modules 目錄;
父目錄下的 node_modules 目錄;
父目錄下的父目錄下的 node_modules 目錄;
沿著路徑向上逐級遞迴,直到根目錄下的 node_modules 目錄。
在自定義模組的載入過程中,node 會逐個嘗試模組路徑中的路徑,直到找到目標檔案為止。可以看出,當前檔案的路徑越深,模組查詢耗時會越多,這是自定義模組的載入速度最慢的原因。
在檔案定位過程中,有些細節需要注意,主要包括副檔名的分析、目錄和包的處理。
副檔名分析
require()
在分析識別符號的過程中,會出現識別符號中不包含副檔名的情況。commonjs 模組規範也允許在識別符號中不包含副檔名,這種情況下,node 會按 .js、.json、.node 的次序補足副檔名,依次嘗試。
在嘗試的過程中,需要呼叫 fs 模組同步阻塞式的判斷檔案是否存在。因為 node 是單執行緒的,所以這裡是乙個會引起效能問題的地方。所以,如果是 .json 和 .node 檔案,在識別符號中帶上副檔名,會加快一點速度。
目錄分析和包
在分析識別符號的過程中,require()
通過分析副檔名後,可能沒有查詢到對應的檔案,但卻得到乙個目錄,這在引入自定義模組和逐個模組路徑查詢時經常會出現,此時 node 會將目錄當做乙個包來處理。
在這個過程中,node 對 commonjs 包規範進行了一定程度的支援。首先,node 在當前目錄下查詢 package.json(commonjs 包規範定義的包描述檔案),通過json.parse()
解析出包描述物件,從中取出 main 屬性指定的檔名進行定位。如果檔名缺少副檔名,將會進入副檔名分析的步驟。
而如果 main 屬性指定的檔名錯誤,或者壓根沒有 package.json 檔案,node 會將 index 當作預設檔名,然後依次查詢 index.js、index.json、index.node。
如果在目錄分析的過程中沒有定位成功任何檔案,則自定義模組進入下乙個模組路徑進行查詢。如果模組路徑陣列都被遍歷完畢,依然沒有查詢到目標檔案,則會丟擲查詢失敗的異常。
node 4 node模組與模組的引入
在node中每個js檔案都是乙個模組 arguments.callee 在函式內獲取此函式 立即執行函式的5個形參 exports是乙個物件 專門用來暴露模組的資料 本質上就是通過module.exports這個物件暴露資料的 require函式型別 專門用來引入模組的 module模組物件 fil...
node引入模板
大家請看一下四種node引入方式,能看出些什麼呢?我們把這個資料夾拖入node modules資料夾即可。引用時就可以像官方包那樣簡便了,如上面第乙個。index檔案是乙個特殊的預設檔案,如果我們把自己寫的包以index命名放在ff資料夾中,通過小黑板生成package.json,引用時相對路徑寫到...
Node模組型別
在node應用中,並不是所有的模組都是同一類,通常會有核心模組 第三方模組 檔案模組 資料夾模組幾種。核心模組指的是那些被編譯進node的二進位制模組,它們被預置在node中,提供node的基本功能,如fs http https等。核心模組使用c c 實現,外部使用js封裝。要載入核心模組,直接在 ...