返回

从源码角度,解读nodejs模块

前端

从源码角度,解读nodejs模块

在nodejs中,模块是代码复用的基本单元,它可以被其他模块导入并使用,从而实现模块之间的相互调用和协作。nodejs一共有四种模块,分别是c++原生模块、native本地js模块、用户js模块、用户c++扩展。

  • c++原生模块

c++原生模块是由c++编写的,它可以直接被nodejs加载和使用。c++原生模块的加载过程是通过node::Load去调用的,在node::Load中会去创建一个node::BindingData对象,然后将这个对象传给加载模块的函数node::binding::Dlopen,最后通过dlopen去加载c++的动态库。

  • native本地js模块

native本地js模块是通过c++编写的,但它不是直接被nodejs加载和使用,而是需要先编译成js代码,然后才能被nodejs加载和使用。native本地js模块的编译过程是通过node::binding::Compile去调用的,在node::binding::Compile中会去创建一个node::BindingData对象,然后将这个对象传给编译模块的函数node::binding::CompileFile,最后通过编译器去编译c++代码生成js代码。

  • 用户js模块

用户js模块是由javascript编写的,它可以直接被nodejs加载和使用。用户js模块的加载过程是通过node::Load去调用的,在node::Load中会去创建一个node::BindingData对象,然后将这个对象传给加载模块的函数node::LoadScript,最后通过vm模块去执行js代码。

  • 用户c++扩展

用户c++扩展是通过c++编写的,它需要先编译成动态库,然后才能被nodejs加载和使用。用户c++扩展的编译过程是通过node::binding::Compile去调用的,在node::binding::Compile中会去创建一个node::BindingData对象,然后将这个对象传给编译模块的函数node::binding::CompileFile,最后通过编译器去编译c++代码生成动态库。

process.binding API

process.binding API是nodejs提供的一个用来加载c++原生模块和native本地js模块的api。process.binding API的语法如下:

process.binding(name)

其中,name是模块的名称。

process.binding API的实现原理是通过node::binding::Dlopen和node::binding::CompileFile这两个函数去加载c++原生模块和native本地js模块。

模块加载过程

模块加载过程是通过node::Load函数去调用的,在node::Load函数中会去创建一个node::BindingData对象,然后根据模块的类型将这个对象传给加载模块的相应函数,最后通过相应的函数去加载模块。

模块加载过程的具体流程如下:

  1. 创建一个node::BindingData对象。
  2. 根据模块的类型将这个对象传给加载模块的相应函数。
  3. 通过相应的函数去加载模块。

如何使用C++实现nodejs模块

可以通过以下步骤使用C++实现nodejs模块:

  1. 创建一个新的c++项目。
  2. 在项目中创建一个新的c++文件。
  3. 在c++文件中编写模块的代码。
  4. 将c++文件编译成动态库。
  5. 将动态库复制到nodejs的模块目录。
  6. 在nodejs中加载模块。

总结

本文从源码角度,解读了nodejs模块的原理,介绍了c++原生模块、native本地js模块、用户js模块、用户c++扩展四种模块的实现机制,并介绍了process.binding API,揭秘了nodejs如何加载模块以及如何使用C++实现nodejs模块。