龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > web编程 > Javascript编程 >

Node.js模块加载详解_node.js(3)

时间:2014-08-25 12:02来源:网络整理 作者:网络 点击:
分享到:
如果require函数的参数不是相对路径,也不是核心模块名,Node会在当前目录的node_modules子目录下查找,比如下面的代码,Node会尝试查找文件./node_modules/my

如果require函数的参数不是相对路径,也不是核心模块名,Node会在当前目录的node_modules子目录下查找,比如下面的代码,Node会尝试查找文件./node_modules/myModule.js:

复制代码 代码如下:

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

如果没找到,Node会继续在上级目录的node_modules文件夹下查找,如果还没找到就继续向上层目录查找,直到找到对应的模块或者到达根目录。

你可以使用这个特性来管理node_modules目录的内容或模块,不过最好还是把模块的管理任务交给NPM(见第一章),本地node_modules目录是NPM安装模块的默认位置,这个设计把Node和NPM关联在了一起。通常,作为开发人员不必太关心这个特性,你可以简单的使用NPM安装,更新和删除包,它会帮你维护node_modules目录

缓存模块

模块在第一次成功加载后会被缓存起来,就是说,如果模块名被解析到同一个文件路径,那么每次调用require(‘myModule')都确切地会返回同一个模块。

比如,有一个叫my_module.js的模块,包含下面的内容:

复制代码 代码如下:

console.log('module my_module initializing...');

module.exports = function() {

         console.log('Hi!');

};

console.log('my_module initialized.');

然后用下面的代码加载这个模块:

复制代码 代码如下:

var myModuleInstance1 = require('./my_module');

它会产生下面的输出:

复制代码 代码如下:

module my_module initializing...

my_module initialized

如果我们两次导入它:

复制代码 代码如下:

var myModuleInstance1 = require('./my_module');

var myModuleInstance2 = require('./my_module');

输出依然是:

复制代码 代码如下:

module my_module initializing...

my_module initialized

也就是说,模块的初始化代码仅执行了一次。当你构建自己的模块时,如果模块的初始化代码里含有可能产生副作用的代码,一定要特别注意这个特性。

小结

Node取消了JavaScript的默认全局作用域,转而采用CommonJS模块系统,这样你可以更好的组织你的代码,也因此避免了很多安全问题和bug。可以使用require函数来加载核心模块,第三方模块,或从文件及目录加载你自己的模块

还可以用相对路径或者绝对路径来加载非核心模块,如果把模块放到了node_modules目录下或者对于用NPM安装的模块,你还可以直接使用模块名来加载。

 译者注:

建议读者把官方文档的模块章节阅读一遍,个人感觉比作者讲得更清晰明了,而且还附加了一个非常具有代表性的例子,对理解Node模块加载会很有很大帮助。下面把那个例子也引用过来:

复制代码 代码如下:

用require(X) 加载路径Y下的模块

1. 如果X是核心模块,

   a. 加载并返回核心模块

   b. 结束

2. 如果X以 './' or '/' or '../ 开始'

   a. LOAD_AS_FILE(Y + X)

   b. LOAD_AS_DIRECTORY(Y + X)

3. LOAD_NODE_MODULES(X, dirname(Y))

4. 抛出异常:"not found"

LOAD_AS_FILE(X)

1. 如果X是个文件,把 X作为JavaScript 脚本加载,加载完毕后结束

2. 如果X.js是个文件,把X.js 作为JavaScript 脚本加载,加载完毕后结束

3. 如果X.node是个文件,把X.node 作为Node二进制插件加载,加载完毕后结束

LOAD_AS_DIRECTORY(X)

1. 如果 X/package.json文件存在,

   a. 解析X/package.json, 并查找 "main"字段.

   b. 另M = X + (main字段的值)

   c. LOAD_AS_FILE(M)

2. 如果X/index.js文件存在,把 X/index.js作为JavaScript 脚本加载,加载完毕后结束

3. 如果X/index.node文件存在,把load X/index.node作为Node二进制插件加载,加载完毕后结束

LOAD_NODE_MODULES(X, START)

1. 另DIRS=NODE_MODULES_PATHS(START)

2. 对DIRS下的每个目录DIR做如下操作:

   a. LOAD_AS_FILE(DIR/X)

   b. LOAD_AS_DIRECTORY(DIR/X)

NODE_MODULES_PATHS(START)

1. 另PARTS = path split(START)

2. 另ROOT = index of first instance of "node_modules" in PARTS, or 0

3. 另I = count of PARTS - 1

4. 另DIRS = []

5. while I > ROOT,

   a. 如果 PARTS[I] = "node_modules" 则继续后续操作,否则下次循环

   c. DIR = path join(PARTS[0 .. I] + "node_modules")

   b. DIRS = DIRS + DIR

   c. 另I = I - 1

6. 返回DIRS

精彩图集

赞助商链接