大型nodejs项目的结构 - 如何处理相互依赖性

时间:2013-06-22 14:18:42

标签: node.js

我有一个相当快的nodejs项目。由于我对模块的理解有限,并且要求我确信我可以做一些事情来清理代码和结构。

<app dir>
  -app.js
  - <modules>
     -module1.js
     -module2.js
  - <routes>
     -route1.js
     -route2.js
  - <utilties>
     -utility1.js
     -utility2.js
  - <authentication>
     -local.js
     -basic.js
     -index.js

我的app.js非常混乱,因为我的文件之间存在依赖关系。 IE我想将我的模型和身份验证传递给我的路由,实用程序可以被一堆东西使用。

var app = express();
... // do express setup

var authenticationStrategy = // get auth strategy from config
var auth = require('./auth)(authenticationStrategy);

var utility1 = require('./utilities/utility1.js');
var utility2 = require('./utilities/utility2.js');
var utilities = {
  utility1: utility1,
  utility2: utility2
}

var Model1 = require('./models/model1')(utilities);
var Model2 = require('./models/model2')(utility1);
var models = {
  Model1: Model1,
  Model2: Model2
}

// Dynamically import all routes
fs.readdirSync('routes').forEach(function(file) {
  if (file[0] == '.') return;
  var route = file.substr(0, file.indexOf('.'));
  require('./routes/' + route)(app, models, utilities);
});

...

etc

我现在知道我可以在每个文件夹中放置一个index.js来清理,但这仍然让我不得不保存像实用程序这样的东西并将其传递给其他需要的调用。

我可以将每个需求放在较低的模块中,只在需要的地方使用,然后我最终使用我的需求爬上目录结构,这看起来很麻烦,即:

model1.js: var utility1 = require('../ utilities / utility1.js');

基本上我认为我的问题是较低级别文件夹中的模块依赖于其他文件夹中的其他模块。我觉得我应该在app.js中引入所有依赖项并将它们传递给需要它们的require模块。

任何建议。我一直试图对这个问题进行重组几天,我只是不停地撞到墙上,因为我所做的一切都没有让它变得更好。

Best是一个很好的节点项目布局,使用像mongoose,express,w / custom模块这样的东西。并展示了处理模块之间相互依赖关系的好方法。

2 个答案:

答案 0 :(得分:2)

修改:https://github.com/gagle/node-getmod

我也很难正确构建我的第一个真实和BIG node.js项目。您遇到的最大问题是require()调用中使用的相对路径。这是一种痛苦,因为这些路径是相对于当前文件的,所以你要有这样的路径:

../../../a.js
./a/b/c/a.js
../../a/b/c/a.js

所有这些都指向同一个文件。这是不人道的。难以阅读,难以维护。

您不应该将您的模块放在node_modules目录中,只需要模块名称(require("a")),因为该目录由第三方模块使用。如果您需要执行维护任务,例如执行所有模块的完全升级,删除它们并再次安装它们等,那么它们极其简单且安全。如果你把你的模块放在那里,如果你没有一份好的文档并且你在一个中等大的团队中工作,那么你会遇到很大的问题。

几个小时后,我以这种技术结束了:

NodeJS local modules for complex application structures

使用mod()功能,您可以很好地控制模块。在我的真实和BIG项目中,我的mod函数如下:

"use strict";

var serverType = require ("./server-type");

global.mod = function (file){
    var dir = file.substring (0, file.search (/\/|\\/));
    if (!dir) dir = file;
    if (dir === "browser" || dir === "common" || dir === "mobile" ||
            dir === "stream"){
        //Relative from the web directory
        return require ("../" + file);
    }
    if (dir === "api"){
        //Relative from the api directory
        return require ("../../" + (file === "api" || file === "api/latest"
                ? file
                : "api/" + APP.versions.api + "/" + file.substring (4)));
    }
    if (dir === "build"){
        //Relative from the build directory
        return require ("../../" + file);
    }
    //Tries to load the module inside browser or mobile directories depending on
    //the cwd
    return require ("../" + serverType () + "/" + file);
};

如果我致电mod("api"),它会返回我的api模块,这是我网站的核心。

如果我调用mod("common/db"),它将返回db包装器。

如果我打电话给mod("build/..."),它会返回构建静态资产所需的模块(编译css和js)


现在,您误解了必须如何使用模块。例如:

var utility1 = require('./utilities/utility1.js');
var utility2 = require('./utilities/utility2.js');
var utilities = {
  utility1: utility1,
  utility2: utility2
}

var Model1 = require('./models/model1')(utilities);
var Model2 = require('./models/model2')(utility1);
var models = {
  Model1: Model1,
  Model2: Model2
}

在这里,您将实用程序模块传递给另一个模块,这不是必需的。您可以从model1和model2模块中获取实用程序模块。

非常基本的例子:

A取决于B

//app.js
require ("./a").a ();

//a.js
var b = require ("./b");
module.exports = {
  a: function (){
    b.b ("I'm A");
  }
};

//b.js
module.exports = {
  b: function (msg){
    console.log ("B says: " + msg);
  }
};

您不需要这样做:

//app.js
var b = require ("./b");
require ("./a").a (b);

//a.js
module.exports = {
  a: function (b){
    b.b ("I'm A");
  }
};

//b.js
module.exports = {
  b: function (msg){
    console.log ("B says: " + msg);
  }
};

这是你在找什么?

答案 1 :(得分:1)

1-在项目根目录中创建一个文件,将其命名为 settings.js

2-在此文件中添加此代码

module.exports = {
    POST_MAX_SIZE : 40 , //MB
    UPLOAD_MAX_FILE_SIZE: 40, //MB
    PROJECT_DIR : __dirname
};

3-在node_modules内部创建一个新的模块名称“settings”并在模块index.js里面写下这段代码:

module.exports = require("../../settings");

4-并且只要您希望项目目录使用

var settings = require("settings");
settings.PROJECT_DIR; 

以这种方式,你将拥有与该文件相关的所有项目目录;)