解析Node.js基于模块和包的代码部署方式


Posted in Javascript onFebruary 16, 2016

模块路径解析规则

有经验的 C 程序员在编写一个新程序时首先从 make 文件写起。同样的,使用 NodeJS 编写程序前,为了有个良好的开端,首先需要准备好代码的目录结构和部署方式,就如同修房子要先搭脚手架。本章将介绍与之相关的各种知识。

模块路径解析规则
我们已经知道,require函数支持斜杠(/)或盘符(C:)开头的绝对路径,也支持./开头的相对路径。但这两种路径在模块之间建立了强耦合关系,一旦某个模块文件的存放位置需要变更,使用该模块的其它模块的代码也需要跟着调整,变得牵一发动全身。因此,require函数支持第三种形式的路径,写法类似于foo/bar,并依次按照以下规则解析路径,直到找到模块位置。

内置模块

如果传递给 require 函数的是 NodeJS 内置模块名称,不做路径解析,直接返回内部模块的导出对象,例如 require('fs')。

node_modules 目录

NodeJS 定义了一个特殊的 node_modules 目录用于存放模块。例如某个模块的绝对路径是 /home/user/hello.js,在该模块中使用 require('foo/bar') 方式加载模块时,则 NodeJS 依次尝试使用以下路径。

/home/user/node_modules/foo/bar
 /home/node_modules/foo/bar
 /node_modules/foo/bar

NODE_PATH 环境变量

与 PATH 环境变量类似,NodeJS 允许通过 NODE_PATH 环境变量来指定额外的模块搜索路径。NODE_PATH 环境变量中包含一到多个目录路径,路径之间在 Linux 下使用:分隔,在 Windows 下使用;分隔。例如定义了以下 NODE_PATH 环境变量:

 NODE_PATH=/home/user/lib:/home/lib
当使用 require('foo/bar')的方式加载模块时,则 NodeJS 依次尝试以下路径。

/home/user/lib/foo/bar
 /home/lib/foo/bar

我们已经知道了 JS 模块的基本单位是单个 JS 文件,但复杂些的模块往往由多个子模块组成。为了便于管理和使用,我们可以把由多个子模块组成的大模块称做包,并把所有子模块放在同一个目录里。

在组成一个包的所有子模块中,需要有一个入口模块,入口模块的导出对象被作为包的导出对象。例如有以下目录结构。

- /home/user/lib/
  - cat/
    head.js
    body.js
    main.js

其中 cat 目录定义了一个包,其中包含了 3 个子模块。main.js 作为入口模块,其内容如下:

var head = require('./head');
var body = require('./body');

exports.create = function (name) {
  return {
    name: name,
    head: head.create(),
    body: body.create()
  };
};

在其它模块里使用包的时候,需要加载包的入口模块。接着上例,使用 require('/home/user/lib/cat/main')能达到目的,但是入口模块名称出现在路径里看上去不是个好主意。因此我们需要做点额外的工作,让包使用起来更像是单个模块。

index.js
当模块的文件名是 index.js,加载模块时可以使用模块所在目录的路径代替模块文件路径,因此接着上例,以下两条语句等价。

var cat = require('/home/user/lib/cat');
var cat = require('/home/user/lib/cat/index');

这样处理后,就只需要把包目录路径传递给 require 函数,感觉上整个目录被当作单个模块使用,更有整体感。

package.json
如果想自定义入口模块的文件名和存放位置,就需要在包目录下包含一个 package.json 文件,并在其中指定入口模块的路径。上例中的 cat 模块可以重构如下。

- /home/user/lib/
  - cat/
    + doc/
    - lib/
      head.js
      body.js
      main.js
    + tests/
    package.json

其中package.json内容如下。

{
  "name": "cat",
  "main": "./lib/main.js"
}

如此一来,就同样可以使用 require('/home/user/lib/cat')的方式加载模块。NodeJS 会根据包目录下的 package.json 找到入口模块所在位置。

