一,原由
为了让Node.js文件可以相互调用,Node.js提供了一个简单的模块系统。
模块是Node.js应用程序的基本组成部分,文件和模块是一一对应的。
换言之。一个Node.js文件就是i 一个模块,这个文件可能是JavaScript代码,JSON,或者编译过的C/C++扩展。
二,创建模块
1.1创建一个模块很容易,文件名叫ninth1.js
Node.js提供了exports和require两个对象,其中exports是模块公开的接口,require用于从外部获取一个模块的接口,即所获取模块的exports对象。
hello.js
上述例子中,hello.js通过exports对象把world作为模块的访问接口,在ninth1.js中通过require('./hello')加载这个模块,然后可以直接访问hello.js中的exports对象的成员函数了。
有时候,我们只是想把一个对象封装到模块中去:
格式如下:
module.exports = function() {
}
例子:
以下是调用该对象。
模块接口唯一的变化是使用了module.exports = Hello 代替了原来的exports.world = function() {} ,在外部引用该模块的时候,其接口对象就是要输出的Hello对象本身,而不是原先的exports
三,服务端的模块放在哪里?
var http = require('http');
...
http.createServer(...);
Node.js自带了一个叫做http 的模块,我们在我们的代码中请求它,并把返回值赋给一个本地变量。
这样我们本地的变量,就成 了一个拥有http模块提供的公共方法的对象。
Node.js存在4种模块(原生模块和3种文件模块)。
尽管require方法极其简单。但是内部加载却是十分复杂,其加载优先级也各自不同。
1.1 从文件模块缓存中加载
尽管原生模块与文件模块的优先级不同,但是都会优先从文件模块的缓存中加载已经存在的模块。
1.2 从原生模块加载
原生模块的优先级仅仅次于文件模块的优先级。require方法在解析文件名之后,优先检查模块是否在原生模块列表中。以http模块为例,尽管在目录下存在一个http/http.js/http.node/http.json文件,require('http')都不会从这些文件中加载,而是从原生模块中加载。
原生模块也有一个缓存区。同样也是优先从缓存区加载。如果缓存区没有加载过,则调用原生模块的加载方式进行加载和执行。
1.3 从文件加载
当文件模块缓存中不存在,而且不是原生模块的时候,Node.js会解析require方法传入的参数,并从文件系统中加载实际的文件,加载过程中的包装和编译细节在前一节已经介绍过,此处,我们详细描述下查找文件模块的过程,其中,也有一些细节值得知晓。
1.4 require方法接收以下集中参数的传递:
1.1.1 http, fs ,path等 ,原生模块。
1.1.2 ./mod或 ../mod,相对路径的文件模块。
1.1.3 /pathtomodule/mod , 绝对路径的文件模块。
1.1.4 mod ,非原生模块的文件模块
1.5 在路径Y下执行require(X)语句执行顺序
1. 如果X是内置模块
a,返回内置模块
b, 停止执行
2.如果X是以 ‘/’ 开头
a,设置Y为文件根路径
3.如果X是以 ‘./’ or '/' or '../' 开头
a, LOAD_AS_FILE(Y+X)
b,LOAD_AS_DIRECTORY(Y+X)
4.LOAD_MODE_MODULES(X,dirname(Y))
5.抛出异常 “not found”
具体参照 Node.js 模块系统|菜鸟教程。