Node.js模塊加載過程module.js源碼閱讀

首發於 搞起博客node

引言

nodejs中以模塊來組織代碼,加載模塊是怎樣的一個過程呢?require又是怎麼在運做?json

模塊

nodejs中以模塊爲最小單位來組織代碼,相似於Java中的package概念,而在nodejs中要搞清楚模塊,就要搞清楚模塊是怎麼樣加載的。數組

源碼分析

咱們都知道加載一個模塊是使用require函數來實現的,那麼先從require函數下手。緩存

1.Module.prototype.require

咱們從module.js裏找,發現有個require方法,Module.prototype.requireapp

Module.prototype.require = function(path) {
  assert(path, 'missing path');
  assert(util.isString(path), 'path must be a string');
  return Module._load(path, this);
};

2.Module._load

經過路徑加載一個模塊。
方法註釋上給出以下解釋:函數

從緩存中查找所要加載的模塊
1. 若是一個模塊已經存在於緩存中:直接返回它的exports對象
2. 若是模塊是一個本地模塊,調用'NativeModule.require()'方法,filename做爲參數,並返回結果
3. 不然,使用這個文件建立一個新模塊並把它加入緩存中。在加載它只會返回exports對象。源碼分析

3.Module._resolveFilename

而一般咱們在某個模塊中給出的路徑都是一個模塊的相對路徑,那麼會先調用Module._resolveFilename這個方法來查找下這個文件的真實路徑的全路徑文件名。ui

而在Module._resolveFilename這個方法中,首先會去檢查,本地模塊是否有這個模塊,若是有,直接返回,若是沒有,繼續往下查找。this

4.Module._resolveLookupPaths

接着就會碰到Module._resolveLookupPaths方法了,從代碼來看,他返回了一個數組,數組的第一個元素是模塊的id,而第二個元素是模塊的paths。prototype

這些paths接下來會用來查找是否存在須要require的這個模塊了,存在就會返回一個文件名。

而接下來經過這個filename來到Module._cache中查找是否,有則返回module.exports對象,沒有緩存則又會查找一次本地模塊,不存在這個本地模塊,就新建立一個模塊,並在cache中緩存它。這就是咱們加載了一個模塊以後,第二次在別處加載時也不會從新加載的緣由。

5.Module.load

而在建立模塊以後,還有個裝載的過程Module.load,裝載的過程當中會將幾種擴展名的文件執行不一樣的操做:
* .js Module._complie,運行這個js幷包裹在適當的做用域中,並傳入參數require, module, exports
* .json 讀文件以後,使用JSON.parse轉成對象
* .node 使用process.dlopen加載擴展

若是js文件中包含模塊引用,那麼還會繼續重複以上操做的。

這裏會try catch一下,若是裝載失敗,就會從cache中將這個模塊刪除。

try {
    module.load(filename);
    hadException = false;
  } finally {
    if (hadException) {
      delete Module._cache[filename];
    }
  }

熱部署

這裏的細節給了咱們一個思路,即當咱們程序運行時,加載了某個模塊,而咱們可能在運行過程當中修改了代碼,或者是從新部署了代碼,那麼咱們能夠經過先刪除cache中的內容,再加載一次,來實現動態加載,也能夠說是熱部署。
具體的作法能夠參考這個文章 http://fex.baidu.com/blog/2015/05/nodejs-hot-swapping/

到這裏一個模塊基本上已經加載完成了。

相關文章
相關標籤/搜索