Javascript 相关文章推荐
Javascript调试工具(下载)
Jan 09 Javascript
用javascript实现的仿Flash广告图片轮换效果
Apr 24 Javascript
JS的location.href跳出框架打开新页面的方法
Sep 04 Javascript
JS长整型精度问题实例分析
Jan 13 Javascript
删除javascript所创建子节点的方法
May 21 Javascript
javascript中sort() 方法使用详解
Aug 30 Javascript
JavaScript函数的调用以及参数传递
Oct 21 Javascript
jQuery实现获取table表格第一列值的方法
Mar 01 Javascript
浅述节点的创建及常见功能的实现
Dec 15 Javascript
Angular实现跨域(搜索框的下拉列表)
Feb 16 Javascript
web前端vue filter 过滤器
Jan 12 Javascript
一篇文章学会Vue中间件管道
Jun 20 Vue.js
javascript每日必学之基础入门
Feb 16 #Javascript
快速掌握Node.js环境的安装与运行方法
Feb 16 #Javascript
js实现异步循环实现代码
Feb 16 #Javascript
JavaScript实现跑马灯抽奖活动实例代码解析与优化(二)
Feb 16 #Javascript
JavaScript实现跑马灯抽奖活动实例代码解析与优化(一)
Feb 16 #Javascript
javascript HTML+CSS实现经典橙色导航菜单
Feb 16 #Javascript
JavaScript中使用数组方法汇总
Feb 16 #Javascript
You might like
IIS7.X配置PHP运行环境小结
2011/06/09 PHP
php中cookie实现二级域名可访问操作的方法
2014/11/11 PHP
ThinkPHP在Cli模式下使用模板引擎的方法
2015/09/25 PHP
PHP中strnatcmp()函数“自然排序算法”进行字符串比较用法分析(对比strcmp函数)
2016/01/07 PHP
php中对象引用和复制实例分析
2019/08/14 PHP
tp5 sum某个字段相加得到总数的例子
2019/10/18 PHP
JavaScipt基本教程之JavaScript语言的基础
2008/01/16 Javascript
javascript 清空form表单中某种元素的值
2009/12/26 Javascript
用AJAX返回HTML片段中的JavaScript脚本
2010/01/04 Javascript
javascript 构建一个xmlhttp对象池合理创建和使用xmlhttp对象
2010/01/15 Javascript
JS 进度条效果实现代码整理
2011/05/21 Javascript
javascript之典型高阶函数应用介绍二
2013/01/10 Javascript
jQuery循环滚动新闻列表示例代码
2014/06/17 Javascript
JS函数定义方式的区别介绍
2016/03/22 Javascript
简单的vue-resourse获取json并应用到模板示例
2017/02/10 Javascript
Angular1.x复杂指令实例详解
2017/03/01 Javascript
Bootstrap实现的经典栅格布局效果实例【附demo源码】
2017/03/30 Javascript
JS实现预加载视频音频/视频获取截图(返回canvas截图)
2017/10/09 Javascript
vue router+vuex实现首页登录验证判断逻辑
2018/05/17 Javascript
JavaScript类数组对象转换为数组对象的方法实例分析
2018/07/24 Javascript
javascript之分片上传,断点续传的实际项目实现详解
2019/09/05 Javascript
vue 公共列表选择组件,引用Vant-UI的样式方式
2020/11/02 Javascript
[01:13:46]iG vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
Python3访问并下载网页内容的方法
2015/07/28 Python
centos6.7安装python2.7.11的具体方法
2017/01/16 Python
浅谈python jieba分词模块的基本用法
2017/11/09 Python
如何用python写一个简单的词法分析器
2018/12/18 Python
Python字典的核心底层原理讲解
2019/01/24 Python
python中树与树的表示知识点总结
2019/09/14 Python
什么是lambda函数
2013/09/17 面试题
入党积极分子学习两会心得体会范文
2014/03/17 职场文书
交通事故协议书范文
2014/04/16 职场文书
邀请书模板
2015/02/02 职场文书
幼儿园庆元旦主持词
2015/07/06 职场文书
《惊弓之鸟》教学反思
2016/02/20 职场文书
秀!学妹看见都惊呆的Python小招数!【详细语言特性使用技巧】
2021/04/27 Python