ExpressJS comment structurer une application?

j'utilise le framework web D'ExpressJS pour NodeJS.

les utilisateurs D'ExpressJS mettent leurs environnements (développement, production, test...), leurs itinéraires etc sur le app.js . Je pense que ce n'est pas une belle façon parce que quand vous avez une grosse application, app.js est trop grand!

j'aimerais avoir cette structure de répertoire:

| my-application
| -- app.js
| -- config/
     | -- environment.js
     | -- routes.js

Voici mon code:

app.js

var express = require('express');
var app = module.exports = express.createServer();

require('./config/environment.js')(app, express);
require('./config/routes.js')(app);

app.listen(3000);

config/environment.js

module.exports = function(app, express){
    app.configure(function() {
    app.use(express.logger());
    });

    app.configure('development', function() {
    app.use(express.errorHandler({
        dumpExceptions: true,
        showStack: true
    }));
    });

    app.configure('production', function() {
    app.use(express.errorHandler());
    });
};

config/routes.js

module.exports = function(app) {
    app.get('/', function(req, res) {
    res.send('Hello world !');
    });
};

Mon code fonctionne bien et je pense que la structure des répertoires est belle. Cependant, le code a dû être adapté et je ne suis pas sûr qu'il soit bon/beau.

Est-il préférable d'utiliser ma structure de répertoires et d'adapter le code ou simplement utiliser un fichier (app.js)?

Merci pour vos conseils!

472
demandé sur Ondrej Slinták 2011-04-25 16:18:34

18 réponses

OK, ça fait longtemps et c'est une question populaire, donc j'ai créé un dépôt GitHub avec du code JavaScript et un long README sur comment j'aime structurer un express de taille moyenne.js application.

focaurus/express_code_structure est le repo avec le dernier code pour cela. Tirez sur les demandes de bienvenue.

voici un aperçu du README depuis stackoverflow n'aime pas juste-un-lien de réponses. Je vais faire quelques mises à jour car il s'agit d'un nouveau projet que je vais continuer à mettre à jour, mais en fin de compte, le GitHub repo sera l'endroit le plus à jour pour cette information.


Express De La Structure De Code

Ce projet est un exemple de la façon d'organiser une moyenne express.js web application.

courant au moins express v4.14 décembre 2016

Build Status

js-standard-style

Quelle est la taille de votre application?

les applications Web ne sont pas tous les mêmes, et il n'y a pas, à mon avis, un seul de la structure de code qui devrait être appliquée à tous les exprimer.js applications.

si votre application est petite, vous n'avez pas besoin d'une telle structure de répertoire comme en témoigne ici. Il suffit de le garder simple et coller une poignée de .js fichiers dans la racine de votre dépôt et vous avez terminé. Voilà.

si votre application est énorme, à un moment donné vous devez la décomposer en paquets npm distincts. En général le nœud.js approach semble favoriser beaucoup de petits paquets, au moins pour les bibliothèques, et vous devriez construire votre application en utilisant plusieurs paquets npm car cela commence à avoir du sens et à justifier la surcharge. De sorte que votre application grandit et une partie du code devient clairement réutilisable en dehors de votre application ou est un sous-système clair, le déplacer à son propre dépôt git et le faire dans un paquet npm autonome.

So ce projet vise à illustrer une structure utilisable pour une application de taille moyenne.

Quelle est votre architecture d'ensemble

il existe de nombreuses approches pour construire un web application, telle que

  • Server Side MVC a la Ruby on Rails
  • Single Page Application style a la MongoDB/Express/Angular / Node (MEAN)
  • de site web de Base avec certaines formes
  • Modèles/Opérations/Vues/Événements de style à la MVC est mort, il est temps de passer à autre chose
  • et beaucoup d'autres à la fois historique et actuelle

chacun de ceux-ci s'intègre parfaitement dans une structure de répertoire différente. Pour les besoins de cet exemple, il ne s'agit que d'un échafaudage et non d'une application pleinement fonctionnelle, mais je suppose que les points clés de l'architecture sont les suivants:

  • le site a quelques pages statiques traditionnelles / gabarits
  • la partie" application "du site est développée comme un style D'Application D'une seule Page
  • la demande expose un style REST / JSON API pour le navigateur
  • l'application Modèle un simple domaine d'affaires, dans ce cas, c'est une application de concessionnaire automobile

et Qu'en est-il de Ruby on Rails?

ce sera un thème tout au long de ce projet que beaucoup des idées incarnées dans Ruby on Rails et la" Convention sur la Configuration " décisions qu'ils ont adoptées, bien que largement acceptées et utilisées, ne sont pas réellement très utiles et sont parfois le contraire de ce que ce référentiel recommande.

