在編譯所有C/C++文件之前,編譯程序需要將所有的JavaScript模塊文件編譯為C/C++代碼,此時是否直接將其便以為可執行代碼了呢?其實不是。
## 1.轉存為C/C++代碼
Node采用了V8附帶的js2c.py工具,將所有內置的JavaScript代碼(src/node.js和lib/*.js)轉換成C++里的數組,生成node_natives.h頭文件,相關代碼如下:
~~~
namespace node{
const char node_native[]={47,47,..};
const char dgram_native[]={47,47,..};
const char console_native[]={47,47,..};
const char buffer_native[]={47,47,..};
const char querystring_native[]={47,42,..};
...
struct _native{
const char* name;
const char* source;
size_t source_len;
};
static const struct _native natives[]={
{"node",node_native,sizeof(node_native)-1},
{"dgram",dgram_native,sizeof(dgram_native)-1},
...
};
}
~~~
在這個過程中,JavaScript代碼以字符串的形式存儲在node命名空間中,是不可直接執行的。在啟動Node進程時,JavaScript代碼直接加載進內存中。在加載的過程中,JavaScript核心模塊經歷標識符分析后直接定位到內存中,比普通的文件模塊從磁盤中一處一處查找要快很多。
## 2.編譯JavaScript核心模塊
lib目錄下的所有模塊文件也沒有定義require、module、exports這些變量。在引入JavaScript核心模塊的過程中,也經歷了頭尾包裝的過程,然后才執行和導出了exports對象。與文件模塊有區別的地方在于:獲取源碼的方式(核心模塊是從內存中加載的)以及緩存執行結果的位置。
JavaScript核心模塊的定義如下面的代碼所示,源文件通過process.binding('natives')取出,編譯成功的模塊緩存到NativeModule._cahce對象上,文件模塊則要緩存到Module._cache對象上:
~~~
function NativeModule(id){
this.filename = id + '.js';
this.id = id;
this.exports = {};
this.loaded = false;
}
NativeModule._source=process.binding('natives');
NativeModule._cache = {};
~~~
- 目錄
- 第1章 Node 簡介
- 1.1 Node 的誕生歷程
- 1.2 Node 的命名與起源
- 1.2.1 為什么是 JavaScript
- 1.2.2 為什么叫 Node
- 1.3 Node給JavaScript帶來的意義
- 1.4 Node 的特點
- 1.4.1 異步 I/O
- 1.4.2 事件與回調函數
- 1.4.3 單線程
- 1.4.4 跨平臺
- 1.5 Node 的應用場景
- 1.5.1 I/O 密集型
- 1.5.2 是否不擅長CPU密集型業務
- 1.5.3 與遺留系統和平共處
- 1.5.4 分布式應用
- 1.6 Node 的使用者
- 1.7 參考資源
- 第2章 模塊機制
- 2.1 CommonJS 規范
- 2.1.1 CommonJS 的出發點
- 2.1.2 CommonJS 的模塊規范
- 2.2 Node 的模塊實現
- 2.2.1 優先從緩存加載
- 2.2.2 路徑分析和文件定位
- 2.2.3 模塊編譯
- 2.3 核心模塊
- 2.3.1 JavaScript核心模塊的編譯過程
- 2.3.2 C/C++核心模塊的編譯過程
- 2.3.3 核心模塊的引入流程
- 2.3.4 編寫核心模塊
- 2.4 C/C++擴展模塊
- 2.4.1 前提條件
- 2.4.2 C/C++擴展模塊的編寫
- 2.4.3 C/C++擴展模塊的編譯
- 2.4.2 C/C++擴展模塊的加載
- 2.5 模塊調用棧
- 2.6 包與NPM
- 2.6.1 包結構
- 2.6.2 包描述文件與NPM
- 2.6.3 NPM常用功能
- 2.6.4 局域NPM
- 2.6.5 NPM潛在問題
- 2.7 前后端共用模塊
- 2.7.1 模塊的側重點
- 2.7.2 AMD規范
- 2.7.3 CMD規范
- 2.7.4 兼容多種模塊規范
- 2.8 總結
- 2.9 參考資源
- 第3章 異步I/O
- 3.1 為什么要異步I/O
- 3.1.1 用戶體驗
- 3.1.2 資源分配
- 3.2 異步I/O實現現狀
- 3.2.1 異步I/O與非阻塞I/O
- 3.2.2 理想的非阻塞異步I/O
- 3.2.3 現實的異步I/O
- 3.3 Node的異步I/O
- 3.3.1 事件循環
- 3.3.2 觀察者
- 3.3.3 請求對象
- 3.3.4 執行回調
- 3.3.5 小結
- 3.4 非I/O的異步API
- 3.4.1 定時器
- 3.5 事件驅動與高性能服務器