• 深入Node.js 模块机制


    (一)简单模块的定义和使用

       定义一个计算圆形的面积和周长的模块,让我们开启node之旅

       

         将这个文件存为circle.js,并新建一个app.js文件,并写入以下代码:

         

         可以看到模块的调用非常的方便,只需要require 需要调用的文件即可


    (二)模块载入策略(重点)

      Node.js的模块分为两类

    1. 原生(核心)模块
    2. 文件模块 

      原生模块在Node.js源代码编译的时候编译进了二进制执行文件,加载的速度最快。另一类文件模块是动态加载的,加载速度比原生模块慢。但是Node.js对原生模块和文件模块都进行了缓存,于是在第二次require时,是不会有重复开销的。其中原生模块都被定义在lib这个目录下面,文件模块则不定性。

      由于通过命令行加载启动的文件几乎都为文件模块。我们从Node.js如何加载文件模块开始谈起。加载文件模块的工作,主要由原生module来实现和完成,该原生模块在启动是已经被加载,进程直接调用到runMain静态方法。

      

       _load静态方法在分析文件名之后执行

       

       并根据文件路径缓存当前模块对象,该模块实例对象则根据文件名加载。

      

      实际上在文件模块中,又分为3类模块。这三类文件模块以后缀来区分,Node.js会根据后缀名来决定加载方法。

    •  .js  通过fs模块同步读取js文件并编译执行。
    •  .node 通过C/C++ 进行编写的Addon。 通过dlopen 方法进行加载。
    •  .json 读取文件,调用JSON.parse解析加载。  

      这里我们将详细描述js后缀的编译过程。Node.js在编译js文件的过程中实际完成的步骤有对js文件内容进行头尾包装。以app.js为例,包装之后的app.js将会变成以下形式。

      

       这段代码会通过VM 原生模块 的runlnThisContext方法执行(类似eval,只是具有明确上下文,不污染全局),返回一个具体的function对象。最后传入module对象的exports,require方法,module,文件名,目录名作为实参并执行。

       这就是为什么require并没有定义在app.js文件中,但是这个方法却存在的原因!!!

       从Node.js的API文档中可以看到还有 __filename, __dirname, module , exports 几个没有定义但是却存在的变量。其中 __filename 和  __dirname在查找文件路径的过程中分析得到后传入的。 module变量是这个模块对象自身,exports是在module的构造函数中初始化的一个空对象({},而不是null)

       在这个主文件中,可以通过require方法去引入其余的模块。而其实这个require方法实际调用的就是load方法。

       load方法在载入,编译,缓存了module后,返回module的exports对象。这就是circle.js文件中只有定义在exports对象上的方法才能被外部调用的原因。

       以上所描述的模块载入机制均定义在lib/module.js中。


    (三)require方法中的文件查找策略

       由于Node.js中存在4类模块(原生模块和3中文件模块),尽管require方法及其简单,但是内部的加载却是十分复杂的,其加载优先级也各自不同。

       

        安装yarn

    npm install -g yarn --registry=https://registry.npm.taobao.org

            进军西南!!!

  • 相关阅读:
    zabbix_QQ邮件告警部署(待续。。。。。。)
    FTP服务的搭建
    项目: NFS服务的搭建
    用ngxin搭建简单的下载站点
    脚本设定开机自启动
    自建小项目:自动化脚本安装ngnix项目
    Zabbix Web操作深入(待续------)
    DHCP原理与配置
    PXE高效能网络批量装机
    DNS域名解析服务
  • 原文地址:https://www.cnblogs.com/misscai/p/11542857.html
Copyright © 2020-2023  润新知