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& ...
随机推荐
- [Java入门笔记] Java语言简介
前言 学习Java有一段时间了,但是一直缺少一个系统的思想,现在重新通过书籍中.网上的文章,视频等资料,整理与回顾Java的知识点. 言归正传,让我们先从了解Java语言开始. Java语言的由来 J ...
- CSS实现自定义手型气泡提示
实现自定义的手型气泡提示 <html> <head> <meta charset="utf-8"> <title></titl ...
- 修改/etc/profile文件
通常情况下,/etc/profile文件是只读的,直接用vi或gedit打开修改后是无法保存的.要修改profile,需要取得root权限,(使用gedit编辑)应该如下: $sudo gedit / ...
- spring 注入一个以枚举类型对象
1.枚举 在实际编程中,往往存在着这样的“数据集”,它们的数值在程序中是稳定的,而且“数据集”中的元素是有限的. 例如星期一到星期日七个数据元素组成了一周的“数据集”,春夏秋冬四个数据元素组成了四季的 ...
- Windows Azure Storage图形界面管理工具
上一篇我们介绍了用PowerShell将Windows Azure的存储服务当网盘来使用.如果感觉还不够简单,那么这次我们来看看还有哪些使用起来更方便的图形界面管理工具吧.当然,这些工具必要支持中国版 ...
- 新手ui设计师必备——切图规范
图文并茂,浅显易懂. 使用markman标注. 资源链接: 图片来自http://www.ui.cn/detail/56347.html 本文作者starof,因知识本身在变化,作者也在不断学习成长, ...
- z-index堆叠规则
一.z-index z-index用来控制元素重叠时堆叠顺序. 适用于:已经定位的元素(即position:relative/absolute/fixed). 一般理解就是数值越高越靠上,好像很简单, ...
- NOIP2010乌龟棋[DP 多维状态]
题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家控制一个乌龟棋子从起 ...
- 网络之OSI七层模型
1. 物理层:设备之间的比特流的传输,物理接口,电气特性等 2. 数据链路层:成帧,用MAC地址访问媒介,错误检测与修正 3. 网络层:提供逻辑地址(IP),选路 4. 传输层:可靠与不可靠的 ...
- 基于SPSS的美国老年夏季运动会运动员数据分析
本文是课程训练的报告,部分图片由于格式原因并没有贴出,有兴趣者阅读完整报告者输入以下链接 http://files.cnblogs.com/files/liugl7/基于SPSS的老 ...