mon point principal ici est qu'il y a des principes sous-jacents au Code d'organisation, et basé sur ces principes, les conventions Ruby on Rails ont du sens (surtout) pour la communauté Ruby on Rails. Cependant, le simple fait d'appliquer ces conventions sans réfléchir ne tient pas la route. Une fois que vous aurez pris connaissance des principes de base, TOUS vos projets seront bien organisés et clairs: scripts shell, jeux, applications mobiles, projets d'entreprise, même votre répertoire personnel.

pour la communauté des Rails, ils veulent être en mesure d'avoir un seul commutateur de développeur de Rails de l'application à l'application et être familier et confortable avec elle à chaque fois. Cela a beaucoup de sens si vous êtes 37 signaux ou des laboratoires pivots, et a des avantages. Dans le monde JavaScript côté serveur, l'éthos général est beaucoup plus Far west que tout et nous n'avons pas vraiment de problème avec cela. C'est notre façon de faire. Nous sommes habitués à cela. Même dans l'express.js, c'est un proche parent de Sinatra, pas les Rails, et prendre des conventions de Rails n'aide généralement rien. Je dirais même Principes sur la Convention sur la Configuration .

principes sous-jacents et Motivations

  • être gérable mentalement
    • le cerveau ne peut traiter et penser qu'à un petit nombre de choses à la fois. C'est pour ça qu'on utilise des répertoires. Il nous aide à faire face à la complexité en je me concentre sur les petites portions.
  • doit être adapté à la taille
    • ne créez pas de" répertoires de manoirs " où il n'y a qu'un seul fichier tout seul 3 répertoires vers le bas. Vous pouvez voir ce qui se passe dans le Ansible Best Practices qui humilie les petits projets dans la création de 10 + répertoires pour contenir 10 + fichiers Quand 1 répertoire avec 3 fichiers serait beaucoup plus approprié. Vous ne conduisez pas un bus pour aller au travail (sauf si vous êtes pilote de bus, mais même alors votre conduite d'un bus au travail ne fonctionne pas), donc ne créez pas de structures de système de fichiers qui ne sont pas justifiés par les fichiers qu'ils contiennent.
  • être modulaire mais pragmatique
    • la communauté de noeuds favorise globalement les petits modules. Tout ce qui peut être clairement séparé entièrement de votre application doit être extrait dans un module soit pour usage interne ou publié publiquement sur npm. Cependant, pour la applications de taille moyenne qui sont le champ d'application ici, les frais généraux de cette Peut ajouter tedium à votre flux de travail sans valeur proportionnée. Donc, pour le temps où vous avez un code qui est pris en compte mais pas assez pour justifier un module npm complètement séparé, considérez-le comme un " proto-module " avec l'espoir que lorsqu'il franchira un certain seuil de taille, il sera extrait.
    • certains comme @hij1nx même inclure un répertoire app/node_modules et avoir des fichiers package.json dans les répertoires proto-module pour faciliter cette transition et agir comme un rappel.
  • Être facile à trouver code
    • avec une fonctionnalité à construire ou un bogue à corriger, notre objectif est qu'un développeur n'ait aucune difficulté à localiser les fichiers sources impliqués.
    • les noms sont significatifs et exacts
    • le code crufty est entièrement supprimé, pas laissé dans un fichier orphelin ou simplement commenté
  • recherche convivial
    • tout le code source de première partie est dans le répertoire app donc vous pouvez cd il y a Exécuter find/grep/xargs / ag/ack / etc et ne pas être distrait par des correspondances de tiers
  • utiliser un nom simple et évident
    • npm il semble maintenant qu'il faille des noms de paquets toutes minuscules. Je trouve cela plutôt terrible mais je dois suivre le troupeau, donc les noms de fichiers devraient utiliser kebab-case même si le nom de la variable pour cela en JavaScript doit être camelCase parce que - est un signe moins en JavaScript.
    • Le nom de la variable
    • correspond au nom de base du chemin du module, mais avec kebab-case transformé en camelCase
  • groupe par accouplement, non par Fonction
    • il s'agit d'une dérogation importante à la Convention de Ruby on Rails du app/views , app/controllers , app/models , etc
    • Les fonctionnalités
    • sont ajoutées à une pile complète, donc je veux me concentrer sur une pile complète de fichiers qui sont pertinents pour ma fonctionnalité. Quand j'ajoute un champ de numéro de téléphone au model user, Je ne me soucie pas d'un autre controller que le Controller user, et je ne me soucie pas d'un autre model que le Model user.
    • donc au lieu d'éditer 6 fichiers qui sont chacun dans leur propre répertoire et d'ignorer des tonnes d'autres fichiers dans ces répertoires, ce dépôt est organisé de telle sorte que tous les fichiers dont j'ai besoin pour construire une fonctionnalité soient colocalisés
    • par la nature de MVC, la vue de l'utilisateur est couplée au contrôleur de l'utilisateur qui est couplé au modèle de l'utilisateur. Donc quand je change le modèle utilisateur, ces 3 fichiers vont souvent changer ensemble, mais le contrôleur des deals ou le contrôleur client sont découplés. et ne sont donc pas concernés. Il en va de même pour les conceptions non MVC.
    • MVC ou découplage style MOVE en termes de quel code va dans quel module est encore encouragé, mais la diffusion des fichiers MVC dans les répertoires de frères et sœurs est tout simplement ennuyeux.
    • ainsi chacun de mes fichiers de routes possède la partie des routes qu'il possède. Un fichier routes.rb de style rails est pratique si vous voulez un aperçu de toutes les routes dans l'application, mais en fait construire des fonctionnalités et corriger les bugs, vous ne vous souciez que des routes pertinentes à la pièce que vous changez.
  • stocker les tests à côté du code
    • C'est juste un exemple de "groupe de couplage", mais je voulais l'appeler spécifiquement. J'ai écrit de nombreux projets où les tests se déroulent sous un système de fichiers parallèle appelé "tests" et maintenant que j'ai commencé à mettre mes tests dans le même répertoire que leur code correspondant, Je ne reviendrai jamais en arrière. C'est plus modulaire et plus facile à utiliser dans les éditeurs de texte et les soulage beaucoup de "../../.."chemin d'accès de non-sens. Si vous êtes dans le doute, essayez sur quelques projets et décider pour vous-même. Je ne vais rien faire au-delà de ça pour te convaincre que c'est mieux.
  • réduction du couplage transversal avec Événements
    • c'est facile de penser" OK, chaque fois qu'une nouvelle affaire est créée, je veux envoyer un e-mail à tous les Les vendeurs", puis il suffit de mettre le code pour envoyer ces e-mails dans la route qui crée des offres.
    • cependant, ce couplage finira par transformer votre application en une boule géante de boue.
    • au lieu de cela, le DealModel devrait simplement lancer un événement "create" et être totalement ignorant de ce que le système pourrait faire d'autre en réponse à cela.
    • quand vous codez de cette façon, il devient beaucoup plus possible de mettre tout le code lié à l'utilisateur dans app/users parce qu'il n'y a pas un nid à rat de logique commerciale couplée qui pollue la pureté de la base de code utilisateur.
  • le flux de Code est suivable
    • Ne pas faire de la magie des choses. Ne chargez pas automatiquement les fichiers des répertoires magiques du système de fichiers. Ne pas être des Rails. L'application démarre à app/server.js:1 et vous pouvez voir tout ce qu'elle charge et exécute en suivant le code.
    • ne faites pas DSLs pour votre route. Ne faites pas idiot métaprogrammation quand il n'est pas demandé.
    • si votre application est si grande que faire magicRESTRouter.route(somecontroller, {except: 'POST'}) est une grande victoire pour vous plus de 3 de base app.get , app.put , app.del , calls, vous construisez probablement une application monolithique qui est trop grande pour travailler efficacement sur. Obtenez fantaisie pour les grands gains, pas pour convertir 3 lignes simples en 1 ligne complexe.
  • Utiliser moins d'-kebab-cas des noms de fichiers

    • ce format évite les problèmes de sensibilité de cas de systèmes de fichiers à travers les plateformes
    • npm interdit le majuscule dans les nouveaux noms de paquets, et cela fonctionne bien avec cela

      express.js détails

  • N'utilisez pas app.configure . C'est presque totalement inutile et tu n'en as pas besoin. Il est en beaucoup de boilerplate en raison de copypasta sans cervelle.

  • THE ORDER OF MIDDLEWARE AND ROUTES IN EXPRESS MATTERS!!!
    • presque tous les problèmes de routage que je vois sur stackoverflow sont des middleware express out-of-order
    • en général, vous voulez que vos itinéraires découplés et ne pas compter sur la commande que beaucoup
    • N'utilisez pas app.use pour l'ensemble de votre application si vous n'avez vraiment besoin que de cet middleware pour 2 routes (je vous regarde, body-parser )
    • assurez-vous que quand tout est dit et fait vous avez exactement cet ordre:
      1. tout middleware d'application super-important
      2. Tous vos itinéraires et un assortiment de route middlewares
      3. ALORS gestionnaires d'erreur
  • malheureusement, étant inspiré de sinatra, express.js suppose que tous vos itinéraires seront dans server.js et il sera clair comment ils sont commandés. Pour une application de taille moyenne, décomposer les choses en modules de routes séparées est agréable, mais il introduit le péril de middleware hors de l'ordre

L'app lien symbolique truc

il y a beaucoup d'approches décrites et discutées en détail par la communauté dans le grand gist meilleur Local require() chemins pour le noeud.js . Je pourrait bientôt décider à préférer soit "juste traiter avec beaucoup de ../../../.."ou l'utilisation le require from modlue. Cependant, pour le moment, j'ai utilisé le truc du lien symbolique détaillé ci-dessous.

donc une façon d'éviter intra-projet nécessite avec des chemins relatifs ennuyeux comme require("../../../config") est d'utiliser l'astuce suivante:

  • créez un lien symbolique sous node_modules pour votre application
    • cd node_modules & & ln-nsf ../ app
  • ajouter juste le symlink node_modules/app lui-même , pas le dossier node_modules entier, à git
    • git add -f node_modules / app
    • Oui, vous devriez toujours avoir un "node_modules" dans votre .gitignore fichier
    • Non, vous ne devez pas mettre "node_modules" dans votre dépôt git. Certaines personnes vous recommanderont de le faire. Elles sont incorrectes.
  • Maintenant vous pouvez demander modules intra-projet utilisant ce préfixe
    • var config = require("app/config");
    • var DealModel = require("app/deals/deal-model") ;
  • essentiellement, cela rend intra - projet nécessite un travail très similaire aux besoins pour les modules externes npm.
  • Désolé, utilisateurs de Windows, vous devez coller avec répertoire parent chemins relatifs.

Configuration

en général code les modules et les classes s'attendent seulement à ce qu'un objet JavaScript de base options soit passé. Seul app/server.js doit charger le module app/config.js . De là, il peut synthétiser de petits objets options pour configurer des sous-systèmes selon les besoins, mais coupler chaque sous-système à un grand module global de configuration rempli d'informations supplémentaires est un mauvais couplage.

essayer de centraliser la création de connexions DB et passer ceux-ci dans les sous-systèmes par opposition à passer les paramètres de connexion et avoir des sous-systèmes qui font eux-mêmes des connexions sortantes.

NODE_ENV

c'est une autre idée séduisante mais terrible portée par les Rails. Il devrait y avoir exactement un endroit dans votre application, app/config.js qui regarde la variable d'environnement NODE_ENV . Tout le reste devrait prendre une option explicite comme argument du constructeur de classe ou comme paramètre de configuration du module.

si le module de messagerie a une option sur la façon de deliver emails (SMTP, log to stdout, put in queue etc), il devrait prendre une option comme {deliver: 'stdout'} mais il ne devrait absolument pas vérifier NODE_ENV .

Essais

je garde maintenant mes fichiers de test dans le même répertoire que leur code correspondant et j'utilise les conventions de nommage de l'extension filename pour distinguer les tests du code de production.

  • foo.js possède le code de module "foo"
  • foo.tape.js a les tests basés sur le noeud pour foo et vit dans le même dir
  • foo.btape.js peut être utilisé pour des tests qui doivent être exécutés dans un environnement de navigateur

j'utilise le système de fichiers globs et la commande find . -name '*.tape.js' pour accéder à tous mes tests si nécessaire.

comment organiser le code dans chaque .js fichier module

la portée de ce projet porte principalement sur l'endroit où les dossiers et les répertoires vont, et je ne veux pas ajouter beaucoup d'autres scope, mais je vais juste mentionner que j'organise mon code en 3 sections distinctes.

  1. Ouverture de bloc de CommonJS exiger des appels à l'état des dépendances
  2. bloc de code principal de pur-JavaScript. Il n'y a pas de pollution commune ici. Ne faites pas référence à exports, module, ou require.
  3. bloc de fermeture des entreprises communes pour l'établissement des exportations
261
répondu Peter Lyons 2016-12-15 20:01:49

mise à jour (2013-10-29) : s'il vous plaît voir mon autre réponse ainsi que qui a JavaScript au lieu de CoffeeScript par la demande populaire ainsi que d'un boilerplate GitHub repo et un README détaillé de mes dernières recommandations sur ce sujet.

Config

ce que vous faites est très bien. J'aime avoir mon propre namespace de configuration installé dans un fichier config.coffee de haut niveau avec un emboîtement espace de noms comme ça.

#Set the current environment to true in the env object
currentEnv = process.env.NODE_ENV or 'development'
exports.appName = "MyApp"
exports.env =
  production: false
  staging: false
  test: false
  development: false
exports.env[currentEnv] = true
exports.log =
  path: __dirname + "/var/log/app_#{currentEnv}.log"
exports.server =
  port: 9600
  #In staging and production, listen loopback. nginx listens on the network.
  ip: '127.0.0.1'
if currentEnv not in ['production', 'staging']
  exports.enableTests = true
  #Listen on all IPs in dev/test (for testing from other machines)
  exports.server.ip = '0.0.0.0'
exports.db =
  URL: "mongodb://localhost:27017/#{exports.appName.toLowerCase()}_#{currentEnv}"

c'est convivial pour l'édition sysadmin. Puis quand j'ai besoin de quelque chose, comme les informations de connexion DB, c'est

require('./config').db.URL

Routes/Contrôleurs

j'aime bien laisser mes routes avec mes contrôleurs et les organiser dans un sous-répertoire app/controllers . Alors je peux les charger et les laisser ajouter toutes les routes dont ils ont besoin.

dans mon app/server.coffee coffeescript fichier je fais:

[
  'api'
  'authorization'
  'authentication'
  'domains'
  'users'
  'stylesheets'
  'javascripts'
  'tests'
  'sales'
].map (controllerName) ->
  controller = require './controllers/' + controllerName
  controller.setup app

donc j'ai des fichiers comme:

app/controllers/api.coffee
app/controllers/authorization.coffee
app/controllers/authentication.coffee
app/controllers/domains.coffee

et par exemple dans mon contrôleur de domaines, j'ai une fonction setup comme celle-ci.

exports.setup = (app) ->
  controller = new exports.DomainController
  route = '/domains'
  app.post route, controller.create
  app.put route, api.needId
  app.delete route, api.needId
  route = '/domains/:id'
  app.put route, controller.loadDomain, controller.update
  app.del route, controller.loadDomain, exports.delete
  app.get route, controller.loadDomain, (req, res) ->
    res.sendJSON req.domain, status.OK

vues

Mettre des points de vue dans app/views est en train de devenir le coutumier. Je la donne comme ceci.

app/views/layout.jade
app/views/about.jade
app/views/user/EditUser.jade
app/views/domain/EditDomain.jade

statique Fichiers

Aller dans un public sous-répertoire.

Github / Semver/NPM

mettez un README.md markdown file à la racine de votre compte rendu git pour github.

mettre un paquet.fichier json avec un "1519550920 sémantique" version le nombre dans votre repo git racine de MNP.

154
répondu Peter Lyons 2013-10-29 18:20:42

est Peter Lyons réponse mot à mot, porté sur vanilla JS de Coffeescript, comme demandé par plusieurs autres. La réponse de Peter est très compétente, et quiconque votera sur ma réponse devrait aussi voter sur la sienne.


Config

ce que vous faites est très bien. J'aime avoir mon propre namespace de configuration dans un fichier config.js de haut niveau avec un namespace imbriqué comme celui-ci.

// Set the current environment to true in the env object
var currentEnv = process.env.NODE_ENV || 'development';
exports.appName = "MyApp";
exports.env = {
  production: false,
  staging: false,
  test: false,
  development: false
};  
exports.env[currentEnv] = true;
exports.log = {
  path: __dirname + "/var/log/app_#{currentEnv}.log"
};  
exports.server = {
  port: 9600,
  // In staging and production, listen loopback. nginx listens on the network.
  ip: '127.0.0.1'
};  
if (currentEnv != 'production' && currentEnv != 'staging') {
  exports.enableTests = true;
  // Listen on all IPs in dev/test (for testing from other machines)
  exports.server.ip = '0.0.0.0';
};
exports.db {
  URL: "mongodb://localhost:27017/#{exports.appName.toLowerCase()}_#{currentEnv}"
};

c'est convivial pour l'édition sysadmin. Puis quand j'ai besoin de quelque chose, comme les informations de connexion DB, c'est

require('./config').db.URL

Routes/Contrôleurs

j'aime bien laisser mes routes avec mes contrôleurs et les organiser dans un sous-répertoire app/controllers . Alors je peux les charger et les laisser ajouter toutes les routes dont ils ont besoin.

dans mon fichier javascript app/server.js Je fais:

[
  'api',
  'authorization',
  'authentication',
  'domains',
  'users',
  'stylesheets',
  'javascripts',
  'tests',
  'sales'
].map(function(controllerName){
  var controller = require('./controllers/' + controllerName);
  controller.setup(app);
});

donc j'ai des fichiers comme:

app/controllers/api.js
app/controllers/authorization.js
app/controllers/authentication.js
app/controllers/domains.js

et par exemple dans mon contrôleur de domaines, j'ai une fonction setup comme celle-ci.

exports.setup = function(app) {
  var controller = new exports.DomainController();
  var route = '/domains';
  app.post(route, controller.create);
  app.put(route, api.needId);
  app.delete(route, api.needId);
  route = '/domains/:id';
  app.put(route, controller.loadDomain, controller.update);
  app.del(route, controller.loadDomain, function(req, res){
    res.sendJSON(req.domain, status.OK);
  });
}

vues

Mettre des points de vue dans app/views est en train de devenir le coutumier. Je la donne comme ceci.

app/views/layout.jade
app/views/about.jade
app/views/user/EditUser.jade
app/views/domain/EditDomain.jade

Fichiers Statiques

Aller dans un public sous-répertoire.

Github / Semver/NPM

mettez un README.md markdown file à la racine de votre compte rendu git pour github.

mettre un paquet.fichier json avec un "1519550920 sémantique" version le nombre dans votre repo git racine de MNP.

50
répondu dthree 2014-11-09 13:31:58

ma question a été introduite en avril 2011, il est calme vieux. Pendant ce temps, je pourrais améliorer mon expérience avec Express.js et comment l'architecture d'une application écrite en utilisant cette bibliothèque. Donc, je partage ici mon expérience.

Voici la structure de mon répertoire:

├── app.js   // main entry
├── config   // The configuration of my applications (logger, global config, ...)
├── models   // The model data (e.g. Mongoose model)
├── public   // The public directory (client-side code)
├── routes   // The route definitions and implementations
├── services // The standalone services (Database service, Email service, ...)
└── views    // The view rendered by the server to the client (e.g. Jade, EJS, ...)

App.js

le but du fichier app.js est de bootstrap l'application expressjs. Il charge le module de configuration, le module logger, attendre la connexion à la base de données, ..., et exécutez le serveur express.

'use strict';
require('./config');
var database = require('./services/database');
var express = require('express');
var app = express();
module.exports = app;

function main() {
  var http = require('http');

  // Configure the application.
  app.configure(function () {
    // ... ... ...
  });
  app.configure('production', function () {
    // ... ... ...
  });
  app.configure('development', function () {
    // ... ... ...
  });

  var server = http.createServer(app);

  // Load all routes.
  require('./routes')(app);

  // Listen on http port.
  server.listen(3000);
}

database.connect(function (err) {
  if (err) { 
    // ...
  }
  main();
});

routes /

le répertoire des routes contient un fichier index.js . Son but est d'introduire une sorte de magie pour charger tous les autres fichiers à l'intérieur du répertoire routes/ . Voici la mise en œuvre:

/**
 * This module loads dynamically all routes modules located in the routes/
 * directory.
 */
'use strict';
var fs = require('fs');
var path = require('path');

module.exports = function (app) {
  fs.readdirSync('./routes').forEach(function (file) {
    // Avoid to read this current file.
    if (file === path.basename(__filename)) { return; }

    // Load the route file.
    require('./' + file)(app);
  });
};

avec ce module, la création d'une nouvelle définition de route et la mise en œuvre est vraiment facile. Pour exemples, hello.js :

function hello(req, res) {
  res.send('Hello world');
}

module.exports = function (app) {
  app.get('/api/hello_world', hello);
};

chaque module de route est autonome .

41
répondu Sandro Munda 2013-11-01 09:56:32

, je tiens à utiliser une "app", plutôt que d'exporter une fonction etc

18
répondu tjholowaychuk 2011-09-08 14:36:07

je pense que c'est une excellente façon de le faire. Pas limité à exprimer, mais j'ai vu un certain nombre de nœud.js projette sur github de faire la même chose. Ils prennent les paramètres de configuration + modules plus petits (dans certains cas chaque URI) sont pris en compte dans des fichiers séparés.

je vous recommande de passer par des projets spécifiques sur GitHub pour avoir une idée. IMO la façon dont vous faites est correcte.

17
répondu neebz 2011-04-25 12:56:17

il est maintenant fin de 2015 et après avoir développé ma structure pendant 3 ans et dans les petits et grands projets. Conclusion?

ne pas faire un grand MVC, mais le séparer dans les modules

So...

pourquoi?

  • habituellement, on travaille sur un module (par exemple des produits), que vous pouvez changer indépendamment.

  • vous pouvez réutiliser les modules

  • Vous êtes en mesure de tester séparément

  • Vous êtes en mesure de remplacer séparément

  • ils ont des interfaces claires (stables)

    - au plus tard, s'il y avait plusieurs développeurs travaillant, la séparation des modules aide

le projet nodebootstrap a une approche similaire à ma structure finale. ( github )

à quoi ressemble cette structure?

  1. petits modules capsulés , chacun avec MVC séparé

  2. chaque module comporte un colis.json

  3. Test comme une partie de la structure (dans chaque module)

  4. configuration Globale , de bibliothèques et de Services

  5. Docker intégré, Cluster, pour toujours

Folderoverview (voir le dossier lib pour les modules):

nodebootstrap structure

13
répondu Simon Fakir 2015-09-29 07:28:19

Cela fait longtemps que la dernière réponse à cette question et Express a également récemment publié la version 4, qui a ajouté quelques choses utiles pour organiser la structure de votre application.

ci-dessous est un billet de blog à jour sur les meilleures pratiques sur la façon de structurer votre application Express. http://www.terlici.com/2014/08/25/best-practices-express-structure.html

il y a aussi un dépôt GitHub qui applique les conseils article. Il est toujours à jour avec la dernière version Express.

https://github.com/terlici/base-express

7
répondu Stefan 2014-10-10 11:23:51

Je ne pense pas que ce soit une bonne approche d'ajouter des routes à config. Une meilleure structure pourrait être quelque chose comme ceci:

application/
| - app.js
| - config.js
| - public/ (assets - js, css, images)
| - views/ (all your views files)
| - libraries/ (you can also call it modules/ or routes/)
    | - users.js
    | - products.js
    | - etc...

Ainsi les produits.js et les utilisateurs.js contiendra toutes vos routes sera toute la logique à l'intérieur.

7
répondu ecdeveloper 2018-01-26 15:57:12

Eh bien j'ai mis mes routes comme un fichier json, que j'ai lu au début, et dans une boucle-for Dans app.js a établi les routes. Route.json inclut la vue qui doit être appelée, et la clé pour les valeurs qui seront envoyés dans la route.

Cela fonctionne pour beaucoup de cas simples, mais j'ai dû créer manuellement quelques routes pour des cas spéciaux.

6
répondu TiansHUo 2011-08-04 07:56:40

cela peut être intéressant:

https://github.com/flatiron/nconf

noeud hiérarchique.configuration de js avec fichiers, variables d'environnement, arguments en ligne de commande et fusion d'objets atomiques.

5
répondu Ulysses V 2013-02-06 03:21:39

j'ai écrit un billet sur cette affaire. Il utilise essentiellement un routeRegistrar qui itère à travers les fichiers du dossier /controllers appelant sa fonction init . La fonction init prend la variable app comme paramètre pour que vous puissiez enregistrer vos routes comme vous le souhaitez.

var fs = require("fs");
var express = require("express");
var app = express();

var controllersFolderPath = __dirname + "/controllers/";
fs.readdirSync(controllersFolderPath).forEach(function(controllerName){
    if(controllerName.indexOf("Controller.js") !== -1){
        var controller = require(controllersFolderPath + controllerName);
        controller.init(app);
    }
});

app.listen(3000);
5
répondu Renato Gama 2015-04-14 12:35:18

1) votre système de fichiers Express project peut-être comme:

