解析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 相关文章推荐
运用Windows XP附带的Msicuu.exe、Msizap.exe来彻底卸载顽固程序
Apr 21 Javascript
JSDoc 介绍使用规范JsDoc的使用介绍
Feb 12 Javascript
关于js中alert弹出窗口文本换行问题简单详细说明
Dec 11 Javascript
针对JavaScript中this指向的简单理解
Aug 26 Javascript
jquery滚动条插件(可以自定义)
Dec 11 Javascript
JavaScript中 DOM操作方法小结
Apr 25 Javascript
layer弹窗插件操作方法详解
May 19 Javascript
angularjs2中父子组件的数据传递的实例代码
Jul 05 Javascript
浅谈Vue.js中如何实现自定义下拉菜单指令
Jan 06 Javascript
详解Vue3.0 前的 TypeScript 最佳入门实践
Jun 18 Javascript
maptalks+three.js+vue webpack实现二维地图上贴三维模型操作
Aug 10 Javascript
javascript中call,apply,bind的区别详解
Dec 11 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
全国FM电台频率大全 - 13 福建省
2020/03/11 无线电
随时给自己贴的图片加文字的php水印
2007/03/16 PHP
PHP的伪随机数与真随机数详解
2015/05/27 PHP
WordPress主题中添加文章列表页页码导航的PHP代码实例
2015/12/22 PHP
PHP下SSL加密解密、验证、签名方法(很简单)
2020/06/28 PHP
PHP设计模式(一)工厂模式Factory实例详解【创建型】
2020/05/02 PHP
javascript delete 使用示例代码
2010/03/29 Javascript
JQuery自定义事件的应用 JQuery最佳实践
2010/08/01 Javascript
nodejs教程 安装express及配置app.js文件的详细步骤
2013/05/11 NodeJs
jquery实现通用版鼠标经过淡入淡出效果
2014/06/15 Javascript
jQuery实现弹出窗口中切换登录与注册表单
2015/06/05 Javascript
微信小程序开发教程之增加mixin扩展
2017/08/09 Javascript
解决vue接口数据赋值给data没有反应的问题
2018/08/27 Javascript
js作用域和作用域链及预解析
2019/04/11 Javascript
[53:36]Liquid vs VP Supermajor决赛 BO 第三场 6.10
2018/07/05 DOTA
[53:15]Newbee vs Pain 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
详解Python中for循环的使用
2015/04/14 Python
python实现windows下文件备份脚本
2018/05/27 Python
python实现将读入的多维list转为一维list的方法
2018/06/28 Python
Django实战之用户认证(用户登录与注销)
2018/07/16 Python
200行python代码实现2048游戏
2019/07/17 Python
对Tensorflow中tensorboard日志的生成与显示详解
2020/02/04 Python
Python实现分数序列求和
2020/02/25 Python
python 安装库几种方法之cmd,anaconda,pycharm详解
2020/04/08 Python
tensorflow指定CPU与GPU运算的方法实现
2020/04/21 Python
python 抓取知乎指定回答下视频的方法
2020/07/09 Python
Grid 宫格常用布局的实现
2020/01/10 HTML / CSS
个人自我评价范文
2014/02/05 职场文书
大学生作弊检讨书
2014/02/19 职场文书
新春文艺演出主持词
2014/03/27 职场文书
数学教研活动总结
2014/07/02 职场文书
2014党员学习习主席讲话思想汇报
2014/09/15 职场文书
邀请书格式范文
2015/02/02 职场文书
2019新员工试用期转正申请书3篇
2019/08/13 职场文书
阿里面试Nacos配置中心交互模型是push还是pull原理解析
2022/07/23 Java/Android
python playwright之元素定位示例详解
2022/07/23 Python