node.js中的模組實現原理

夜雨隨風發表於2018-09-18

起源

javascript當初被設計出來用於瀏覽器,js的能力大小取決於執行環境對於api的支援能力。在web的發展中,瀏覽器中出現了更多標準api,但是後端javascript規範卻遠遠落後。對於javscsript語言而言, 它薄弱環節是缺少規範:

  • 沒有模組系統
  • 標準庫少
  • 沒有標準介面
  • 缺乏包管理系統

commonJS規範的提出,主要是彌補了js沒有標準的缺陷,以具備開發大型應用的基礎能力,而不是停留在小型指令碼的處境。在發展中,commonJS的成長中,規範涵蓋了模組、二進位制、buffer、字符集編碼、i/o流、程式環境、檔案系統、套接字、單元測試、tcp/ip、包管理等。

commonJS規範

  • 模組引用:使用require()引用一個模組
  • 模組定義:在模組中,上下文提供require()引入外部模組,匯入相應功能。上下文提供了export()方法匯出當前模組的方法或者變數。並且這是唯一到匯出出口。模組中還存在一個module物件。他代表模組自身,export是module的屬性。在node中,一個檔案就是一個模組
  • 模組標示:模組標示就是傳遞給require()的引數,內部模組可以是駝峰字串,自己寫的模組可以使相對路徑和絕對路徑,可以忽略字尾名。

Node的模組實現

先上圖:

node.js中的模組實現原理
首先判斷引用的模組是否是核心模組。如果是,則直接使用。因為核心模組在node啟動時就已經載入進了記憶體中。如果非核心模組,則為檔案模組。引用檔案模組首先會查詢快取中是否存在,如果存在就直接執行。若不存在,則會對require中傳入的識別符號進行地址補全,轉化成絕對路徑,再依次新增.js/.node/.json進行讀取嘗試。

如果目標檔案為json,會通過JSON.parse()轉化後返回。 如果目標檔案為.node,會通過dlopen()方法進行載入。 如果目標檔案為.js,先在讀取的檔案字串首尾依次拼接(function(){}),目的是解析執行時為模組程式碼新增一個封閉作用域。然後呼叫vm原生模組的runInThisContext()方法執行。返回一個具體的function物件。不會汙染全域性。最後call()執行。

相關文章