Nodejs模块加载机制

 2015年03月09日    319     声明


1.node是如何加载模块的

Node.js的模块分为两类,一类为核心模块(原生模块),一类为第三方模块(文件模块)。在Node中,即可以通过文件路径也可用名称来引用模块,通过名称引用的模块最终会被映报为一个文件路径(除核心模块外)。核心模块优先级高于文件模块,require相同名称的核心模块和文件模块,被加载到的只能是核心模块。


2.模块导出

Node基于CommonJS规范进行文件和包管理,当应用程序较为复杂时,应该将一些类、对象等划分成定义良好的可重用模块,模块只对暴露需要提供外部访问的内容。

function ClassA(x, y) {
     function add() {
     	return x + y;
     }

     function sub() {
     	return x -y;
     }

     return {
     	add: add,
     	sub: sub
     }
}

module.exports = ClassA;

上面代码的最后一行定义了模块的导出内容。module是Node中一个全局变量,表示当前模块自身,module.exports表示模块向调用脚本所导出的内容。导出内容可以是变量、函数、对象等任意内容。使用该模块的代码如下:

var ClassA = require('./myModule');

var myClass = new ClassA(2, 3);
console.log(myClass.add()); 	//	->	5


3.模块加载

使用require函数来加载模块,如果模块存在返回模块对象。使用方法如下:

var myModule = require('./myModule');

对于核心模块、第三方模块及本地模块,模块加载方法有所不同:


3.1 核心模块的加载

核心模块以二进制包的形式发布,这些模块只能通过模块名,而不能通文件路径引用,即使有与核心模块同名第三方模块,也会优先加载核心模块。

核心模块加载方法如下:

var fs = require('fs');


3.2 文件、文件夹模块加载

文件模块可以从绝对路径或相对路径加载。如下所示:

var myModule=require('/home/liuht/myModules/myModule');

var myModule=require('../myModules/myModule');

var myModule=require('../myModules/myModule.js ');

上面不带.js扩展名的代码与带扩展名功能相同,当找不到文件时Node会加上.js再次查找。

文件夹模块使用文件夹路径来加载:

var myModule = require('../myModuleDir');

找到文件夹后,Node会按包处理,优先查找pakeage.json中的main入口处,pakeage.json文件不存在则会把index.js当作程序入口处。


3.3 node_modules模块加载

如果一个模块名即不是文件、文件夹名,又不是核心模块Node会在node_modules文件夹中查找:

var myModule = require('myModule.js');

上面的代码,Node会查找./node_modules/mymodule.js,如果没找到,Node会在父文件夹../node_module/myModule.js中查找,依次类推,最终到达根目录或找到所需模块为止。


3.4 本地NPM模块加载

通过npm本地模式安装的第三方模块,也会被安装到node_modules目录中,通过npm安装到本地目录或全局目录的第三方模块加载方式如下:

var request = require('request');

以上代码会加载npm安装的request模块,如果全局模式和本地模式都安装过此模块,则优先加载模块的本地版本。


3.5 全局NPM模块加载

通过npm install -g全局安装的模块,会被安装到环境变量$NODE_PATH设置的路径下,Linux下这个路径一般会被设置为/usr/local/lib/node_modules目录,如果在其它位置没找到模志,Node会在NODE_PATH目录下查找,仍然未找到,还会搜索下面这些路径。

  • 1: $HOME/.node_modules
  • 2: $HOME/.node_libraries
  • 3: $PREFIX/lib/node

建议将所有模块放到node_modules目录下,这样加载会更快一些。

另外,如果遇到全局安装的Node模块require引用不到的情况,应检查$NODE_PATH环境变量是否设置,及设置的目录和全局安装的实际目录是否一置。