Nodejs模块加载

Nodejs就是一个模块加载系统,一个文件就是一个模块。要想了解模块的加载机制,关键就是搞清require函数的实现。

加载规则

require(x)的使用分为三种情况

  1. 内置模块

    如require(‘fs’)

  2. 路径

    x以’/‘或者’./‘或者’../‘开头。加载此类模块,首先会根据父模块确定x的绝对地址,然后将x作为文件进行查找,如果找到x、x.js、x.json或者x.node,则查找结束。没有则将x作为文件夹进行查找x/package.json、x/index.js、x/index.json或者x/index.node

  3. node_modules

    如require(‘jquery’),会在父模块的目录下查找node_modules,按照第二种情况中查找的规范,并以此向上一级一级查询,直到找到为止

以上三种情况都未找到,那么抛出异常。

Module

Nodejs定义了一个Module构造函数,我们定义的模块都是其实例。Module定义了很多实例属性,id、exports、parent、filename、loaded、children,这些都可以在模块中透过module获取。

require加载模块,都是通过Module._load方法实现的。模块加载的时候会先从缓存中查找,若是第一次加载则会将模块缓存起来,以filename作为唯一标示。如果是内置模块,会跳过这一步,直接加载。

1
2
var module = new Module(filename, parent);
Module._cache[filename] = module;

_load方法实际做了两件事,确定文件的绝对地址和模块处理。其中获取文件的绝对地址的方法,可以通require.resolve()的方法调用。

模块加载

1
module.load(filename);

Nodejs在编译文件的时候,通过wrapper,将module对象传入。

1
2
3
(function (exports, require, module, __filename, __dirname) {
//Your module
});

最后将module.exports对象返回,到此模块就加载完成了。

1
return module.exports