Node.js-require的使用方法
require最常用的方法
require('http') 内置模块
require('./server') “./”表示当前路径,后面跟的是相对路径
require("../lib/server") ../表示上一级目录,后面跟的也是相对路径
server.js
[javascript]
var http = require('http');
function start(){
server = http.createServer(function (req, res) {
res.writeHeader(200, {"Content-Type": "text/plain"});
res.end("Hello oschina\n");
})
server.listen(8000);
console.log("httpd start @8000");
}
exports.start = start;
index.js
[javascript]
//路径根据自己的实际情况而定
var server = require("./learnNode/server");
server.start();
下面介绍require的只是来自于链接:http://www.nodecn.org/modules.html#file_Modules
模块
Node 使用 CommonJS 模块系统。
Node 有一个简单的模块加载系统。在 Node 中,文件和模块一一对应。比如,在 foo.js 加载同一目录中的circle.js 模块。
foo.js 的内容:
var circle = require('./circle.js');
console.log( 'The area of a circle of radius 4 is '
+ circle.area(4));
circle.js 的内容:
var PI = Math.PI;
exports.area = function (r) {
return PI * r * r;
};
exports.circumference = function (r) {
return 2 * PI * r;
};
模块 circle.js 导出了 area() 函数和 circumference() 函数,这样它们就能从模块外部访问了。要导出对象,将其添加到特殊的 exports 对象就行。
模块的局部变量是私有的。在本例中,变量 PI 是 circle.js 私有的。
核心模块
Node 有一些已编译成二进制的模块,这些模块将在本文档的其他地方详细 介绍。
核心模块在 Node 源代码的 lib/ 文件夹中定义。
使用 require() 时,核心模块总是优先加载。例如,require('http') 总是返回内置的 HTTP 模块,即使该名称的文件存在。
文件模块
如果没有找到确切的文件,Node 将尝试给所需的文件名 添加 .js 后缀再加载,然后再尝试 .node。
.js 文件被视为 JavaScript 文本文件,而 .node 文件被视为已编译的插件模块,用 dlopen 加载。
模块以 '/' 开头表示使用文件的绝对路径。例如,require('/home/marco/foo.js') 将加载/home/marco/foo.js 文件。
模块以 './' 开头表示调用 require() 时使用相对路径。也就是说,为了保证 require('./circle') 能找到,circle.js 必须和 foo.js 在同一目录。
如果不以 '/' 或'./' 开头,该模块可以是一个“核心模块”,也可是一个从 node_modules 文件夹中加载的模块。
从 `node_modules` 文件夹中加载
如果传递给 require() 有模块标识符是不是原生模块,而且不以 '/'、'../' 或'./' 开头,那么 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
这就允许程序将依赖关系本地化,防止它们冲突。
优化 `node_modules` 查找过程
当嵌套依赖关系的层次很深时,这个文件查找列表可能会变得很长。因此,在查找时进行如下优化:
首先,/node_modules 不会附加到一个以 /node_modules 结尾的文件夹后面。
其次,如果调用 require() 的文件已经在一个 node_modules 层级里,那么最顶层的 node_modules 文件夹将被视为搜索树的根。
例如,如果在文件 '/home/ry/projects/foo/node_modules/bar/node_modules/baz/quux.js' 中调用require('asdf.js'),那么 Node 将搜索下列位置:
/home/ry/projects/foo/node_modules/bar/node_modules/baz/node_modules/asdf.js
/home/ry/projects/foo/node_modules/bar/node_modules/asdf.js
/home/ry/projects/foo/node_modules/asdf.js
以文件夹作为模块
Node 允许用户在独立的目录中方便地组织程序,然后提供单一入口指向该库。有三种方式可以将文件夹作为require() 的参数。
第一种方式是在该文件夹中创建 package.json 文件,指定一个 main 模块。一个典型的 package.json 文件可能看起来像这样:
{ "name" : "some-library",
"main" : "./lib/some-library.js" }
如果此文件位于 ./some-library 文件夹,则 require('./some-library') 会尝试加载 ./some-library/lib/some-library.js。
这是 Node 能找到 package.json 文件的情况。
如果在该目录中没有 package.json 文件,那么 Node 将尝试加载该目录中的 index.js 或 index.node 文件。例如,如果上面的例子找不到 package.json,那么 require('./some-library') 将试图加载:
./some-library/index.js
./some-library/index.node
缓存
模块在首次被加载后会缓存起来。这意味着每次调用 require('foo') 将得到完全相同的对象,如果它被解析为同一个文件的话。
从 `require.paths` 加载
在 Node 中,require.paths 是一个字符串数组,表示模块不以 '/' './' 或 '..' 打头的搜索路径。例如,如果 require.paths 设置为:
[ '/home/micheil/.node_modules',
'/usr/local/lib/node_modules' ]
则调用 require('bar/baz.js') 会搜索以下位置:
1: '/home/micheil/.node_modules/bar/baz.js'
2: '/usr/local/lib/node_modules/bar/baz.js'
可以在运行时修改 require.paths 数组来改变这种行为。
它的值最初从 NODE_PATH 环境变量而来,那是一个冒号分隔的绝对路径列表。在前面的例子中,NODE_PATH 环境变量可能被设置为:
/home/micheil/.node_modules:/usr/local/lib/node_modules
只有使用上面的 node_modules 算法找不到模块时才会尝试 require.paths。全局模块的优先级低于捆绑依赖。
**注意** 请不要修改 `require.paths`
出于兼容性的考虑,require.paths 仍然是模块查找过程的首选策略。尽管如此,它可能会在将来的版本中废弃。
虽然它看起来似乎是个好主意,但在实践中一个可变的 require.paths 列表往往是麻烦和混乱的根源。
修改 `require.paths` 毫无用处
这行代码并不会像期望的那样:
require.paths = [ '/usr/lib/node' ];
它的结果就是丢弃了 Node 实际的模块查找路径引用,并创建了一个毫无用处的指向别处的新的引用。
在 `require.paths` 中加入相对路径……不是个好主意
如果你这样做:
require.paths.push('./lib');
它不会添加 ./lib 在文件系统上已解析的完整路径。相反,它实际增加的是 './lib',这意味着如果你在/a/b/x.js 中 require('y.js'),那么它会查找 /a/b/lib/y.js。如果你之后又在 /l/m/n/o/p.js 中require('y.js'),那么它就会查找 /l/m/n/o/lib/y.js。
在实践中,人们往往将它作为捆绑依赖的临时解决办法,这个技巧是不太稳妥的。
零隔离
有一种糟糕的设计:所有模块共用一个 require.paths 数组。
结果,如果一个 Node 程序依赖于这种行为,它可能会永久而微妙地改变同一进程中其它 Node 程序的行为。当应用程序的复杂度增加时,我们倾向于封装功能,这些行为很难预料的部分会成为开发者的恶梦。
增编:软件包管理小贴示
在 Node 中,require() 函数的语义被设计成通用性足以支持大量合理的目录结构。因此 dpkg、rpm 和 npm之类的包管理器可以从 Node 模块构建原生包而不作更改。
下面我们给出一个可以工作的建议的目录结构:
比方说,我们希望 /usr/lib/node/<some-package>/<some-version> 文件夹中包含某个包的特定版本的内容。
一个软件包可以依赖别的包。为了安装 foo 包,你可能需要安装 bar 包的特定版本 。可能该 bar 包本身有依赖关系,在某些情况下,这些依赖关系甚至可能发生冲突或者形成回路。
由于 Node 在加载任何模块时都会查找它的真实路径(即:会解析符号链接),然后在 node_modules 文件夹用上文描述的方式查找依赖。使用以下架构可以很简单地解决:
/usr/lib/node/foo/1.2.3/ -foo 包的内容,版本1.2.3。
/usr/lib/node/bar/4.3.2/ -bar 包的内容,foo 依赖这个包。
/usr/lib/node/foo/1.2.3/node_modules/bar -到 /usr/lib/node/bar/4.3.2/ 的符号链接。
/usr/lib/node/bar/4.3.2/node_modules/* -到 bar 所依赖的包的符号链接。
因此,即使遇到一个回路,或者有依赖冲突,每个模块都能够得到它依赖的可用版本。
当 foo 包中有代码 require('bar') 时,它会得到符号链接至/usr/lib/node/foo/1.2.3/node_modules/bar 的版本。然后,当 bar 包调用 require('quux') 时,它会得到符号链接至 /usr/lib/node/bar/4.3.2/node_modules/quux 的版本。
此外,为了使模块查找过程更加优化,而 不是直接把包放到 /usr/lib/node 中,我们可以它们放到/usr/lib/node_modules/<name>/<version> 里。这样,Node 就不用在 /usr/node_modules 或/node_modules 中查找了。
为了使 REPL 能够正常引用模块,可以将 /usr/lib/node_modules 添加至 $NODE_PATH环境变量。因为使用node_modules 文件夹查找模块时的路径都是相对的,而且调用 require() 时基于文件的真实路径,因此软件包本身可以放在任何位置。
Node.js-require的使用方法的更多相关文章
- Node.js require 模块加载原理 All In One
Node.js require 模块加载原理 All In One require 加载模块,搜索路径 "use strict"; /** * * @author xgqfrms ...
- Node.js require 方法
Node.js 中存在 4 类模块(原生模块和3种文件模块),尽管 require 方法极其简单,但是内部的加载却是十分复杂的,其加载优先级也各自不同
- Node.js 手册查询-3-Mongoose 方法
Mongoose 参考手册 标签(空格分隔): MongoDB Mongoose 是什么? 一般我们不直接用MongoDB的函数来操作MongoDB数据库 Mongose就是一套操作MongoDB数据 ...
- Node.js 手册查询-4-Express 方法
express 标签(空格分隔): node.js express [TOC] 安装: 新版本中命令行工具分家了 npm install -g express //安装 express 然后 npm ...
- Node.js原生及Express方法实现注册登录原理
由于本文只是实现其原理,所以没有使用数据库,只是在js里面模拟数据库,当然是种中还是需要用数据库的. 1.node.js原生方法 ①html页面,非常简单,没有一丝美化~我们叫它user.html & ...
- [Node.js] require背后的故事
前言 熟悉Node.js的肯定对下面的代码熟悉 var http = require('http'); 这段代码很好理解,就是加载一个http模块.但是你有没有想过为什么要这么写?这其中的缘由是什么呢 ...
- node.js require() 源码解读
时至今日,Node.js 的模块仓库 npmjs.com ,已经存放了15万个模块,其中绝大部分都是 CommonJS 格式.这种格式的核心就是 require 语句,模块通过它加载.学习 Node. ...
- 在CentOS 7上安装Node.js的4种方法(yum安装和源码安装)
CentOS 7上的安装方法,其中涵盖了源码安装,已编译版本安装,EPEL(Extra Packages for Enterprise Linux)安装和通过NVM(Node version mana ...
- 在CentOS 7上安装Node.js的4种方法(包含npm)
Node.js和Javascript有着千丝万缕的联系,可以说Node.js让Javascript显得从未如此强大.好吧…微魔其实是个门外汉…但是这并不能阻碍微魔学习探索未知的信心~今天在国外闲逛,看 ...
- 在CentOS 7上安装Node.js的4种方法
一.源码安装 1.下载源码(官网查看最新版本链接) wget http://nodejs.org/dist/v0.10.30/node-v0.10.30.tar.gz 2.解压源码 tar xzvf ...
随机推荐
- map循环遍历删除
typedef map<string,int> MapFileList; int main() { MapFileList m_SingleList; m_SingleList.inser ...
- 解决 在IE与firefox宽度不一致的问题
浏览器默认不同的字体问题,字体分为“等宽”和“不等宽”字体,所以 在IE与firefox内间距是不等的. 解决办法: body{font-family: 宋体, simsun; ...
- qt tablewidget中单个和批量删除代码如下(部分)截图如下
def coltable(self):#行删除 row=self.downwidget.currentRow() select=self.downwidget.isItemSelected ...
- 信息熵(Entropy)究竟是用来衡量什么的?
信息熵(Entropy)究竟是用来衡量什么的? ——与Philip ZHANG商榷 思明 Philip ZHANG先生在反驳彭小明的时候,提出一个观点,他说:“ 就语言文 字来说,总体效率不是用民族主 ...
- MySQL server version for the right syntax to use near 'type=InnoDB' at line 1
转载请注明出处:http://blog.csdn.net/bettarwang/article/details/40180271 在执行一个Hibernate的演示样例时,配置了<propert ...
- 在Ubuntu上下载、编译和安装Android最新内核源代码(Linux Kernel)
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6564592 在前一篇文章提到,从源代码树下载下 ...
- React 入门最好的实例-TodoList
React 的核心思想是:封装组件,各个组件维护自己的状态和 UI,当状态变更,自动重新渲染整个组件. 最近前端界闹的沸沸扬扬的技术当属react了,加上项目需要等等原因,自己也决定花些时间来好好认识 ...
- JavaScript学习笔记:检测数组方法
检查数组的方法 很多时候我们需要对JavaScript中数据类型(Function.String.Number.Undefined.Boolean和Object)做判断.在JavaScript中提供了 ...
- document.write 向文档中写内容,包括文本、脚本、元素之类的,但是它在什么时候执行不会覆盖当前页面内容尼?
当你打开一个页面,浏览器会 调用 document.open() 打开文档 document.write(...) 将下载到的网页内容写入文档 所有内容写完了,就调用 document.close() ...
- WebApi2官网学习记录---Configuring
Configuration Settings WebAPI中的configuration settings定义在HttpConfiguration中.有一下成员: DependencyResolver ...