解析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 13 Javascript
js 控制图片大小核心讲解
Oct 09 Javascript
js 采用delete实现继承示例代码
May 20 Javascript
jQuery实现tab标签自动切换的方法
Feb 28 Javascript
jQuery 1.9.1源码分析系列(十五)之动画处理
Dec 03 Javascript
基于JQuery实现分隔条的功能
Jun 17 Javascript
JS转换HTML转义符的方法
Aug 24 Javascript
浅谈jquery中next与siblings的区别
Oct 27 Javascript
利用node.js搭建简单web服务器的方法教程
Feb 20 Javascript
AngularJS自定义指令详解(有分页插件代码)
Jun 12 Javascript
详解js中的几种常用设计模式
Jul 16 Javascript
vue抽出组件并传值实例
Jul 31 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&MYSQL服务器配置说明
2006/10/09 PHP
php 的加密函数 md5,crypt,base64_encode 等使用介绍
2012/04/09 PHP
php文件打包 下载之使用PHP自带的ZipArchive压缩文件并下载打包好的文件
2012/06/13 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(十一)
2014/06/25 PHP
Php连接及读取和写入mysql数据库的常用代码
2014/08/11 PHP
php对二维数组进行相关操作(排序、转换、去空白等)
2015/11/04 PHP
PHP实现深度优先搜索算法(DFS,Depth First Search)详解
2017/09/16 PHP
浅谈JavaScript函数参数的可修改性问题
2013/12/05 Javascript
Node.js中对通用模块的封装方法
2014/06/06 Javascript
JavaScript中的原型和继承详解(图文)
2014/07/18 Javascript
jQuery中removeClass()方法用法实例
2015/01/05 Javascript
jQuery+ajax实现无刷新级联菜单示例
2015/05/21 Javascript
JavaScript中标识符提升问题
2015/06/11 Javascript
浅析AngularJS中的生命周期和延迟处理
2015/06/18 Javascript
对于jQuery性能的一些优化建议
2015/08/13 Javascript
javascript实现不同颜色Tab标签切换效果
2016/04/27 Javascript
jQuery文字提示与图片提示效果实现方法
2016/07/04 Javascript
JavaScript 实现的checkbox经典实例分享
2016/10/16 Javascript
浅谈angular.js跨域post解决方案
2017/08/30 Javascript
jquery中done和then的区别(详解)
2017/12/19 jQuery
webpack中使用iconfont字体图标的方法
2018/02/22 Javascript
详解vue后台系统登录态管理
2019/04/02 Javascript
vue store之状态管理模式的详细介绍
2019/06/13 Javascript
JS实现返回上一页并刷新页面的方法分析
2019/07/16 Javascript
[00:27]DOTA2次级职业联赛 - Lilith战队宣传片
2014/12/01 DOTA
python3图片转换二进制存入mysql
2013/12/06 Python
解决Python出现_warn_unsafe_extraction问题的方法
2016/03/24 Python
利用python将xml文件解析成html文件的实现方法
2017/12/22 Python
Python的numpy库中将矩阵转换为列表等函数的方法
2018/04/04 Python
详解django中使用定时任务的方法
2018/09/27 Python
Python 限制线程的最大数量的方法(Semaphore)
2019/02/22 Python
python GUI库图形界面开发之PyQt5图片显示控件QPixmap详细使用方法与实例
2020/02/27 Python
外国语学院毕业生自荐信
2013/10/28 职场文书
演讲比赛获奖感言
2014/02/02 职场文书
幼儿园标语大全
2014/06/19 职场文书
2016领导干部廉洁从政心得体会
2016/01/19 职场文书