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& ...
随机推荐
- Sql Server之旅——第九站 看公司这些DBA们设计的这些复合索引
这一篇再说下索引的最后一个主题,索引覆盖,当然学习比较好的捷径是看看那些大师们设计的索引,看从中能提取些什么营养的东西,下面我们看 看数据库中一个核心的Orders表. 一:查看表的架构 <1& ...
- 安装了SQL2005再安装SQL 2008R2,提示此计算机上安装了 Microsoft Visual Studio 2008 的早期版本和检查是否安装了 SQL Server 2005 Express 工具的解决方案
工作电脑上安装了SQL 2005, 但是客户电脑上安装的是SQL 2008R2,有时候连接他们的库调试没法连接,很不方便.然后又安装了个SQL2008 R2,期间遇到这两个问题,网上搜索了一下收到了解 ...
- nsis制作启动Tomcat服务的exe安装包教程
一. 准备工作 下载nsis相关工具包,点击此下载 1. 安装程序:nsis-2.46-setup.exe 2. 编辑程序:cnisedit203.exe 3. 帮助文档:NSIS205帮助文档.ra ...
- hadoop日常运维与升级总结
日常运维 升级 问题处理方法 日常运维 进程管理 由于配置文件的更改,需要重启生效, 或者是进程自己因某种致命原因终止, 或者发现进程工作出现异常等情况下,需要进行手动进程的关闭或启动, 或者是增删节 ...
- Binary Tree: Write a function to return count of nodes in binary tree which has only one child.
June 8, 2015 我最喜欢的一道算法题目, 二行代码. 编程序需要很强的逻辑思维, 严密,我还没有很好训练自己.想一想, 二行代码, 五分钟就可以搞定; 最近这几天网上大家热议的 Homebr ...
- continue break return的区别
1.continue 语句的作用 终止本次循环的执行,即跳过当前一次循环中continue语句后尚未执行的语句,然后进行下一次循环条件的判断. 2.break 语句的作用 (1)当 ...
- 洛谷U2641 木板面积(area)——S.B.S.
题目背景 一年一次的夏令营又要开始了,卡卡西和小伙伴们早就做好了准备,满心期 待着这趟快乐之旅.在一个阳光明媚的清晨,卡卡西在老师的带领下来到了这次 夏令营的首站——“神奇木材加工厂” . 题目描述 ...
- 转: windows 10使用原生linux bash命令行
转: https://www.zybuluo.com/pandait/note/337430 windows 10使用原生linux bash命令行 linux bash windows-10 第一时 ...
- noj[1581] 筷子
题目描述 A先生有很多双筷子.确切的说应该是很多根,因为筷子的长度不一,很难判断出哪两根是一双的.这天,A先生家里来了K个客人,A先生留下他们吃晚饭.加上A先生,A夫人和他们的孩子小A,共K+3个人. ...
- iOS Block详细介绍(block实现)
Block的实现 数据结构定义 block的数据结构定义如下图 对应的结构体定义如下: struct Block_descriptor { unsigned long int reserved; un ...