require是一个函数,可以帮助我们引入一个文件(模块)中导出的对象
这里我总结比较常见的查找规则
情况一:X是一个Node核心模块,比如path、http p直接返回核心模块,并且停止查找
情况二:X是以 ./ 或 ../ 或 /(根目录)开头的
将X当做一个文件在对应的目录下查找;
如果有后缀名,按照后缀名的格式查找对应的文件
如果没有后缀名,会按照如下顺序:
- 直接查找文件X
- 查找X.js文件
- 查找X.json文件
- 查找X.node文件
没有找到对应的文件,将X作为一个目录
查找目录下面的index文件
- 查找X/index.js文件
- 查找X/index.json文件
- 查找X/index.node文件
如果没有找到,那么报错:not found
情况三:直接是一个X(没有路径),并且X不是一个核心模块
会按照当前目录逐级向上查找node_modules文件
如果上面的路径中都没有找到,那么报错:not found
模块的加载过程
结论一:模块在被第一次引入时,模块中的js代码会被运行一次
结论二:模块被多次引入时,会缓存,最终只加载(运行)一次
- 为什么只会加载运行一次呢?
- 这是因为每个模块对象module都有一个属性:loaded。
- 为false表示还没有加载,为true表示已经加载;
结论三:如果有循环引入,那么加载顺序是什么?
如果出现右图模块的引用关系,那么加载顺序是什么呢?
- 这个其实是一种数据结构:图结构;
- 图结构在遍历的过程中,有深度优先搜索(DFS, depth first search)和广度优先搜索(BFS, breadth first search);
- Node采用的是深度优先算法:main -> aaa -> ccc -> ddd -> eee ->bbb