Nodejs模块载入运行原理


Posted in NodeJs onFebruary 23, 2018

前言

使用Nodejs,就不可避免地引用第三方模块,它们有些是Nodejs自带的(例:http,net...),有些是发布在npm上的(例:mssql,elasticsearch...)

本篇章聚焦3个问题:

  1. Nodejs模块的加载过程。
  2. 应用启动的过程。
  3. 应用如何加载依赖模块。

1.模块的加载过程

Nodejs 模块大概可分为4种:

a) builtin module Nodejs中以C++形式提供的模块。

b) constant module Nodejs中定义常量的模块。

c) native module Nodejs中以javascript形式提供的模块。

d) 第三方module 由第三方提供的模块。

我们先看builtin module 和 native module的生成过程。

Nodejs模块载入运行原理

native JS module的生成相对复杂一些,编译后,会在/out/release/obj/gen目录下生成一个node_natives.h。

该文件是由js2c.py生成,它会把Nodejs源码中的lib目录下,所有js文件转成ASCII码,并存放在相应的数组里。

Nodejs模块载入运行原理

builtin C++ module 生成过程相对简单,每个builtin C++的模块入口,都会通过宏NODE_MODULE_CONTEXT_AWARE_BUILTIN扩展成一个func,例如对tcp_wrap模块而言,会扩展成static void register_tcp_wrap() attribute(constructor) 函数。

熟悉GCC的朋友都知道,attribute(constructor)修饰的函数会在Nodejs的main()函数之前被执行,也就是说,builtin C++ module 会在main()函数之前被载入到modlist_builtin列表,而modlist_builtin是一个struct node_module类型的指针,get_builtin_module()会遍历查找我们所需的模块。

其实无论是naive JS module 还是 builtin C++ module,最终都是要被编译成可执行文件。对于两者的提取方式,却大不相同,js module 使用process.binding('natives'),而C++ module 则直接使用get_builtin_module()。

在node.cc里面提供了一个binding()函数,当我们应用require()来引用另外一个模块时,binding()函数便会被引入。下面我们分析一下这个函数:

Nodejs模块载入运行原理

可以目测到,函数主要为三个模块服务:builtin,constants和native。

builtin优先级最高,会到modlist_builtin中查找,过程非常简单,遍历整个列表,查找相同名字的模块即可。找到后,模块的注册函数会被先执行,然后将数据exports返回。

constants模块优先级次之,Nodejs中的常量定义通过constants导出。

native 优先级最低。

2.应用启动的过程

Nodejs模块载入运行原理

上图为一个流程图,它描述了test.js做为参数启动开始,最终被执行。整个过程可以分为4步:

1.可执行文件 node : node入口,在启动过程中主要扮演环境准备工作

2.src/node.js:启动脚本

3.Native Module:为module.js 的执行做准备工作

4.module.js:native module,用来加载,编译,执行应用程序

应用如何加载依赖模块

前面提到NativeModule.require()只负责帮助引用natives module,这对于lib/module.js而言已经足够了。

但是很明显,一般应用不但需要引用matives module,还要引用第三方模块,让我们看一下module.js中的Module.prototype._require()函数中。

Nodejs模块载入运行原理

NodeJs 相关文章推荐
nodejs开发微博实例
Mar 25 NodeJs
Nodejs初级阶段之express
Nov 23 NodeJs
NodeJS与HTML5相结合实现拖拽多个文件上传到服务器的实现方法
Jul 26 NodeJs
nodejs如何获取时间戳与时间差
Aug 03 NodeJs
nodeJs链接Mysql做增删改查的简单操作
Feb 04 NodeJs
详解nodeJS中读写文件方法的区别
Mar 06 NodeJs
搭建简单的nodejs http服务器详解
Mar 09 NodeJs
详解nodejs微信公众号开发——1.接入微信公众号
Apr 10 NodeJs
nodejs前端模板引擎swig入门详解
May 15 NodeJs
NodeJs 实现简单WebSocket即时通讯的示例代码
Aug 05 NodeJs
Nodejs封装类似express框架的路由实例详解
Jan 05 NodeJs
通过实例了解Nodejs模块系统及require机制
Jul 16 NodeJs
Nodejs下使用gm圆形裁剪并合成图片的示例
Feb 22 #NodeJs
nodejs微信扫码支付功能实现
Feb 17 #NodeJs
nodejs+express搭建多人聊天室步骤
Feb 12 #NodeJs
nodeJs实现基于连接池连接mysql的方法示例
Feb 10 #NodeJs
NodeJS简单实现WebSocket功能示例
Feb 10 #NodeJs
nodejs使用redis作为缓存介质实现的封装缓存类示例
Feb 07 #NodeJs
nodejs中Express与Koa2对比分析
Feb 06 #NodeJs
You might like
PHP句法规则详解 入门学习
2011/11/09 PHP
PHP递归调用的小技巧讲解
2013/02/19 PHP
深入理解PHP变量的值类型和引用类型
2015/10/21 PHP
Laravel5.4简单实现app接口Api Token认证方法
2019/08/29 PHP
php实现根据身份证获取精准年龄
2020/02/26 PHP
jQuery 事件队列调整方法
2009/09/18 Javascript
老鱼 浅谈javascript面向对象编程
2010/03/04 Javascript
jQuery表单验证插件formValidator(改进版)
2012/02/03 Javascript
javascript 获取元素样式必杀技
2014/05/04 Javascript
基于NodeJS的前后端分离的思考与实践(三)轻量级的接口配置建模框架
2014/09/26 NodeJs
原生javascript实现分享到朋友圈功能 支持ios和android
2016/05/11 Javascript
JavaScript 实现的checkbox经典实例分享
2016/10/16 Javascript
Vue.JS入门教程之事件监听
2016/12/01 Javascript
jQuery实现简单的回到顶部totop功能示例
2017/10/16 jQuery
原生JS实现$.param() 函数的方法
2018/08/10 Javascript
解决jquery有正确返回值但不执行success函数的问题
2018/08/20 jQuery
使用webpack搭建pixi.js开发环境
2020/02/12 Javascript
微信小程序基于高德地图API实现天气组件(动态效果)
2020/10/22 Javascript
详解Python使用simplejson模块解析JSON的方法
2016/03/24 Python
利用Python实现图书超期提醒
2016/08/02 Python
python使用opencv读取图片的实例
2017/08/17 Python
用python的turtle模块实现给女票画个小心心
2019/11/23 Python
python飞机大战 pygame游戏创建快速入门详解
2019/12/17 Python
Pycharm内置终端及远程SSH工具的使用教程图文详解
2020/03/19 Python
Pycharm配置PyQt5环境的教程
2020/04/02 Python
详解python中GPU版本的opencv常用方法介绍
2020/07/24 Python
CSS3动画之流彩文字效果+图片模糊效果+边框伸展效果实现代码合集
2017/08/18 HTML / CSS
申报职称专业技术个人的自我评价
2013/12/12 职场文书
企业党员公开承诺书
2014/03/26 职场文书
2014年物业管理工作总结
2014/11/21 职场文书
夫妻分居协议书范本
2014/11/28 职场文书
公司禁烟通知
2015/04/23 职场文书
卫生院艾滋病宣传活动总结
2015/05/09 职场文书
新郎新娘致辞
2015/07/31 职场文书
入党积极分子培养联系人意见
2015/08/12 职场文书
德生BCL3000抢先使用感受和评价
2022/04/07 无线电