美文网首页
3、node的核心模块

3、node的核心模块

作者: 萘小蒽 | 来源:发表于2019-07-23 09:46 被阅读0次

    JavaScript核心模块的编译过程;

    在编译所有C/C++文件之前,编译程序需要将所有的JavaScript模块文件编译为C/C++代码,此时编译完成的代码还不可执行。

    1. 转存为C/C++代码
    Node采用了V8附带的js2c.py工具,将所有内置的JavaScript代码(src/node.jslib/*.js)转换成C++里的数组,生成node_natives.h文件。
    在这个过程中,JavaScript代码以字符串的形式存储在node命名空间中,是不可直接执行的。

    2. 编译JavaScript核心模块
    lib目录下的所有模块文件也没有定义require、module、exports这些变量,在引入JavaScript核心模块的过程中,也经历了头尾包装的过程,然后执行和导出了export对象。

    与文件模块的区别在于获取源代码的方式(核心模块是从内存中加载的)以及缓存执行结果的位置。

    JavaScript核心模块定义如下所示:

    function NativeModule(id){
        this.filename = id + '.js';
        this.id = id;
        this.exports = {};
        this.loaded = false;
    }
    NativeModule._source = process.binding('native');
    NativeModule._cache = {};
    

    源文件通过process.binding('native')取出,编译成功的模块缓存到NativeModule._cache对象上,文件模块则缓存到Module._cache对象上。


    C/C++核心模块的编译过程

    在核心模块中,有些模块全部由C/C++编写,有些模块则由C/C++完成核心部分,其他由JavaScript实现包装或向外导出,以满足性能需求。

    C++模块主内完成核心,JavaScript主外实现封装的模式是node能够提高性能的常见方式。

    C/C++编写的部分统一称为内建模块,通常不能被用户直接调用。比如buffer、crypto、evals、fs、os都是部分由C/C++编写的。

    2. 内建模块的优势

    1. 它们本身由C/C++编写,性能上优于脚本语言;
    2. 在进行文件编译时,它们被编译进二进制文件,一旦Node开始执行,它们被直接加载进内存中,无需再次做标识符定位。

    3. 模块之间的依赖
    Node的所有模块类型中,存在一种依赖层级关系,文件模块可能会依赖核心模块,核心模块可能会依赖内建模块。

    Node模块依赖

    通常不推荐直接调用内建模块,如果需要,直接调用核心模块即可,因为核心模块中基本都封装了内建模块。

    4. 内建模块的导出
    Node在启动时,会生成一个全局变量process,并提供Binding()方法来协助加载内建模块。(Binding()的实现代码在src/node.cc中)。

    加载内建模块时,先创建一个exports空对象,然后调用get_builtin_module()方法去除内建模块对象,通过register_func()填充exports对象,最后exports对象按模块名缓存,并返回给调用方完成导出。

    核心模块的引入流程

    从下图可以看出核心模块的引入流程,它要经历C/C++层面的内建模块定义、(JavaScript)核心模块的自定义和引入以及(JavaScript)文件模块层面引入。

    os原生模块的引入流程

    相关文章

      网友评论

          本文标题:3、node的核心模块

          本文链接:https://www.haomeiwen.com/subject/kkookctx.html