node 学习笔记 - Modules 模块加载系统 (1)
本文同步自我的个人博客:http://www.52cik.com/2015/12/11/learn-node-modules-path.html
用了这么久的 require,但却没有系统的学习过 node 的模块系统,今天就翻官方文档系统的学习下。
循环引用
node 对模块循环引用做了相应的处理,防止无尽的循环。
官方例子:
a.js:
console.log('a starting');
exports.done = false;
var b = require('./b.js');
console.log('in a, b.done = %j', b.done);
exports.done = true;
console.log('a done');
b.js:
console.log('b starting');
exports.done = false;
var a = require('./a.js');
console.log('in b, a.done = %j', a.done);
exports.done = true;
console.log('b done');
main.js:
console.log('main starting');
var a = require('./a.js');
var b = require('./b.js');
console.log('in main, a.done=%j, b.done=%j', a.done, b.done);
执行结果:
$ node main.js
main starting
a starting
b starting
in b, a.done = false
b done
in a, b.done = true
a done
in main, a.done=true, b.done=true
在结果中可以看到,b 里引用 a 的时候结果是 a.done = false,这就算文档里说的 unfinished copy,这样就避免了程序的死循环。
核心模块
其实就是被编译到 node 内部的一些模块,在源码的 lib 目录下可以找到。例如 require('http') 的时候不论是否有其他同名模块,都直接返回 node 的核心模块,也就算最高优先级。
这些模块就是 node 官网文档目录列表里的那些模块。
文件模块
这个花样就多了,慢慢说吧。
模块后缀
node 默认支持 .js .json .node 后缀的模块,也就是说 require 的时候不需要写后缀名。例如 require('./a'),node 会先尝试当前目录下的 a.js 文件,如果有,就载入否则继续尝试 a.json, a.node 这些文件,如果都不存在,就会抛出模块未找到的错误。
当然这些模块后缀都是可以自己定义拓展的,比如 ejs 就拓展了个 .ejs 的后缀,支持直接 require 就得到了编译好的模块引擎了。
模块路径
以 '/', './' 或 '../' 开头的,都是指定路径加载。
模块以 '/' 为前缀,则表示绝对路径。例如,require('/home/marco/foo.js') 加载的是 /home/marco/foo.js 这个文件。
模块以 './' 为前缀,则路径是相对于当前文件的。也就是说,circle.js 必须和 foo.js 在同一目录下,require('./circle') 才能找到。
其实还一个特殊路径的模块加载,就是 node_modules 文件夹,这个要单独说了。
从 node_modules 目录中加载
如果模块不是以 '/', './' 或 '../' 开头的,那么 node 会从当前模块的父目录开始,尝试在它的 node_modules 文件夹里加载相应模块。如果没有找到,那么就再向上移动到父目录,直到到达顶层目录位置。
假如 /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
如果都找不到,会去全局模块路径找,还找不到就会抛出模块未找到的错误。
目录模块
当一个模块功能多代码多的时候,不合适写到一个文件里,那这个时候就可以用目录当作模块使用了。有两种方法可以让一个目录作为 require 方式引入。官网说三种,其实吧 .js .node 看做两种了。
index.js 入口
例如在 some-library 目录里有 index.js 或者 index.node 文件,那么 require('./some-library') 就将尝试加载下面的文件:
- ./some-library/index.js
- ./some-library/index.node
非常简单方便。
package.json
还有一种方式可以指定入口文件,就是通过 package.json,下面是一个 package.json 文件的示例。
{
"name" : "some-library",
"main" : "./src/some-library.js"
}
那么 require('./some-library') 就将会去加载 ./some-library/src/some-library.js。
全局模块
当以上方法找不到模块时,node 会去全局配置下寻找全局模块:
- $HOME/.node_modules
- $HOME/.node_libraries
- $PREFIX/lib/node
以及
- /usr/lib/node_modules
或者
- /usr/local/lib/node_modules
这些都没测试,我只知道我本地的全局模块路径是 /usr/local/lib/node_modules,是我本机 npm 安装的全局模块路径。
官网里还有一些奇葩的全局目录,我都没见过,算了不研究了。
node 学习笔记 - Modules 模块加载系统 (1)的更多相关文章
- node 学习笔记 - Modules 模块加载系统 (2)
本文同步自我的个人博客:http://www.52cik.com/2015/12/14/learn-node-modules-module.html 上一篇讲了模块是如何被寻找到然后加载进来的,这篇则 ...
- thinkphp学习笔记9—自动加载
原文:thinkphp学习笔记9-自动加载 1.命名空间自动加载 在3.2版本中不需要手动加载类库文件,可以很方便的完成自动加载. 系统可以根据类的命名空间自动定位到类库文件,例如定义了一个类Org\ ...
- abp vnext2.0之核心组件模块加载系统源码解析与简单应用
abp vnext是abp官方在abp的基础之上构建的微服务架构,说实话,看完核心组件源码的时候,很兴奋,整个框架将组件化的细想运用的很好,真的超级解耦.老版整个框架依赖Castle的问题,vnext ...
- 第三章:模块加载系统(requirejs)
任何一门语言在大规模应用阶段,必然要经历拆分模块的过程.便于维护与团队协作,与java走的最近的dojo率先引入加载器,早期的加载器都是同步的,使用document.write与同步Ajax请求实现. ...
- Openstack本学习笔记——Neutron-server服务加载和启动源代码分析(三)
本文是在学习Openstack过程中整理和总结.因为时间和个人能力有限.错误之处在所难免,欢迎指正! 在Neutron-server服务载入与启动源代码分析(二)中搞定模块功能的扩展和载入.我们就回到 ...
- Node学习笔记之模块实现
一.模块分类 由Node提供的模块,称为核心模块:部分核心模块在Node源代码的编译过程中,编译进了二进制执行文件.在node进程启动时,该部分就直接加载进内存,文件定位和编译执行的步骤可以省略掉,并 ...
- JS框架设计之加载器所在路径的探知一模块加载系统
1.要加载一个模块,我们需要一个URL作为加载地址,一个script作为加载媒介,但用户在require是都用ID,我们需要一个将ID转换为URL的方法,思路很简单,强加个约定,URL的合成规则是为: ...
- JS框架设计之模块加载系统
任何语言一到大规模应用阶段,必然要拆封模块,有利于维护和团队协作,与Java走得最近的dojo率先引进了加载器,使用document.write与同步Ajax请求实现,后台dojo以JSONP的方法来 ...
- YUI笔记 1 模块加载
我们通常开发js程序就是使用<script>标签把脚本引入到页面中进行开发,如果是简单的逻辑还好,但是如果是比较庞大的大规模js开发,可能会出现下面的问题: 1. <script& ...
随机推荐
- [20130704] Intra-Query Parallel Thread Deadlocks
今天碰到了 Intra-Query Parallel Thread Deadlocks 简单的说就是并发查询把自己给锁住了. 原理: 在并发查询运行是,有一个生产者和一个消费者,生产者等待消费者产生 ...
- 数据处理/OLAP/OLTP
- Cookie在IE缓存问题深度研究
最近在发布net到生产环境的时候,测试发现了问题,IE的登录无效. 同样的版本在QA环境没有遇到问题. 代码一样,chrome,firefox 都可以.就是IE不行,调试发现 登录完成,读取cooki ...
- centos---无线上网的电脑所安装的虚拟机网络设置
1.共享设置 找到本地的无线网卡,右键---属性---共享,设置如下 2.修改VMware Network Adapter VMnet1 选中VMware Network Adapter VMnet1 ...
- RAM,SRAM,DRAM,SDRAM,DDR RAM,ROM,PROM,EPROM,EEPROM,NAND FLASH,NOR FLASH的区别
RAM:由字面意思就可以理解,SDRAM SRAM DRAM(下面蓝色字体的这几种)都可以统称RAM,random access memory(随机存取存储器)的缩写,下面是51hei.com为大家整 ...
- c++学习之容器细枝末节(1)
对照着c++primier 开始学习第九章容器,把课后习题当做练习,虽然是看过书上的讲解,但是做题编程的时候,一些需要注意的地方还是难免有遗漏. 一下是几点印象比较深刻的总结: (1)前几章只学了ve ...
- HDU4003Find Metal Mineral[树形DP 分组背包]
Find Metal Mineral Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Other ...
- 第16章 调色板管理器_16.4 一个DIB位图库的实现(1)
16.4.1自定义的 DIBSTRUCT结构体 字段 含义 PBYTE *ppRow ①指向位图视觉上最上面的一行像素.(不管是自下而上,还是自上而下) ②放在第一个字段,为的是后面定义宏时可方便访问 ...
- 向Tiny6410移植QT4.7.0版本
在移植QT之前我们首先要安装tslib,没有移植的可以看这篇文章移植. http://www.cnblogs.com/ynxf/p/5392476.html step 1: echo yes |../ ...
- 如何在Actionbarsherlock中一直显示overflow效果?
对Android开发一致性有一定考虑的程序员应当或多或少对Actionbarsherlock这个库有一定的了解.Actionbarsherlock的产生是因为Android在3.0(API 11)之后 ...