/ ...
/lib
/node_modules
/public
/views
      app.js
      config.json
      package.json

app.js - vous mondial de l'app container

2) Module principal (fichier lib/mymodule/index.js):

var express = require('express');    
var app = module.exports = express();
// and load module dependencies ...  

// this place to set module settings
app.set('view engine', 'jade');
app.set('views', __dirname + '/views');

// then do module staff    
app.get('/mymodule/route/',function(req,res){ res.send('module works!') });

3) Connecter le module dans l'application principale.js

...
var mymodule = require('mymodule');
app.use(mymodule);

4) logique de L'échantillon

lib/login
lib/db
lib/config
lib/users
lib/verify
lib/
   /api/ 
   ...
lib/
   /admin/
      /users/
      /settings/
      /groups/
...
  • test
  • échelle
  • Separate dépend du module
  • groupage route par fonctionnalité (ou modules)

tj , dit - /afficher sur Vimeo intéressante idée de comment modulariser demande expresse - Modulaire d'applications web avec un Nœud.js et Express . Puissant et simple.

4
répondu diproart 2017-05-23 11:47:25

http://locomotivejs.org / fournit un moyen de structurer une application construite avec un noeud.js et Express.

à Partir du site web:

" Locomotive est un cadre web pour le noeud.js. Supports de Locomotive MVC les modèles, les routes reposantes, et la convention sur la configuration, tandis que intégration transparente avec n'importe quelle base de données et moteur de modèle. Locomotive construit sur Express, en préservant la puissance et la simplicité vous avez venus à attendre de Nœud."

