Javascript 如何构建 express.js 应用程序?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7732293/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 03:22:11  来源:igfitidea点击:

How to structure a express.js application?

javascriptnode.jsmodularityexpress

提问by Eric the Red

Is there a common convention for breaking up and modularizing the app.jsfile in an Express.jsapplication? Or is it common to keep everything in a single file?

app.jsExpress.js应用程序中是否有用于分解和模块化文件的通用约定?还是将所有内容保存在一个文件中很常见?

采纳答案by Chance

I have mine broken up as follows:

我的分解如下:

~/app
|~controllers
| |-monkey.js
| |-zoo.js
|~models
| |-monkey.js
| |-zoo.js
|~views
| |~zoos
|   |-new.jade
|   |-_form.jade
|~test
|  |~controllers
|    |-zoo.js
|  |~models
|    |-zoo.js
|-index.js

I use Exports to return what's relevant. For instance, in the models I do:

我使用 Exports 返回相关内容。例如,在我做的模型中:

module.exports = mongoose.model('PhoneNumber', PhoneNumberSchema);

and then if I need to create a phone number, it's as simple as:

然后如果我需要创建一个电话号码,就像这样简单:

var PhoneNumber = require('../models/phoneNumber');
var phoneNumber = new PhoneNumber();

if I need to use the schema, then PhoneNumber.schema

如果我需要使用架构,那么 PhoneNumber.schema

(which assumes that we are working from the routes folder and need to go 1 level up and then down to models)

(假设我们正在从 routes 文件夹工作,并且需要向上一级然后向下一级到模型)



EDIT 4

编辑 4

The express wikihas a list of frameworks built on top of it.

快递维基具有建立在它之上的框架的列表。

Of those, I think Twitter's matadoris structured pretty well. We actually used a very similar approach to how they load up parts of the app.

其中,我认为 Twitter 的斗牛士结构非常好。我们实际上使用了一种非常相似的方法来加载应用程序的各个部分。

derby.jsalso looks extremely interesting. It's akin to meteorwithout all of the hype and actually gives credit where credit is due (notably, node and express).

derby.js看起来也非常有趣。它类似于没有所有炒作的流星,实际上在信用到期时给予信用(特别是节点和快递)。



EDIT 3

编辑 3

If you are a fan of CoffeeScript (I am not) and reeeeaaaaaally want the L&F of Rails, there is also Tower.js.

如果您是 CoffeeScript 的粉丝(我不是)并且 reeeeaaaaaly 想要 Rails 的 L&F,那么还有Tower.js



EDIT 2

编辑 2

If you are familiar with Rails and don't mind the bleed-over of some concepts there is Locomotive. It is a light-weight framework built on Express. It has a very similar structure as RoR and carries over some of the more rudimentary concepts (such as routing).

如果您熟悉 Rails 并且不介意某些概念的混淆,那就是Locomotive。它是一个基于 Express 构建的轻量级框架。它具有与 RoR 非常相似的结构,并继承了一些更基本的概念(例如路由)。

It's worth checking out even if you don't plan to use it.

即使您不打算使用它,也值得一试。



EDIT 1

编辑 1

nodejs-express-mongoose-demois very similar to how I have mine structured. Check it out.

nodejs-express-mongoose-demo与我的结构非常相似。一探究竟。

回答by Raynos

Warning:referencing code I hacked together for node knockout, it kind of works but is far from elegant or polished.

警告:引用我为节点淘汰而编写的代码,它有点工作,但远非优雅或优美。

To be more specific about splitting up app.jsI have the following app.jsfile

更具体地说,app.js我有以下app.js文件

var express = require('express'),
    bootstrap = require('./init/bootstrap.js'),
    app = module.exports = express.createServer();

bootstrap(app);

This basically means I place all my bootstrapping in a seperate file, then I bootstrap the server.

这基本上意味着我将所有引导程序放在一个单独的文件中,然后我引导服务器。

So what does bootstrapdo?

那么bootstrap有什么作用呢?

var configure = require("./app-configure.js"),
    less = require("./watch-less.js"),
    everyauth = require("./config-everyauth.js"),
    routes = require("./start-routes.js"),
    tools = require("buffertools"),
    nko = require("nko"),
    sessionStore = new (require("express").session.MemoryStore)()

module.exports = function(app) {
    everyauth(app);
    configure(app, sessionStore);
    less();
    routes(app, sessionStore);
    nko('/9Ehs3Dwu0bSByCS');


    app.listen(process.env.PORT);
    console.log("server listening on port xxxx");
};

Well it splits all the server initialization setup in nice chunks. Specifically

