转载自:http://blog.leapoahead.com/2015/09/03/prevent-node-require-dot-hell/

在Node应用中,我们使用require来加载模块。在目录层次相对复杂的应用中,总是会出现类似require('../../../../../module')的调用,我把它称之为Dot Hell。我用了一些时间研究现有的解决方案,并介绍我个人认为最好的方法。

在Node中的全局对象是global,它就像浏览器的window对象一样。global对象下面的方法都可以直接调用。

1
2
global.a = 1
require('assert').equal(1, a)

因此最简单的方法,也是我认为最好的方式就是在global下创建一个appRequire方法作为require方法的包装,appRequire方法专门用于调用应用内的包。

1
2
3
4
var path = require('path')
global.appRequire = function(path) {
return require(path.resolve(__dirname, path))
}

假设我们的项目目录结构如下

1
2
3
4
5
6
7
8
├── app
│   ├── controller
│   │   └── AppController.js
│   ├── model
│   │   └── User.js
│   └── view
│   └── AppView.js
└── app.js

其中app.js是应用的入口。那么我们只需要在app.js中应用上面的代码,那么在整个应用程序中就都可以使用了。

例如,现在在app/controller/AppController.js中,我们可以用下面的语句调用app/model/User.js

1
var User = appRequire('app/model/User')

Oh Yeah! 一切都很优雅,很顺利。

但是一个应用中一定还会有测试代码。以单元测试为例,我们如果用mocha之类的Task Runner去运行测试的话,就得在每个测试前面都加上这一段代码,这样做很容易出错,而且很麻烦。

所以,我们可以把上述的封装代码单独封装成一个文件global-bootstrap.js,在运行mocha的时候,用mocha的require参数来指定每次运行测试之前要加载global-bootstrap.js

1
2
3
# 用Mocha运行tests文件夹下面的所有测试
# 在运行的时候加载should库,以及我们封装的含有appRequire函数的文件
mocha --require should --require global-bootstrap.js --recursive tests

其他方案

对于解决这个问题,还有两种方案:NODE_ENV方案(及其变种)Symlink方案,你可以在这里看到。

我认为应该避免使用这两种方案。虽然这两种方案都可行,但是它们都会可能导致应用自身的目录名和node模块名冲突。例如,在下面的结构中,使用require('request')就很容易产生二义性。

1
2
3
4
5
.
├── node_modules
│   └── request
└── request
└── index.js

总结

我一直认为Node的模块引用方式的设计是有问题的,Dot Hell就很能说明这点。而Python相对而言就优雅很多,你可以直接通过路径的形式来导入包(在正确配置的情况下)。本文的解决方案允许我们用类似Python的方式去加载模块,你可以在我的项目webcraft中看到其应用。

在Node应用中避免“Dot Hell”

在Node应用中避免“Dot Hell”的更多相关文章

  1. 在node.js中,使用基于ORM架构的Sequelize,操作mysql数据库之增删改查

    Sequelize是一个基于promise的关系型数据库ORM框架,这个库完全采用JavaScript开发并且能够用在Node.JS环境中,易于使用,支持多SQL方言(dialect),.它当前支持M ...

  2. 如何在Node.js中合并两个复杂对象

    通常情况下,在Node.js中我们可以通过underscore的extend或者lodash的merge来合并两个对象,但是对于像下面这种复杂的对象,要如何来应对呢? 例如我有以下两个object: ...

  3. Node.js中的Session,不要觉得简单哦。

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,博客地址为http://www.cnblogs.com/jasonnode/ .学习网站上有对应 ...

  4. Node.js 中MongoDB的基本接口操作

    Node.js 中MongoDB的基本接口操作 连接数据库 安装mongodb模块 导入mongodb模块 调用connect方法 文档的增删改查操作 插入文档 方法: db.collection(& ...

  5. 在node.js中使用COOKIE

    node.js中如何向客户端发送COOKIE呢?有如下两个方案: 一.使用response.writeHead,代码示例: //设置过期时间为一分钟 var today = new Date(); v ...

  6. 初步揭秘node.js中的事件

    当你学习node.js的时候,Events是一个非常重要的需要理解的事情.非常多的Node对象触发事件,你能在文档API中找到很多例子.但是关于如何写自己的事件和监听,你可能还不太清楚.如果你不了解, ...

  7. Node.js权威指南 (10) - Node.js中的错误处理与断言处理

    10.1 使用domain模块处理错误 / 272 10.1.1 domain模块概述 / 272 10.1.2 创建并使用Domain对象 / 274 10.1.3 隐式绑定与显式绑定 / 276 ...

  8. Node.js中的URL

    Node.js中的URL 什么是URL URL是Uniform Location Resource的缩写,翻译为"统一资源定位符",也就是描述资源位置的固定表示方法.被URL描述的 ...

  9. mysql语句在node.js中的写法

    总结一下mysql语句在node.js中的各种写法,参考了npm网站mysql模块给的实例. 查询 select //1 db.query('select * from tuanshang_users ...

随机推荐

  1. Google最新的图片格式WEBP全面解析

    前言 不管是 PC 还是移动端,图片一直是流量大头,以苹果公司 Retina 产品为代表的高 PPI 屏对图片的质量提出了更高的要求,如何保证在图片的精细度不降低的前提下缩小图片体积,成为了一个有价值 ...

  2. java Socket实现简单在线聊天(一)

    最近的项目有一个在线网页交流的需求,由于很久以前做过的demo已经忘记的差不多了,因此便重新学习一下. 我计划的大致实现步骤分这样几大步: 1.使用awt组件和socket实现简单的单客户端向服务端持 ...

  3. Activiti 实战篇 小试牛刀

    原文地址:http://blog.csdn.net/qq_30739519/article/details/51166062 1:工作流的概念   说明: 1) 假设:这两张图就是华谊兄弟的请假流程图 ...

  4. R语言︱list用法、批量读取、写出数据时的用法

    列表是一种特别的对象集合,它的元素也由序号(下标)区分,但是各元素的类型可 以是任意对象,不同元素不必是同一类型.元素本身允许是其它复杂数据类型,比如,列表 的一个元素也允许是列表.例如: > ...

  5. MinnowBoard MAX 硬件开发板

    Minnowboard MAX MinnowBoard MAX是一款紧凑型,经济实惠,而且功能强大的开发板为专业人士和制造商.开放式的硬件设计使无尽的定制和集成的潜力.它采用64位英特尔®凌动™E38 ...

  6. (二十三)mongodb中group的问题

    今天的工作中我需要从mongodb数据库中查出一定的数据,并排序后返回给前台,数据库表中包含了ruleID,processingID,userID,updateTime等字段.    同一个ruleI ...

  7. Minimum Inversion Number~hdu 1394

    The inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that ...

  8. 前台序列化传过来的值,后台获取之后封装到map当中,让后在转化成json格式,最后在把json里面的参数里面的某一个值进行分割,最后在存到json格式的数据中去。

    一,html脚本 <script type="text/javascript"> $(function() { $(".btn-submit").c ...

  9. 异常-----freemarker.core.NonStringException

    一,案例一 1.1.错误描述 <html> <head> <meta http-equiv="content-type" content=" ...

  10. 一:学习Linux前准备工作

    1:虚拟机,网站上有很多种类的虚拟机,找一款适合自己用的.我这里使用的是 Virtual Box 下载地址:https://www.virtualbox.org/ 安装虚拟机 一路 Next 就可以. ...