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 相关文章推荐
Ubuntu中搭建Nodejs开发环境过程分享
Jun 01 NodeJs
NodeJS中利用Promise来封装异步函数
Feb 25 NodeJs
用NodeJS实现批量查询地理位置的经纬度接口
Aug 16 NodeJs
NodeJS远程代码执行
Aug 28 NodeJs
Express与NodeJs创建服务器的两种方法
Feb 06 NodeJs
nodejs中使用HTTP分块响应和定时器示例代码
Mar 19 NodeJs
详解nodejs操作mongodb数据库封装DB类
Apr 10 NodeJs
使用vs code开发Nodejs程序的使用方法
Sep 21 NodeJs
Mac 安装 nodejs方法(图文详细步骤)
Oct 30 NodeJs
nodejs实现的连接MySQL数据库功能示例
Jan 25 NodeJs
Nodejs 和 Electron ubuntu下快速安装过程
May 04 NodeJs
nodejs微信开发之自动回复的实现
Mar 17 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数组是否为索引数组的实现方法
2013/06/13 PHP
PHP中模糊查询并关联三个select框
2017/06/19 PHP
jQuery live
2009/05/15 Javascript
jQuery 锚点跳转滚动条平滑滚动一句话代码
2010/04/30 Javascript
Javascript 检测键盘按键信息及键码值对应介绍
2013/01/03 Javascript
jquery获得同源iframe内body下标签的值的方法
2014/09/25 Javascript
js实现上传图片预览的方法
2015/02/09 Javascript
jQuery幻灯片特效代码分享--鼠标滑过按钮时切换(2)
2020/11/18 Javascript
使用jquery插件qrcode生成二维码
2015/10/22 Javascript
一个简单不报错的summernote 图片上传案例
2016/07/11 Javascript
JavaScript 实现 Tab 点击切换实例代码
2017/03/25 Javascript
Angular实现预加载延迟模块的示例
2017/10/12 Javascript
浅谈webpack打包之后的文件过大的解决方法
2018/03/07 Javascript
不使用JavaScript实现菜单的打开和关闭效果demo
2018/05/01 Javascript
解决vue数组中对象属性变化页面不渲染问题
2018/08/09 Javascript
Vue打包后访问静态资源路径问题
2019/11/08 Javascript
vue随机验证码组件的封装实现
2020/02/19 Javascript
[02:43]中国五虎出征TI3视频
2013/08/02 DOTA
[09:13]2014DOTA2国际邀请赛 中国区预选赛coser表演
2014/05/23 DOTA
[49:20]VG vs TNC Supermajor小组赛B组败者组决赛 BO3 第二场 6.2
2018/06/03 DOTA
Python ValueError: invalid literal for int() with base 10 实用解决方法
2015/06/21 Python
Python采用Django开发自己的博客系统
2020/09/29 Python
Python3中使用PyMongo的方法详解
2017/07/28 Python
python保留小数位的三种实现方法
2020/01/07 Python
Python 基于FIR实现Hilbert滤波器求信号包络详解
2020/02/26 Python
python 瀑布线指标编写实例
2020/06/03 Python
python线程里哪种模块比较适合
2020/08/02 Python
python 实现弹球游戏的示例代码
2020/11/17 Python
南非最受欢迎的时尚品牌:MRP
2016/09/18 全球购物
万得城电器土耳其网站:欧洲第一大电子产品零售商
2016/10/07 全球购物
欧尚俄罗斯网上超市:Auchan俄罗斯
2018/05/03 全球购物
JAVA招聘远程笔试题
2015/07/23 面试题
中文专业毕业生自荐书范文
2014/01/04 职场文书
初中生操行评语大全
2014/04/24 职场文书
党员学习群众路线教育实践活动对照检查材料
2014/09/23 职场文书
Python识别花卉种类鉴定网络热门植物并自动整理分类
2022/04/08 Python