解析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 相关文章推荐
uploadify 3.0 详细使用说明
Jun 18 Javascript
java和javascript获取word文档的书签位置对比
Jun 19 Javascript
通过js为元素添加多项样式,浏览器全兼容写法
Aug 30 Javascript
jQuery+CSS3折叠卡片式下拉列表框实现效果
Nov 02 Javascript
Bootstrap树形控件使用方法详解
Jan 27 Javascript
jquery实现界面无刷新加载登陆注册
Jul 30 Javascript
jQuery给指定的table动态添加删除行的操作方法
Oct 12 Javascript
JS实现仿百度文库评分功能
Jan 12 Javascript
JavaScript中捕获与冒泡详解及实例
Feb 03 Javascript
vue+iview+less+echarts实战项目总结
Feb 22 Javascript
vue利用v-for嵌套输出多层对象,分别输出到个表的方法
Sep 07 Javascript
JS数组的高级使用方法示例小结
Mar 14 Javascript
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
一篇不错的PHP基础学习笔记
2007/03/18 PHP
PHPThumb图片处理实例
2014/05/03 PHP
php+highchats生成动态统计图
2014/05/21 PHP
php构造方法中析构方法在继承中的表现
2016/04/12 PHP
PHP面向对象程序设计组合模式与装饰模式详解
2016/12/02 PHP
从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解
2019/04/03 PHP
JavaScript call apply使用 JavaScript对象的方法绑定到DOM事件后this指向问题
2011/09/28 Javascript
Jquery Post处理后不进入回调的原因及解决方法
2014/07/15 Javascript
jQuery实现折线图的方法
2015/02/28 Javascript
如何实现chrome浏览器关闭页面时弹出“确定要离开此面吗?”
2015/03/05 Javascript
Node.js的文件权限及读写flag详解
2016/10/11 Javascript
在js中做数字字符串补0(js补零)
2017/03/25 Javascript
bootstrap3 dialog 更强大、更灵活的模态框
2017/04/20 Javascript
为什么要使用Vuex的介绍
2019/01/19 Javascript
vue路由传参三种基本方式详解
2019/12/09 Javascript
es6数组includes()用法实例分析
2020/04/18 Javascript
解决Vue-cli3没有vue.config.js文件夹及配置vue项目域名的问题
2020/12/04 Vue.js
python使用电子邮件模块smtplib的方法
2016/08/28 Python
基于Python列表解析(列表推导式)
2018/06/23 Python
python简单验证码识别的实现方法
2019/05/10 Python
Django中ajax发送post请求 报403错误CSRF验证失败解决方案
2019/08/13 Python
python使用itchat模块给心爱的人每天发天气预报
2019/11/25 Python
Python + selenium + crontab实现每日定时自动打卡功能
2020/03/31 Python
Python调用OpenCV实现图像平滑代码实例
2020/06/19 Python
Python爬取数据并实现可视化代码解析
2020/08/12 Python
工程质量承诺书
2014/03/27 职场文书
合同权益转让协议书模板
2014/11/18 职场文书
表扬稿格式范文
2015/01/16 职场文书
会议欢迎词
2015/01/23 职场文书
2015建军节87周年演讲稿
2015/03/19 职场文书
六五普法学习心得体会
2016/01/21 职场文书
使用Html+Css实现简易导航栏功能(导航栏遇到鼠标切换背景颜色)
2021/04/07 HTML / CSS
用Python监控你的朋友都在浏览哪些网站?
2021/05/27 Python
你知道哪几种MYSQL的连接查询
2021/06/03 MySQL
windows安装 redis 6.2.6最新步骤详解
2022/04/26 Redis
js判断两个数组相等的5种方法
2022/05/06 Javascript