4
répondu Ben Mordue 2014-03-14 14:06:05

je donne la structure de dossier de style MVC s'il vous plaît trouver ci-dessous .

nous avons utilisé la structure de dossier de bellow pour nos applications web grandes et moyennes .

 myapp   
|
|
|____app
|      |____controllers
|      |    |____home.js
|      |
|      |____models
|      |     |___home.js
|      |
|      |____views
|           |___404.ejs
|           |___error.ejs
|           |___index.ejs
|           |___login.ejs
|           |___signup.ejs
|   
|
|_____config
|     |___auth.js
|     |___constants.js
|     |___database.js
|     |___passport.js
|     |___routes.js
|
|
|____lib
|    |___email.js
|
|____node_modules
|
|
|____public.js
|    |____css
|    |    |__style.css
|    |    
|    |____js
|    |    |__script.js
|    |
|    |____img
|    |    |__img.jpg
|    |
|    |
|    |____uploads
|         |__img.jpg
|      
|   
|
|_____app.js
|
|
|
|_____package.json

j'ai créé un module npm pour le structureur de dossier MVC generation express.

s'il vous Plaît trouver le soufflet https://www.npmjs.com/package/express-mvc-generator

simples étapes pour générer et utiliser ce module.

I) installer le module npm install express-mvc-generator -g

