abbshr.github.io
abbshr.github.io copied to clipboard
动手实现一个Custom-Node.js
了解Node.js的运行机理之后就有能力对其进行custom了,我们可以尝试着DIY一个node-v0.10.31.(1)
涉及源码
-
node.gyp
: Node.js构建编译所用配置文件 -
lib/
我要custom那些东西呢? 我尚未拜读v8的API,况且C++水平略渣,因此暂且不理会deps
和src/*.cc
这两个目录,从最贴近现实处入手: lib/
和src/node.js
.
修改src/node.js
最合适不过了,因为这是官方推荐的自定义Node核心功能的方法.其实还可以扩充Node的JavaScript核心模块组,我这次玩的就是这个.
我向lib目录里添加了read.i
和websocket
,这两个是我之前写的Node扩展模块,这次把他们跟Node核心模块整合,哈哈.
read.i用于增强Node.js的接受用户输入的能力, websocket用于扩展Node.js的应用层协议,提供websocket协议支持.
添加核心模块
准备read.i的源码read.i.js
,拷贝到lib目录下. 既然read是提供读取,我们不妨让他使用的便捷一些:
// 这里我修改了src/node.js中初始化全局变量的函数
// 将read.i模块添加到gloabl变量中
startup.globalVariables = function() {
global.process = process;
global.global = global;
global.GLOBAL = global;
global.root = global;
global.Buffer = NativeModule.require('buffer').Buffer;
process.binding('buffer').setFastBufferConstructor(global.Buffer);
process.domain = null;
process._exiting = false;
// 添加read变量
global.read = NativeModule.require('read');
};
ok,编译一下
./configure
sudo make && ./node
然后你惊讶的发现报错了是吧,Node根本没找到你的模块! 原因是你并没有在node.gyp
中添加新的模块,下面修改以下node.gyp:
{
'variables': {
'v8_use_snapshot%': 'true',
'node_use_dtrace%': 'false',
'node_use_etw%': 'false',
'node_use_perfctr%': 'false',
'node_has_winsdk%': 'false',
'node_shared_v8%': 'false',
'node_shared_zlib%': 'false',
'node_shared_http_parser%': 'false',
'node_shared_cares%': 'false',
'node_shared_libuv%': 'false',
'node_use_openssl%': 'true',
'node_use_systemtap%': 'false',
'node_shared_openssl%': 'false',
'library_files': [
'src/node.js',
'lib/_debugger.js',
'lib/_linklist.js',
'lib/assert.js',
'lib/buffer.js',
'lib/child_process.js',
'lib/console.js',
'lib/constants.js',
'lib/crypto.js',
'lib/cluster.js',
'lib/dgram.js',
'lib/dns.js',
'lib/domain.js',
'lib/events.js',
'lib/freelist.js',
'lib/fs.js',
'lib/http.js',
'lib/https.js',
'lib/module.js',
'lib/net.js',
'lib/os.js',
'lib/path.js',
'lib/punycode.js',
'lib/querystring.js',
'lib/readline.js',
'lib/repl.js',
'lib/stream.js',
'lib/_stream_readable.js',
'lib/_stream_writable.js',
'lib/_stream_duplex.js',
'lib/_stream_transform.js',
'lib/_stream_passthrough.js',
'lib/string_decoder.js',
'lib/sys.js',
'lib/timers.js',
'lib/tls.js',
'lib/tty.js',
'lib/url.js',
'lib/util.js',
'lib/vm.js',
'lib/zlib.js',
# 这里添加新的模块路径
'lib/read.js',
],
},
....
....
}
再次编译,执行./node
,就能调用我们的read
模块了,同时也可以直接使用,当然这个模块在REPL环境中是无效的,仅作用于普通模式.
下面添加websocket模块.过程类似,只不过我的这个模块是由多个相互依赖的文件组成.
注: 每个通过require或NativeModule.require的模块,其文件必须首先添加进node.gyp的library_files子节点下.并且在Node编译时,会将这个节点数组中所有文件均编译成独立的核心模块!
因此,如果有多个依赖的话,就一个不剩的添加到node.gyp里,经过编译之后,这些模块的名称就是它的文件名.所以不能有两个index.js
,在添加时一定要注意.
然后修改依赖文件和主文件中的require
,把所有require的文件路径统统改成模块的文件名(不包含扩展名). like this:
var utils = require('index');
var Client = require('client');
var datarecv_handler = require('datarecv_handler');
经过编译,我们的node-v10.31.1私人定制版就新鲜出炉了.
当然,除了添加模块之外还有好多事可以做,比如修改模块加载方式,Node的运行模式等等.