好吧,它把所有的服务器初始化设置分成了很好的块。具体来说

  • I have a chunk that sets up all my remote OAuth authentication using everyauth.
  • I have a chunk that configures my application (basically calling app.configure)
  • I have a little bit of code that punches less so it re-compiles any of my less into css at run time.
  • I have code that sets up all my routes
  • I call this small nko module
  • Finally I start the server by listening to a port.
  • 我有一个使用everyauth 设置我所有远程OAuth 身份验证的块。
  • 我有一个配置我的应用程序的块(基本上是调用app.configure
  • 我有一些代码较少,因此它在运行时将我的任何较少内容重新编译为 css。
  • 我有设置我所有路线的代码
  • 我称这个小 nko 模块
  • 最后,我通过侦听端口来启动服务器。

Just for example let's look at the routingfile

举个例子,让我们看看路由文件

var fs = require("fs"),
    parseCookie = require('connect').utils.parseCookie;

module.exports = function(app, sessionStore) {
    var modelUrl = __dirname + "/../model/",
        models = fs.readdirSync(modelUrl),
        routeUrl = __dirname + "/../route/"
        routes = fs.readdirSync(routeUrl);

Here I load all my models and routes as arrays of files.

在这里,我将所有模型和路由加载为文件数组。

Disclaimer:readdirSyncis only ok when called before you start the http server(before .listen). Calling synchronious blocking calls at server start time just makes the code more readable (it's basically a hack)

免责声明:readdirSync在启动 http 服务器之前(之前.listen)调用时才可以。在服务器启动时调用同步阻塞调用只会使代码更具可读性(这基本上是一种黑客攻击)

    var io = require("socket.io").listen(app);

    io.set("authorization", function(data, accept) {
        if (data.headers.cookie) {
            data.cookie = parseCookie(data.headers.cookie);

            data.sessionId = data.cookie['express.sid'];

            sessionStore.get(data.sessionId, function(err, session) {

                if (err) {
                    return accept(err.message, false);
                } else if (!(session && session.auth)) {
                    return accept("not authorized", false)
                }
                data.session = session;
                accept(null, true);
            });
        } else {
            return accept('No cookie', false);
        }
    });

Here I punch socket.io to actually use authorization rather then letting any tom and Hyman to talk to my socket.io server

在这里,我使用 socket.io 实际使用授权,而不是让任何 tom 和 Hyman 与我的 socket.io 服务器交谈

    routes.forEach(function(file) {
        var route = require(routeUrl + file),
            model = require(modelUrl + file);

        route(app, model, io);
    });
};

Here I start my routes by passing the relevant model into each route object returned from the route file.

在这里,我通过将相关模型传递到从路由文件返回的每个路由对象来开始我的路由。

Basically the jist is you organize everything into nice little modules and then have some bootstrapping mechanism.

基本上 jist 是你将所有东西组织成漂亮的小模块,然后有一些引导机制。

My other project (my blog) has an init file with a similar structure.

我的另一个项目(我的博客)有一个类似结构的 init 文件

Disclaimer:the blog is broken and doesn't build, I'm working on it.

免责声明:该博客已损坏且无法构建,我正在努力。

回答by Alexander Bykhov

For maintainable routing organisation you can check out this articleabout the express-routescannode moduleand try it. This is the best solution for me.

为了维护路由组织你可以看看这篇文章有关明示,routescan节点模块和尝试。这对我来说是最好的解决方案。

回答by JKleinne

I have my apps build on top of the express-generator tool. You can install it by running npm install express-generator -gand run it using express <APP_NAME>.

我的应用程序构建在 express-generator 工具之上。您可以通过运行安装它 npm install express-generator -g并使用express <APP_NAME>.

To give you a perspective, one of my smaller application's structure looked like this:

为了给您一个视角,我的一个较小的应用程序结构如下所示:

~/
|~bin
| |-www
|
|~config
| |-config.json
|
|~database
| |-database.js
|
|~middlewares
| |-authentication.js
| |-logger.js
|
|~models
| |-Bank.js
| |-User.js
|
|~routes
| |-index.js
| |-banks.js
| |-users.js
|
|~utilities
| |-fiat-converersion.js
|
|-app.js
|-package.json
|-package-lock.json

One cool thing I like about this structure I end up adopting for any express application I develop is the way the routes are organized. I did not like having to require each route files into the app.js and app.use()each route, especially as the file gets bigger. As such, I found it helpful to group and centralize all my app.use()on a ./routes/index.js file.

我喜欢这种结构的一件很酷的事情是我最终在我开发的任何快速应用程序中采用的这种结构是路由的组织方式。我不喜欢将每个路由文件都要求到 app.js 和app.use()每个路由中,尤其是当文件变大时。因此,我发现将我的所有内容分组和集中app.use()在 ./routes/index.js 文件中很有帮助。

In the end, my app.js will look something like this:

最后,我的 app.js 将如下所示:

...
const express = require('express');
const app = express();

...
require('./routes/index')(app);

and my ./routes/index.js will look something like this:

我的 ./routes/index.js 看起来像这样:

module.exports = (app) => {
  app.use('/users', require('./users'));
  app.use('/banks', require('./banks'));
};

I am able to simply require(./users)because I wrote the users route using express.Router() which allows me to "group" multiple routes and then export them at once, with the goal of making the application more modular.

我之所以能够这样做,仅仅require(./users)是因为我使用 express.Router() 编写了用户路由,它允许我“分组”多个路由,然后一次导出它们,目的是使应用程序更加模块化。

This is an example of what you would fine on my ./routers/users.js route:

这是您可以在我的 ./routers/users.js 路由上使用的示例:


const router = require('express').Router();

router.post('/signup', async (req, res) => {
    // Signup code here
});

module.exports = router;

Hopefully this helped answer your question! Best of luck!

希望这有助于回答您的问题!祝你好运!