在Node应用中避免“Dot Hell”
转载自: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”的更多相关文章
- 在node.js中,使用基于ORM架构的Sequelize,操作mysql数据库之增删改查
Sequelize是一个基于promise的关系型数据库ORM框架,这个库完全采用JavaScript开发并且能够用在Node.JS环境中,易于使用,支持多SQL方言(dialect),.它当前支持M ...
- 如何在Node.js中合并两个复杂对象
通常情况下,在Node.js中我们可以通过underscore的extend或者lodash的merge来合并两个对象,但是对于像下面这种复杂的对象,要如何来应对呢? 例如我有以下两个object: ...
- Node.js中的Session,不要觉得简单哦。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,博客地址为http://www.cnblogs.com/jasonnode/ .学习网站上有对应 ...
- Node.js 中MongoDB的基本接口操作
Node.js 中MongoDB的基本接口操作 连接数据库 安装mongodb模块 导入mongodb模块 调用connect方法 文档的增删改查操作 插入文档 方法: db.collection(& ...
- 在node.js中使用COOKIE
node.js中如何向客户端发送COOKIE呢?有如下两个方案: 一.使用response.writeHead,代码示例: //设置过期时间为一分钟 var today = new Date(); v ...
- 初步揭秘node.js中的事件
当你学习node.js的时候,Events是一个非常重要的需要理解的事情.非常多的Node对象触发事件,你能在文档API中找到很多例子.但是关于如何写自己的事件和监听,你可能还不太清楚.如果你不了解, ...
- Node.js权威指南 (10) - Node.js中的错误处理与断言处理
10.1 使用domain模块处理错误 / 272 10.1.1 domain模块概述 / 272 10.1.2 创建并使用Domain对象 / 274 10.1.3 隐式绑定与显式绑定 / 276 ...
- Node.js中的URL
Node.js中的URL 什么是URL URL是Uniform Location Resource的缩写,翻译为"统一资源定位符",也就是描述资源位置的固定表示方法.被URL描述的 ...
- mysql语句在node.js中的写法
总结一下mysql语句在node.js中的各种写法,参考了npm网站mysql模块给的实例. 查询 select //1 db.query('select * from tuanshang_users ...
随机推荐
- loading加载动画
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Windows平台的PHP之开启COM配置
Windows平台的PHP如果未配置COM,调用COM组件,错误如下 Fatal error: Class 'COM' not found in XXXXXXXXX php 根目录的 ext 文件夹下 ...
- javascript学习笔记02--面向对象学习
js面向对象编程 1. javascript 是一种基于对象的编程 object-based(基于对象):遇到的所有对象都是对象2.javascript没有类class,但是有新的原型对象,习 ...
- Flex中的FusionCharts 3D柱形图
1.3D柱形图源码 <?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:f ...
- Excel 2010高级应用-圆环图(七)
Excel 2010高级应用-圆环图(七) 基本操作如下: 1.新建空白Excel文档,并命名为圆环图 2.单击"插入",并找到圆环图图样 3.单击圆环图图样,并在空白文档上生成图 ...
- Linux显示目前与过去登入系统的用户相关信息
Linux显示目前与过去登入系统的用户相关信息 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ last youhaido pts/0 :0 Sat Jan 2 ...
- .Net Core下 Redis的String Hash List Set和Sorted Set的例子
1.新建一个.Net Core控制台应用程序,用Nuget导入驱动 打开程序包管理控制台, 执行以下代码. PM> Install-Package ServiceStack.Redis 即可添加 ...
- 在TextBox中敲击回车执行ASP.NET后台事件
1.在TextBox中敲击回车执行ASP.NET后台事件 0.说明 页面中有一个用于搜索的TextBox,希望能在输入内容后直接回车开始搜索,而不是手动去点击它旁边的搜索按钮 但因为该TextBo ...
- SpringMVC 框架系列之初识与入门实例
微信公众号:compassblog 欢迎关注.转发,互相学习,共同进步! 有任何问题,请后台留言联系! 1.SpringMVC 概述 (1). MVC:Model-View-Control Contr ...
- 【HNOI2004】宠物收养所(splay)
题面 Description 最近,阿Q开了一间宠物收养所.收养所提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物.每个领养者都希望领养到自己满意的宠物,阿Q根据领养者的要求通过他自己发明的 ...