Node.js之模組機制

逆月翎發表於2019-09-21

文章原創於公眾號:程式猿周先森。本平臺不定時更新,喜歡我的文章,歡迎關注我的微信公眾號。
file

其實在JavaScript的發展中,它主要是在瀏覽器前端中被應用廣泛。因為在實際應用中, JavaScript的表現能力主要取決於宿主環境的API支援程度, 在最早期,只有對BOM, DOM的支援,隨著HTML5的出現,在瀏覽器中出現了更多,更強大的API供JavaScript呼叫,但是這些都是發生在前端,後端JavaScript的規範卻遠遠落後。Java有class檔案,Phthon有import機制,PHP有include和require,但是JavaScript通過script標籤引入程式碼的方式顯得雜亂無章,為我們的後期維護增加了難度。對於JavaScript來說,還有四大主要缺點:

* 1.沒有模組系統。

* 2.標準庫比較少。

* 3.沒有標準,統一的介面。

* 4.缺乏包管理系統。

Node.js實現了一套非常易用的模組系統,而Node的包管理系統NPM對包規範的完好支援使得Node應用在開發過程事半功倍。這一篇文章,主要針對Node的模組以及包的實現進行說明。

Node的模組規範

其實模組的定義非常簡單,主要分為模組引用,模組定義和模組標識三個部分。

1)模組引用

Node.js中存在require()方法,這個方法接受模組標識,以此引入一個模組的API到當前的上下文中。

2)模組定義

既然我們可以用require()來引入模組,那自然也可以引出模組。Node.js提供了exports物件用於匯出當前模組的方法和變數,並且exports是唯一匯出的出口。在每個模組中,存在一個module物件,表示模組本身,exports其實就是module的一個屬性。在Node.js中,一個檔案其實就是一個模組,將我們需要匯出的方法和屬性繫結在exports物件上作為屬性就可以將該方法或屬性匯出。

在另一個模組,可以通過require()引入模組,就可以使用匯出的方法sum()。

3)模組標識

模組標識其實傳遞給require()方法的引數,模組標識必須是符合駝峰命名的字串或者以./,../開頭的路徑,引入模組模組標識可以省略.js字尾。

模組的好處是將特定的方法和變數限定在特定的作用域中,使得開發者完全不必去考慮變數汙染的問題。

Node.js的模組實現

在Node.js中,有三類模組,其中一類是Node.js提供的核心模組,就比如上一篇說過的fs檔案模組,database資料庫模組,還有一類是開發者自行編寫的檔案模組,就比如剛才示例的test.js模組,第三類就是自定義模組,這是一種特殊的檔案模組,一般是一個檔案或包的形式,比如引入mysql所需的jar包。

在Node.js中引入模組,需要經歷三步:

(1)路徑分析

對於檔案模組來說,引入時模組標識指明瞭確切的檔案位置,所以在路徑分析中可以省略大量時間,載入速度僅次於核心模組。

自定義模組則是會從專案根目錄逐個比較路徑,直到找到目標模組為止。所以,自定義模組的路徑越深,路徑分析的耗時越多,所以自定義模組的載入速度是最慢的。

(2)檔案定位

剛才其實說過了,模組標識可以不包含字尾名,所以Node.js在檔案定位時會依次補充.js,.json,.node字尾名,然後去進行檔案定位,因為Node.js是單執行緒,所以檔案定位時會發生堵塞,所以如果引入的模組字尾是.json或者.node,可以在引入的時候加上字尾,可以提高查詢速度。

(3)編譯執行

定義到具體檔案後,Node.js會建立一個模組物件,然後將模組引入並且編譯。每一個編譯成功的模組其檔案路徑都會作為索引快取在快取物件上,以提高二次引入模組的效能。

核心模組在Node.js原始碼的編譯過程中,直接被編譯成二進位制檔案,然後被直接載入到記憶體中,所以核心模組引入時,檔案定位和編譯執行這兩個步驟可以直接跳過,並且核心模組在路徑分析中會被優先判斷,所以核心模組的載入速度是最快的。

檔案模組則是在執行時動態載入,所以路徑分析,檔案定位以及編譯執行這三個步驟都不可省略,所以載入速度比核心模組慢。

Node.js對引入過的模組會進行快取,以減少二次引入模組的效能開銷二次載入模組一律採用快取優先方式。核心模組的快取檢查優先於檔案模組。

包管理工具NPM

剛才說到Node模組,但是雖然我們可以引用模組,但是模組與模組之間仍然是雜湊在各地的,相互之間並不能直接引用。而Node的包管理工具NPM則將模組相互聯絡起來。包其實是在模組的基礎上進一步組織JavaScript程式碼。

其實NPM會有一個包描述檔案package.json,一般位於包的根目錄, NPM的所有行為都與包描述檔案息息相關。前面幾篇有講過NPM作為預設包管理工具,會作為Node環境被一起安裝。

NPM常用功能

NPM幫助Node完成了第三方模組的釋出,安裝和依賴。因為有NPM的存在,Node和第三方模組之間形成了很好的一個生態系統,而且逐漸越來越強大。接下來大致講解下幾個NPM常見命令

  • npm --version 檢視當前NPM的版本
  • npm 檢視幫助說明
  • npm help 檢視具體命令說明
  • 執行命令會在瀏覽器中開啟對應命令的說明文件
  • npm install 安裝依賴包,預設使用–-save引數,即預設新增到package.json中
  • 執行該命令,NPM會在當前目錄建立nodemodules目錄,然後再nodemodules建立對應依賴包的目錄,然後將依賴包解壓到該目錄。
  • npm init 在此目錄初始化生成package.json檔案
  • npm uninstall 解除安裝依賴包, 預設使用-–save引數,即從package.json中移除
  • npm ls檢視當前目錄的依賴包
  • npm root -g 檢視全域性安裝地址
  • npm list 檢視依賴的當前版本

NPM存在的問題

在NPM平臺,每個人都可以分享包,所以包質量沒有辦法保證,而且Node.js執行在服務端,所以需要考慮安全問題。所以一個優秀的模組需要符合幾大模組:

  1. 具備良好的測試
  2. 具備良好的文件
  3. 具備良好的測試覆蓋率
  4. 具備良好的程式碼規範

今天內容就到這裡了,其實這篇文章並沒有涉及到程式碼的編寫,而是從模組的角度去理解Node.js,Node.js通過模組規範,彌補了JavaSCript沒有結構性的不足,而NPM通過對包的統一管理,使得專案開發中的依賴問題得到有效解決。

下一篇將從非同步程式設計的角度帶大家繼續瞭解Node.js,下一篇再見!歡迎關注我個人公眾號:程式猿周先森file

相關文章