【问题标题】:Structure of big nodejs project - How to handle interdependencies大型nodejs项目的结构 - 如何处理相互依赖关系
【发布时间】:2013-06-22 14:18:41
【问题描述】:

我有一个 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 来清理内容,但这仍然让我不得不保存实用程序之类的东西并将其传递给其他 require 调用。

我可以将每个 require 仅放在需要的较低模块中,但最终我会用我的 require 爬上目录结构,这看起来也很混乱,即:

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

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

任何建议。几天来,我一直在尝试对其进行重组,但我只是不停地用头撞墙,因为我没有做任何事情真的让它变得更好。

最好的节点项目布局是使用 mongoose、express、w/ 自定义模块之类的东西。并展示一种处理模块之间相互依赖关系的好方法。

【问题讨论】:

    标签: node.js


    【解决方案1】:

    编辑:https://github.com/gagle/node-getmod

    我也很头疼如何正确构建我的第一个真正的大型 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() 函数,您可以很好地控制您的模块。在我真实的大型项目中,我的 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);
      }
    };
    

    这是你要找的吗?

    【讨论】:

    • 它确实有帮助,因为没有“完美”或内置的解决方案。基本上是的,我坚持在文件夹中包含的模块中执行 require('../../utilities/util1.js') 。要么使用自定义函数来隐藏你必须使用相对路径。
    【解决方案2】:

    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; 
    

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

    【讨论】:

      猜你喜欢
      • 2021-02-21
      • 2016-08-14
      • 2021-10-24
      • 2014-10-22
      • 2017-09-20
      • 1970-01-01
      • 2015-11-02
      • 2012-12-14
      • 1970-01-01
      相关资源
      最近更新 更多