1. Js 常见模块机制

  • AMD: 异步加载,推崇依赖前置、提前执行。相关库: require.js
  • CMD: 异步加载,推崇依赖就近、延迟执行。此规范其实是在sea.js推广过程中产生的。
  • Commonjs: Node.js是commonJS规范的主要实践者,它有四个重要的环境变量为模块化的实现提供支持:module、exports、require、global。实际使用时,用module.exports定义当前模块对外输出的接口(不推荐直接用exports),用require加载模块。
  • ES6 Module:编译时就引入模块代码(非Object),而不是在代码运行时加载,所以无法实现条件加载。支持静态分析

    2. ES6 模块与 CommonJS 模块的差异

  1. CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
  2. CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。

    3. NodeJs 模块加载机制

    image.png

4.Nodejs 模块

  • builtin module Nodejs中以C++形式提供的模块。
  • constant module Nodejs中定义常量的模块。
  • native module Nodejs中以javascript形式提供的模块。
  • 第三方module 由第三方提供的模块。

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

image.png

native JS module的生成相对复杂一些,编译后,会在/out/release/obj/gen目录下生成一个node_natives.h。
该文件是由js2c.py生成,它会把Nodejs源码中的lib目录下,所有js文件转成ASCII码,并存放在相应的数组里。
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()。

参考文章:
前端模块化:CommonJS,AMD,CMD,ES6
深入浅出 NodeJs 模块机制
require() 源码解读