在NodeJS中用到的模块化方案是
CommonJS
模块化开发
在开发中,将整个大的项目分解成以一个个小的结构(一个个功能),每个结构有自己的逻辑代码,有自己的作用域。可以给其他作用域提供自己导出的变量,函数,对象。也可以导入其他作用域导出的变量,函数,对象
CommonJS
案例:
通过exports进行导出,require进行导入。
在bar.js中: exports是一个对象,在这个对象上添加属性,将添加的属性导出。
在main.js中:require获取bar.js导出的对象赋值给bar,也就是说main.js中的bar和bar.js中的exports是同一个对象。
画图解析赋值的全过程
实际上就是引用赋值
module.exports又是什么
实际上在导出的时候,真正就是module.exports在进行导出,但是在因为在每个js文件执行前有
伪代码:
module.exports = exports = { }
因为module.exports和exports的指向不一样了,而真正导出确实module.exports所以在引用的时候,导入的是module.exports指向的对象。
require函数的细节(查找规则)
require(X)
情况一:X是核心模块,找到直接返回,并停止查找。
情况二:X是以 ./ 或 …/ 或 /(根目录)开头的
- .如果有后缀名,按照后缀名的格式查找对应的文件
- 如果没有后缀名,会按照如下顺序:
1> 直接查找文件X
2> 查找X.js文件
3> 查找X.json文件
4> 查找X.node文件 - 没有找到对应的文件,将X作为一个目录
1> 查找X/index.js文件
2> 查找X/index.json文件
3> 查找X/index.node文件 - 找到就返回,没找到报错 not find。
情况三:直接是一个X(没有路径),并且X不是一个核心模块(第三方模块)
当前文件文件夹路径,一层一层往上面找node_module里边找。找到就返回,没找到报错 not find。
模块加载过程
- 模块在被第一次引入时,模块中的js代码会被运行一次
- 模块被多次引入时,会缓存,最终只加载(运行)一次
- Node采用的是深度优先算法,进行模块的引入
CJS和ES module的区别
CommonJS(CJS)
- commonJS加载js文件时动态加载的,并且是同步加载的
- commonJS通过module.exports导出的是一个对象。在使用时在运行后导出得对象里边去取值
- commonJS是单个值导出
es module
- es module加载js文件时时编译时加载的,import和export是关键字,在编译的时候就知道模块之间的依赖关系了
- es module导出的是变量的本身的引用。浏览器在下载完JS文件之后,将其解析成
模块记录
,然后再进行静态分析,分析导入和导出语句,并且分配一定的内存,然后再开始执行模块内的代码,并且再内存内更新导出记录的值,导入模块使用的就是这个内存内的记录。 - es module可以导出多个