一、循环模块
1、当存在循环的require()
调用时,一个模块可能在返回时并不会被执行。 //只在第一次调用时会执行
二、核心模块
1、Node中有一些模块是编译成二进制的。
2、核心模块定义在node源代码的lib/
目录下。
3、require()总是会优先加载核心模块。例如,require('http')
总是返回编译好的HTTP模块,而不管是否有这个名字的文件。
三、文件模块
1、如果按文件名没有查找到,那么node会添加 .js
和 .json
后缀名,再尝试加载,如果还是没有找到,最后会加上.node
的后缀名再次尝试加载。
2、.js 会被解析为Javascript纯文本文件,.json
会被解析为JSON格式的纯文本文件. .node
则会被解析为编译后的插件模块,由dlopen
进行加载。
3、模块加载的两种方式:
- 使用绝对(/)或相对(./)路径的文件
- 从node_modules文件夹加载
四、从node_modules文件夹中加载
1、如果require()
中的模块名不是一个本地模块,也没有以'/'
, '../'
, 或是 './'
开头,那么node会从当前模块的父目录开始,尝试在它的/node_modules
文件夹里加载相应模块。
2、需要配置package.json文件 //json文件说明
3、如果位于'/home/ry/projects/foo.js'
的文件调用了require('bar.js')
,那么node查找的位置依次为:
- /home/ry/projects/node_modules/bar.js
/home/ry/node_modules/bar.js
/home/node_modules/bar.js
/node_modules/bar.js
注:这就要求程序员应尽量把依赖放在就近的位置,以防崩溃。
五、模块缓存
1、模块在第一次加载后会被缓存。这意味着每次调用require('foo')
的时候都会返回同一个对象。
2、模块的缓存是依赖于解析后的文件名。由于随着调用的位置不同,可能解析到不同的文件(比如需从node_modules
文件夹加载的情况),所以,如果解析到其他文件时,就不能保证require('foo')
总是会返回确切的同一对象。
六、其他
1、require() 返回 module.exports
,并且 module
是一个典型的只能在特定模块作用域内有效的变量,如果要使用它,就必须明确的导出。
2、module.id:用于区别模块的标识符。通常是完全解析后的文件名。
3、module.filename:模块完全解析后的文件名。
4、module.loaded:module的加载状态。
5、module.parent:引入该模块的模块.
6、module.children:这个模块引入的所有模块对象。
7、为了获取调用 require
加载的确切的文件名,使用 require.resolve()
函数。
8、当 Node 直接运行一个文件时,require.main
就被设置为它的 module
。
9、模块包的目录结构、依赖关系等(NPM)