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

时间:2023-01-05 16:55:51

I have a nodejs project that is getting rather large rather fast. Due to my limited understanding of modules and require I am sure that I can do some things to clean up the code and structure.

我有一个相当快的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

My app.js is pretty messy as I have dependencies between my files. IE I want to pass my models and authentication to my routes, utilities can be used by a bunch of things.

我的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

I now know that I can put an index.js in each folder to clean things up but that still leaves me with having to save off things like utilities and pass that into other require calls.

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

I can put each require in lower modules only where its needed but then I end up climbing the directory structure with my require which also seems messy, i.e.:

我可以将每个需求放在较低的模块中,仅在需要的地方,但最后我最终攀登目录结构,我的需求似乎也很混乱,即:

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

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

Basically I think my problem is that modules in lower level folders depend on other modules in other folders. With I feel like I should pull in all dependencies in app.js and pass them to the require modules that need them.

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

Any advice. I have been trying to restructure this for a couple days and I just keep banging my head against the wall as nothing I do is really making it any better.

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

Best would be a good node project layout that uses things like mongoose, express, w/ custom modules. and show a good way to handle interdependencies between modules.

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

2 个解决方案

#1


2  

Edit: https://github.com/gagle/node-getmod

I also had headaches to properly structure my first real and BIG node.js project. The biggest problem you have is the relative path used in the require() calls. It's a pain because these paths are relative to the current file, so you tipically have paths like these:

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

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

All of them pointing to the same file. This is inhuman. Hard to read, hard to maintain.

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

You shouldn't put your modules inside the node_modules directory and simply require the module by its name (require("a")) because this directory is used by third party modules. If you need to do maintenance tasks, like perform a full upgrade of all modules, deleting them and installing them again, etc. they are extremly easy and safe to do. If you put your there your modules you'll have a big problem if you don't have a good documentation and you work in a medium-big team.

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

After a few hours I ended with this technique:

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

NodeJS local modules for complex application structures

用于复杂应用程序结构的NodeJS本地模块

With the mod() function you have a good control over your modules. In my real and BIG project my mod function is the following:

使用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);
};

If I call to mod("api") it returns my api module, the core of my website.

如果我调用mod(“api”)它会返回我的api模块,这是我网站的核心。

If I call to mod("common/db") it returns the db wrapper.

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

If I call to mod("build/...") it returns the module needed to build the static assets (compiles css and js)

如果我调用mod(“build / ...”),它将返回构建静态资产所需的模块(编译css和js)

etc


Now, you misunderstand how the modules must be used. Example:

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

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
}

Here you are passing a the utilities module to another module and this is not needed. You can get the utilities module from inside the model1 and model2 modules.

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

Very basic example:

很基本的例子:

A depends on B

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);
  }
};

You don't need to do this:

你不需要这样做:

//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);
  }
};

Is this what you are looking for?

这是你想要的?

#2


1  

1- create a file in the project root call it settings.js

1-在项目根目录中创建一个文件,调用它settings.js

2- inside this file add this code

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

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

3- inside node_modules create a new module name it "settings" and inside the module index.js write this code:

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

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

4- and any time you want your project directory just use

4-以及您希望项目目录使用的任何时间

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

in this way you will have all project directories relative to this file ;)

通过这种方式,您将拥有相对于此文件的所有项目目录;)

#1


2  

Edit: https://github.com/gagle/node-getmod

I also had headaches to properly structure my first real and BIG node.js project. The biggest problem you have is the relative path used in the require() calls. It's a pain because these paths are relative to the current file, so you tipically have paths like these:

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

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

All of them pointing to the same file. This is inhuman. Hard to read, hard to maintain.

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

You shouldn't put your modules inside the node_modules directory and simply require the module by its name (require("a")) because this directory is used by third party modules. If you need to do maintenance tasks, like perform a full upgrade of all modules, deleting them and installing them again, etc. they are extremly easy and safe to do. If you put your there your modules you'll have a big problem if you don't have a good documentation and you work in a medium-big team.

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

After a few hours I ended with this technique:

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

NodeJS local modules for complex application structures

用于复杂应用程序结构的NodeJS本地模块

With the mod() function you have a good control over your modules. In my real and BIG project my mod function is the following:

使用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);
};

If I call to mod("api") it returns my api module, the core of my website.

如果我调用mod(“api”)它会返回我的api模块,这是我网站的核心。

If I call to mod("common/db") it returns the db wrapper.

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

If I call to mod("build/...") it returns the module needed to build the static assets (compiles css and js)

如果我调用mod(“build / ...”),它将返回构建静态资产所需的模块(编译css和js)

etc


Now, you misunderstand how the modules must be used. Example:

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

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
}

Here you are passing a the utilities module to another module and this is not needed. You can get the utilities module from inside the model1 and model2 modules.

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

Very basic example:

很基本的例子:

A depends on B

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);
  }
};

You don't need to do this:

你不需要这样做:

//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);
  }
};

Is this what you are looking for?

这是你想要的?

#2


1  

1- create a file in the project root call it settings.js

1-在项目根目录中创建一个文件,调用它settings.js

2- inside this file add this code

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

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

3- inside node_modules create a new module name it "settings" and inside the module index.js write this code:

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

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

4- and any time you want your project directory just use

4-以及您希望项目目录使用的任何时间

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

in this way you will have all project directories relative to this file ;)

通过这种方式,您将拥有相对于此文件的所有项目目录;)