首發於 搞起博客node
nodejs中以模塊來組織代碼,加載模塊是怎樣的一個過程呢?require又是怎麼在運做?json
nodejs中以模塊爲最小單位來組織代碼,相似於Java中的package概念,而在nodejs中要搞清楚模塊,就要搞清楚模塊是怎麼樣加載的。數組
咱們都知道加載一個模塊是使用require函數來實現的,那麼先從require函數下手。緩存
咱們從module.js裏找,發現有個require方法,Module.prototype.require
。app
Module.prototype.require = function(path) { assert(path, 'missing path'); assert(util.isString(path), 'path must be a string'); return Module._load(path, this); };
經過路徑加載一個模塊。
方法註釋上給出以下解釋:函數
從緩存中查找所要加載的模塊
1. 若是一個模塊已經存在於緩存中:直接返回它的exports對象
2. 若是模塊是一個本地模塊,調用'NativeModule.require()'方法,filename做爲參數,並返回結果
3. 不然,使用這個文件建立一個新模塊並把它加入緩存中。在加載它只會返回exports對象。源碼分析
而一般咱們在某個模塊中給出的路徑都是一個模塊的相對路徑,那麼會先調用Module._resolveFilename
這個方法來查找下這個文件的真實路徑的全路徑文件名。ui
而在Module._resolveFilename
這個方法中,首先會去檢查,本地模塊是否有這個模塊,若是有,直接返回,若是沒有,繼續往下查找。this
接着就會碰到Module._resolveLookupPaths
方法了,從代碼來看,他返回了一個數組,數組的第一個元素是模塊的id,而第二個元素是模塊的paths。prototype
這些paths接下來會用來查找是否存在須要require的這個模塊了,存在就會返回一個文件名。
而接下來經過這個filename來到Module._cache
中查找是否,有則返回module.exports
對象,沒有緩存則又會查找一次本地模塊,不存在這個本地模塊,就新建立一個模塊,並在cache中緩存它。這就是咱們加載了一個模塊以後,第二次在別處加載時也不會從新加載的緣由。
而在建立模塊以後,還有個裝載的過程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/
到這裏一個模塊基本上已經加載完成了。