解析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获取网页中的js、css、Flash等文件
Dec 20 Javascript
Highslide.js是一款基于js实现的网页中图片展示插件
Mar 30 Javascript
javascript GUID生成器实现代码
Oct 31 Javascript
JavaScript字符串对象slice方法入门实例(用于字符串截取)
Oct 16 Javascript
牛叉的Jquery——Jquery与DOM对象的互相转换及DOM的三种操作
Oct 29 Javascript
Node.js中使用socket创建私聊和公聊聊天室
Nov 19 Javascript
javascript如何实现360度全景照片问题汇总
Apr 04 Javascript
jQuery中队列queue()函数的实例教程
May 03 Javascript
Vue项目全局配置微信分享思路详解
May 04 Javascript
JS 正则表达式验证密码、邮箱格式的实例代码
Oct 28 Javascript
从源码里了解vue中的nextTick的使用
Nov 22 Javascript
vue实现的网易云音乐在线播放和下载功能案例
Feb 18 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
第十一节 重载 [11]
2006/10/09 PHP
PHP实现多条件查询实例代码
2010/07/17 PHP
php中实现记住密码自动登录的代码
2011/03/02 PHP
PHP持久连接mysql_pconnect()函数使用介绍
2012/02/05 PHP
使用PHP导出Word文档的原理和实例
2013/10/21 PHP
destoon实现调用图文新闻的方法
2014/08/21 PHP
PHP函数nl2br()与自定义函数nl2p()换行用法分析
2016/04/02 PHP
Zend Framework实现自定义过滤器的方法
2016/12/09 PHP
php+websocket 实现的聊天室功能详解
2020/05/27 PHP
js自定义方法通过隐藏iframe实现文件下载
2013/02/21 Javascript
javascript对话框使用方法(警告框 javascript确认框 提示框)
2014/01/07 Javascript
js验证IP及子网掩码的合法性有效性示例
2014/04/30 Javascript
JS、CSS以及img对DOMContentLoaded事件的影响
2014/08/12 Javascript
JavaScript实现的简单幂函数实例
2015/04/17 Javascript
jQuery固定元素插件scrolltofixed使用指南
2015/04/21 Javascript
原生JS封装ajax 传json,str,excel文件上传提交表单(推荐)
2016/06/21 Javascript
基于Bootstrap的Java开发问题汇总(Spring MVC)
2017/01/15 Javascript
JS实现匀加速与匀减速运动的方法示例
2017/09/04 Javascript
jQuery实现的滑块滑动导航效果示例
2018/06/04 jQuery
socket io与vue-cli的结合使用的示例代码
2018/11/01 Javascript
mpvue+vant app搭建微信小程序的方法步骤
2019/02/11 Javascript
Python实现周期性抓取网页内容的方法
2015/11/04 Python
python numpy函数中的linspace创建等差数列详解
2017/10/13 Python
python实现数据写入excel表格
2018/03/25 Python
python实现飞机大战
2018/09/11 Python
python批量爬取下载抖音视频
2019/06/17 Python
pow在python中的含义及用法
2019/07/11 Python
PyTorch实现ResNet50、ResNet101和ResNet152示例
2020/01/14 Python
pytorch实现线性拟合方式
2020/01/15 Python
可能这些是你想要的H5软键盘兼容方案(小结)
2019/04/23 HTML / CSS
以设计师精品品质提供快速时尚:PopJulia
2018/01/09 全球购物
英国自行车商店:AW Cycles
2021/02/24 全球购物
请写出 BOOL flag 与"零值"比较的 if 语句
2016/02/29 面试题
研究生导师推荐信
2014/09/06 职场文书
晚自修旷课检讨书怎么写
2014/11/17 职场文书
利用Python将list列表写入文件并读取的方法汇总
2022/03/25 Python