核心模塊被編譯進二進制文件需要遵循一定的規則。作為Node的使用者,盡管幾乎沒有機會參與核心模塊的開發,但是了解如何開發核心模塊有助于我們更加深入的了解Node。
核心模塊中的JavaScript部分幾乎與文件模塊的開發一樣,遵循CommonJS模塊規范,上下文中除了擁有require、module、exports外,還可以調用Node中的一些全局變量,這里不做描述。
下面我們以C/C++模塊為例演示如何編寫內建模塊。為了便于理解,我們先編寫一個極其簡單的JavaScript版本的原型,這個方法返回一個Hello World! 字符串:
~~~
exports.sayHello = ()=>{
console.log('Hello World!');
};
~~~
編寫內建模塊通常分兩步完成:編寫頭文件和編寫C/C++文件。
(1).將以下代碼保存為node_hello.h,存放到Node的src目錄下:
~~~
#ifndef NODE_HELLO_H_
#define NODE_HELLO_H_
#include <v8.h>
namespace node{
//預定義方法
v8::Handle<v8::Value> SayHello(const v8::Arguments& args);
}
#endif
~~~
(2).編寫node_hello.cc,并存儲到src目錄下:
~~~
#include <node.h>
#include <node_hello.h>
#include <v8.h>
namespace node{
using namespace v8;
//實現預定義的方法
Handle<Value> SayHello(const Arguments& args){
HandleScope scope;
return scope.Close(String::New("Hello World!"));
}
//給傳入的目標對象添加sayHello方法
void Init_Hello(Handle<Object> target){
target=>Set(String::NewSymbol("sayHello"),FunctionTemplate::New(sayHello)->GetFunction());
}
}
//調用NODE_MODULE()將注冊方法定義到內存中
NODE_MODULE(node_hello, node::Init_Hello)
~~~
以上兩步完成了內建模塊的編寫,但是真正要讓Node認為它是內建模塊,還需要更改`src/node_extensions.h`,在`NODE_EXT_LIST_END`前添加`NODE_EXT_LIST_ITEM(node_hello)`,以將`node_hello`模塊添加到`node_module_list`數組中。
其次,還需要讓編寫的兩份代碼編譯進執行文件,同時需要更改Node的項目生成文件node.gyp,并在'target_name':'node'節點的sources中添加上新編寫的兩個文件。然后編譯整個Node項目,具體的編譯步驟請參見附錄A。
編譯和安裝后,直接在命令行中運行以下代碼,將會得到期望的效果:
~~~
$ node
> var hello =process.binding('hello');
undefined
>hello.sayHello();
'Hello World!'
>
~~~
至此,原生編寫過程中需要注意的細節都已表述過了。可以看出,簡單的模塊通過JavaScript來編寫可以大大提高生產效率。這里我們寫作本書的目的是希望有能力的讀者可以深入Node的核心模塊,去學習它或者改進它。
- 目錄
- 第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 事件驅動與高性能服務器