node加載模塊步驟:node
1) 路徑分析 (如判斷是否是核心模塊、是絕對路徑仍是相對路徑等)c++
2) 文件定位 (文件擴展名分析, 目錄和包處理等細節)json
3) 編譯執行 數組
原生模塊加載順序緩存
1) 緩存app
2) 本地原生模塊函數
1) 緩存ui
2) 若是是絕對路徑, 則直接按路徑讀取並編譯spa
3) 若是是「/」則直接從/node_modules目錄查找code
4) 若是是相對路徑, 則生成以下查詢規則,
[ '/home/myapp/mydir/node_module', '/home/myapp/node_module' '/home/node_module', '/node_module' ]
5) 從上述數組中取出第一個目錄做爲查找對象, 若是存在結束查找
6) 而後依次嘗試添加.js、.json、.node後綴繼續查找, 若是存在則結束
7) 嘗試將require參數做爲一個包查找, 讀取目錄下的package.json文件, 取得main參數指定的文件
8) 根據指定的文件未找到, 若是沒有,執行第6步
9) 若是main參數不存在或者第8步未找到, 則查找該目錄下index文件, 若是沒有, 執行第6步
10) 若是依然沒有找到, 則開始取出數組第二條路徑, 而後執行5-7步。 直到數組中最後一個值
11) 若是還沒找到, 拋出異常
至此, 文件終於找到了。。。而後呢?找到後該作什麼呢?
也許有的人早就發現一個問題, require函數是哪裏來的呢?模塊中明明沒有定義啊, 爲何就能使用了呢?
有的同窗立刻回答說, 它是個全局的。。。全局的?那這個所謂全局的又在哪定義的呢? 額。。。不知道。。。
require到底哪裏來的呢?
上面咱們已經通過重重困難終於找到了咱們的文件, 下一步就是咱們的編譯
node針對不一樣後綴的文件分類編譯
1) .js文件的編譯
.js文件的編譯源碼比較複雜, 其最終編譯後會包裝成以下結構
(function (exports, require, module, __filename, __dirname) { var math = require('math'); exports.area = function(radius) { return Math.PI * radius * radius; } })
如今知道爲何有require, exports, module這些函數或對象了吧。。。
2) .json文件的編譯
.json的文件最爲簡單, 其實就是調用JSON.parse。下爲node源碼
Module._extensions['.json'] = function(module, filename) { var content = fs.readFileSync(filename, 'utf8'); try { module.exports = JSON.parse(internalModule.stripBOM(content)); } catch (err) { err.message = filename + ': ' + err.message; throw err; } };
3) .node文件的編譯
.node是c/c++模塊, 在此不深究, 附上源碼
Module._extensions['.node'] = function(module, filename) { return process.dlopen(module, path._makeLong(filename)); };