这一小节紧接模块实现,重点解释Node.js的核心模块(built-in modules)是什么、怎么分类、为什么特殊,以及它们在require时的优先级和实现方式。核心模块是Node区别于浏览器JS的关键之一,提供底层能力(如文件系统、网络、进程等),让Node能做服务器端开发。
原书这一小节不长,但信息密度高,朴灵作者强调:核心模块在require时优先级最高,并且部分是预编译成二进制的,加载速度极快。
详细讲解
核心模块的引入背景
在CommonJS规范下,模块分为用户模块(我们写的文件)和核心模块。Node为了提供标准库(如Java、Python有),实现了大量核心模块。require('fs')、require('http') 等就是核心模块。
核心模块的分类
朴灵作者将核心模块分为两类(书中有图示):
-
用JavaScript实现的(纯JS核心模块):
- 源码在Node项目的 lib目录 下(如 lib/fs.js、lib/http.js、lib/util.js)。
- 这些模块加载时像普通JS模块一样编译,但因为是内置的,优先从内存加载。
- 例子:util、events、path、stream 等。
-
用C/C++实现的(绑定模块,或内置模块):
- 源码在Node项目的 src目录 下(如 src/fs.cc、src/node_http.cc)。
- 这些涉及底层系统调用(如文件I/O、网络),用C++绑定V8和libuv。
- 编译Node二进制时,这些C++代码被编译进node.exe,启动时直接可用。
- 例子:fs(文件系统)、net(TCP)、http(解析器部分)、buffer、crypto 等。
此外,还有一种混合型:入口是JS,但内部调用C++绑定(如http模块的lib/http.js 调用 src/node_http.cc)。
核心模块的加载过程
- 在路径分析阶段,如果标识符是核心模块名(如'fs'),直接从内置列表加载。
- 预编译:C++部分在Node编译时已转为二进制,JS部分在Node启动时转为V8字节码(或直接执行)。
- 优势:加载极快、无需磁盘I/O、跨平台一致。
书里提到一个关键点:核心模块的JS部分也经过“模块编译”包裹,但它们在Node源码中用 NativeModule 机制管理(源码中的 node.cc 和 module.cc)。
为什么区分核心模块?
- 性能:底层操作用C++更快。
- 稳定性:核心API统一。
- 生态:用户模块和npm包构建在其上。
这一小节结尾过渡到下一节:有些性能瓶颈,核心模块不够时,可以自己写C++扩展模块。