ii) cocher les options express -h

iii) Générer express structure mvc express myapp

iv) dépendances D'installation: npm install :

v) ouvrez votre configuration/base de données.js, veuillez configurer votre Mongo db.

vi) exécuter l'application node app ou nodemon app

vii) vérifier L'URL http://localhost:8042/signup ou http://yourip:8042/signup

4
répondu Raja Rama Mohan Thavalam 2016-07-05 06:45:28

j'ai récemment adopté les modules comme mini-applications indépendantes.

|-- src
  |--module1
  |--module2
     |--www
       |--img
       |--js
       |--css
     |--#.js
     |--index.ejs
  |--module3
  |--www
     |--bower_components
     |--img
     |--js
     |--css
  |--#.js
  |--header.ejs
  |--index.ejs
  |--footer.ejs

maintenant pour tout routage de module (#.js), vues (*.ejs), js, css et assets sont côte à côte. le routage des sous-modules est configuré dans le #parent.js avec deux lignes supplémentaires

router.use('/module2', opt_middleware_check, require('./module2/#'));
router.use(express.static(path.join(__dirname, 'www')));

ainsi, même des sous-modules sont possibles.

n'oubliez pas de définir view au répertoire src

app.set('views', path.join(__dirname, 'src'));
1
répondu zevero 2016-05-20 08:07:44

voici à quoi ressemble la structure de mon répertoire express project.

je fais habituellement un express dirname pour initialiser le projet, pardonnez Ma paresse, mais il est très souple et extensible. PS - vous devez obtenir express-generator pour cela (pour ceux qui le cherchent sudo npm install -g express-generator , sudo parce que vous l'installez dans le monde entier)

|-- bin
    |-- www //what we start with "forever"
|-- bower_components
|-- models
    |-- database.js
    |-- model1.js //not this exact name ofcourse.
    |-- .
|-- node_modules
|-- public
    |-- images
    |-- javascripts
        |-- controllers
        |-- directives
        |-- services
        |-- app.js
        |-- init.js //contains config and used for initializing everything, I work with angular a lot.
    |-- stylesheets
|-- routes
    |-- some
    |-- hierarchy
    .
    .
|-- views
    |-- partials
    |-- content
|-- .env
|-- .env.template
|-- app.js
|-- README.md

Vous devez vous demander pourquoi .des dossiers env? Parce qu'ils travaillent! J'utilise le module dotenv dans mon projets (beaucoup récemment) et ça marche! Pop dans ces 2 énoncés dans app.js ou www

var dotenv = require('dotenv');
dotenv.config({path: path.join(__dirname + "/.env")});

et une autre ligne pour définir rapidement /bower_components pour servir le contenu statique sous la ressource /ext

app.use('/ext', express.static(path.join(__dirname, 'bower_components')));

il peut probablement être un ajustement pour les gens qui cherchent à utiliser Express et Angular ensemble, ou tout simplement express sans que javascripts hiérarchie bien sûr.

0
répondu Nitesh Oswal 2015-08-04 19:40:03

Ma structure express 4. https://github.com/odirleiborgert/borgert-express-boilerplate

colis

View engine: twig
Security: helmet
Flash: express-flash
Session: express-session
Encrypt: bcryptjs
Modules: express-load
Database: MongoDB
    ORM: Mongoose
    Mongoose Paginate
    Mongoose Validator
Logs: winston + winston-daily-rotate-file
Nodemon
CSS: stylus
Eslint + Husky

Structure

|-- app
    |-- controllers
    |-- helpers
    |-- middlewares
    |-- models
    |-- routes
    |-- services
|-- bin
|-- logs
|-- node_modules
|-- public
    |-- components
    |-- images
    |-- javascripts
    |-- stylesheets
|-- views
|-- .env
|-- .env-example
|-- app.js
|-- README.md
0
répondu Odirlei Borgert 2018-06-15 18:45:22