web-dev-qa-db-fra.com

Comment structurer une application express.js?

Existe-t-il une convention commune pour scinder et modulariser le app.js fichier dans une application Express.js? Ou est-il courant de tout conserver dans un seul fichier?

102
Eric the Red

J'ai le mien divisé comme suit:

~/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

J'utilise Exports pour renvoyer ce qui est pertinent. Par exemple, dans les modèles que je fais:

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

et puis si j'ai besoin de créer un numéro de téléphone, c'est aussi simple que:

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

si j'ai besoin d'utiliser le schéma, alors PhoneNumber.schema

(ce qui suppose que nous travaillons à partir du dossier routes et que nous devions passer d'un niveau à un autre puis aux modèles)


EDIT 4

Le wiki express contient une liste de cadres construits par-dessus.

Parmi ceux-ci, je pense que Twitter matador est assez bien structuré. Nous avons en fait utilisé une approche très similaire pour charger certaines parties de l'application.

derby.js semble également extrêmement intéressant. Cela s'apparente à météore sans tout le battage publicitaire et donne en réalité un crédit là où le crédit est dû (notamment noeud et express).


EDIT 3

Si vous êtes fan de CoffeeScript (je ne le suis pas) et que vous voulez vraiment le L & F de Rails, il y a aussi Tower.js.


EDIT 2

Si vous connaissez Rails et ne vous inquiétez pas du fiasco de certains concepts, il y a Locomotive. Il s’agit d’un framework léger construit sur Express, dont la structure est très similaire à celle de RoR et qui reprend certains des concepts les plus rudimentaires (tels que le routage).

Cela vaut la peine de vérifier même si vous ne prévoyez pas de l'utiliser.


EDIT 1

nodejs-express-mongoose-demo est très similaire à la façon dont j'ai structuré le mien. Vérifiez-le.

82
Chance

Avertissement: référençant le code que j'ai piraté ensemble pour le knock-out du nœud, cela fonctionne mais il est loin d'être élégant ou poli.

Pour être plus précis sur la scission app.js J'ai le fichier app.js suivant

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

bootstrap(app);

Cela signifie essentiellement que je place tous mes fichiers d'amorçage dans un fichier séparé, puis je bootstrap le serveur).

Alors qu'est-ce que bootstrap fait?

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

Eh bien, il divise l’ensemble de la configuration d’initialisation du serveur en gros morceaux. Plus précisément

  • J'ai un morceau qui configure toute mon authentification à distance OAuth en utilisant everyauth.
  • J'ai un morceau qui configure mon application (essentiellement appelant app.configure)
  • J'ai un peu de code qui frappe moins afin de recompiler n'importe lequel de mes moins en css au moment de l'exécution.
  • J'ai un code qui configure tous mes itinéraires
  • J'appelle ce petit module nko
  • Enfin, je démarre le serveur en écoutant un port.

Par exemple, regardons le fichier routage

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

Ici, je charge tous mes modèles et itinéraires en tant que tableaux de fichiers.

Clause de non-responsabilité: readdirSync n’est ok que s’il est appelé avant de démarrer le serveur http (avant .listen). L'appel de blocage synchronisé au démarrage du serveur rend le code plus lisible (c'est un hack)

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

Ici, je me connecte à socket.io pour utiliser l’autorisation plutôt que de laisser un tom et une prise parler à mon serveur socket.io

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

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

Ici, je commence mes itinéraires en transmettant le modèle approprié à chaque objet de route renvoyé à partir du fichier de route.

Fondamentalement, le jist est que vous organisez tout dans Nice petits modules et ensuite un mécanisme de démarrage.

Mon autre projet (mon blog) a un fichier init avec une structure similaire .

Disclaimer: le blog est cassé et ne se construit pas, je travaille dessus.

9
Raynos

Pour l'organisation de routage maintenable, vous pouvez consulter cet article à propos de le module de nœud express-routescan et l'essayer C'est la meilleure solution pour moi.

1
Alexander Bykhov

J'ai mes applications construites sur l'outil de générateur express. Vous pouvez l'installer en exécutant npm install express-generator -g Et en utilisant express <APP_NAME>.

Pour vous donner une idée, une des structures de ma plus petite application ressemblait à ceci:

~/
|~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

Une chose intéressante que j’aime dans cette structure que j’adopte pour toute application express que je développe est la façon dont les itinéraires sont organisés. Je n'aimais pas avoir besoin de demander chaque fichier de route dans app.js et app.use() chaque route, d'autant plus que le fichier grossissait. En tant que tel, j’ai trouvé utile de regrouper et de centraliser tous mes app.use() sur un fichier ./routes/index.js.

En fin de compte, mon application.js ressemblera à ceci:

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

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

et mes ./routes/index.js ressembleront à ceci:

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

Je suis capable de simplement require(./users) parce que j'ai écrit l'itinéraire des utilisateurs en utilisant express.Router (), ce qui me permet de "grouper" plusieurs itinéraires, puis de les exporter en même temps, dans le but de rendre l'application plus modulaire.

Voici un exemple de ce qui vous conviendrait le mieux sur mon itinéraire ./routers/users.js:


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

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

module.exports = router;

J'espère que cela a aidé à répondre à votre question! Bonne chance!

0
JKleinne