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!
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
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 fichierspackage.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 pouvezcd
il y a Exécuter find/grep/xargs / ag/ack / etc et ne pas être distrait par des correspondances de tiers
- tout le code source de première partie est dans le répertoire
- 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 êtrecamelCase
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é encamelCase
- 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
- 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.
- il s'agit d'une dérogation importante à la Convention de Ruby on Rails du
- 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 baseapp.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.
- 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 à
-
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:
- tout middleware d'application super-important
- Tous vos itinéraires et un assortiment de route middlewares
- 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.
- Ouverture de bloc de CommonJS exiger des appels à l'état des dépendances
- 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.
- bloc de fermeture des entreprises communes pour l'établissement des exportations
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.
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.
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 .
, je tiens à utiliser une "app", plutôt que d'exporter une fonction etc
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.
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?
-
petits modules capsulés , chacun avec MVC séparé
-
chaque module comporte un colis.json
-
Test comme une partie de la structure (dans chaque module)
-
configuration Globale , de bibliothèques et de Services
-
Docker intégré, Cluster, pour toujours
Folderoverview (voir le dossier lib pour les modules):
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
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.
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.
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.
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);
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.
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."
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
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'));
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.
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