ExpressJS Comment structurer une application?

J’utilise le framework web ExpressJS pour NodeJS.

Les personnes utilisant ExpressJS placent leurs environnements (développement, production, test …), leurs itinéraires, etc. sur l’ app.js . Je pense que ce n’est pas une belle façon car lorsque vous avez une grosse application, app.js est trop grosse!

Je voudrais 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 devait être adapté et je ne suis pas sûr que ce soit bien / beau.

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

Merci pour vos conseils!

OK, ça fait un moment que c’est une question populaire, alors j’ai créé un repository github en échafaudage avec du code JavaScript et un long README sur la façon dont je souhaite structurer une application express.js de taille moyenne.

focusaurus / express_code_structure est le référentiel avec le dernier code pour cela. Les demandes de tirage sont les bienvenues.

Voici un aperçu du fichier README, car stackoverflow n’aime pas les réponses à un simple lien. Je vais faire quelques mises à jour car il s’agit d’un nouveau projet que je vais continuer à mettre à jour, mais finalement le repository github sera la mise à jour de ces informations.


Structure de code express

Ce projet est un exemple de la façon d’organiser une application Web express.js de taille moyenne.

Courant au moins exprimer v4.14 décembre 2016

Statut de construction

js-standard-style

Quelle est la taille de votre application?

Les applications Web ne sont pas toutes les mêmes et, à mon avis, il n’ya pas de structure de code unique à appliquer à toutes les applications express.js.

Si votre application est petite, vous n’avez pas besoin d’une telle structure de répertoires, comme illustré ici. Restez simple et collez une poignée de fichiers .js à la racine de votre référentiel et vous avez terminé. Voilà.

Si votre application est énorme, à un moment donné, vous devez la décomposer en packages npm distincts. En général, l’approche node.js semble privilégier de nombreux petits packages, au moins pour les bibliothèques, et vous devez créer votre application en utilisant plusieurs packages npm, car cela commence à être logique et justifie la surcharge. Ainsi, au fur et à mesure que votre application se développe et qu’une partie du code devient clairement réutilisable en dehors de votre application ou est un sous-système clair, déplacez-la vers son propre référentiel git pour en faire un package npm autonome.

L’ objective de ce projet est donc d’illustrer une structure réalisable pour une application de taille moyenne.

Quelle est votre architecture globale

Il existe de nombreuses approches pour créer une application Web, telles que

  • Côté serveur MVC a la Ruby on Rails
  • Application simple page à la MongoDB / Express / Angular / Node (MEAN)
  • Site web de base avec quelques formulaires
  • Le modèle Models / Operations / Views / Events à la MVC est mort, il est temps de passer à autre chose
  • et beaucoup d’autres à la fois actuels et historiques

Chacun d’entre eux s’intègre parfaitement dans une structure de répertoire différente. Pour les besoins de cet exemple, il ne s’agit que d’échafaudages et non d’une application pleinement opérationnelle, mais je suppose que les points clés de l’architecture sont les suivants:

  • Le site comporte des pages / modèles statiques traditionnels
  • La partie “application” du site est développée en tant que style d’application à page unique
  • L’application expose une API de style REST / JSON au navigateur
  • L’application modélise un domaine d’entreprise simple, dans ce cas, il s’agit d’une application de concession automobile

Et que dire de Ruby on Rails?

Tout au long de ce projet, un des thèmes abordés dans les décisions Ruby on Rails et «Convention over Configuration» qu’ils ont adoptées, bien que largement acceptées et utilisées, n’est pas vraiment utile et est parfois à l’opposé de ce référentiel. recommande.

Mon point principal ici est qu’il existe des principes sous-jacents à l’organisation du code, et sur la base de ces principes, les conventions Ruby on Rails ont un sens (principalement) pour la communauté Ruby on Rails. Cependant, se contenter de singer ces conventions passe inaperçu. Une fois que vous aurez compris les principes de base, TOUS vos projets seront bien organisés et clairs: scripts shell, jeux, applications mobiles, projets d’entreprise, et même votre répertoire personnel.

Pour la communauté Rails, ils souhaitent pouvoir faire passer un seul développeur Rails d’une application à l’autre d’une application à l’autre et s’y familiariser et s’y familiariser à chaque fois. Cela a du sens si vous êtes 37 signaux ou Pivotal Labs et que vous en avez des avantages. Dans le monde JavaScript côté serveur, la philosophie globale est bien plus sauvage que tout et nous n’avons pas vraiment de problème avec cela. C’est comme ça que nous roulons. Nous y sums habitués. Même dans express.js, c’est un proche parent de Sinatra, pas de Rails, et prendre des conventions avec Rails n’aide généralement rien. Je dirais même Principles over Convention over Configuration .

Principes et motivations sous-jacents

  • Être gérable mentalement
    • Le cerveau ne peut traiter et penser à un petit nombre de choses en même temps. C’est pourquoi nous utilisons des répertoires. Cela nous aide à gérer la complexité en nous concentrant sur de petites portions.
  • Être approprié à la taille
    • Ne créez pas de “répertoires Mansion” où il n’y a qu’un fichier contenant 3 répertoires. Vous pouvez voir cela se produire dans les meilleures pratiques Ansible qui regrette que les petits projets créent plus de 10 répertoires contenant plus de 10 fichiers lorsque 1 répertoire avec 3 fichiers serait beaucoup plus approprié. Vous ne conduisez pas un bus pour aller au travail (sauf si vous êtes chauffeur de bus, mais même si vous conduisez un bus AT pour ne pas travailler), ne créez pas de structures de système de fichiers qui ne sont pas justifiées par les fichiers qu’ils contiennent .
  • Être modulaire mais pragmatique
    • La communauté de nœuds favorise globalement les petits modules. Tout ce qui peut être séparé proprement de votre application doit être extrait dans un module pour usage interne ou publié publiquement sur npm. Cependant, pour les applications de taille moyenne dont la scope est ici, la surcharge peut append un peu de temps à votre stream de travail sans valeur proportionnelle. Donc, pour le moment où vous avez du code qui est exclu, mais pas suffisamment pour justifier un module npm complètement séparé, considérez-le comme un ” proto-module ” en espérant que lorsqu’il franchira un seuil de taille, il sera extrait.
    • Certaines personnes, telles que @ hij1nx, incluent même un répertoire app/node_modules et des fichiers package.json dans les répertoires proto-module pour faciliter cette transition et servir de rappel.
  • Soyez facile à localiser le code
    • Étant donné une fonctionnalité à créer ou un bogue à corriger, notre objective est qu’un développeur n’ait pas de difficulté à localiser les fichiers sources concernés.
    • Les noms sont significatifs et précis
    • le code erroné est complètement supprimé, pas laissé dans un fichier orphelin ou simplement mis en commentaire
  • Être convivial pour la recherche
    • tout le code source de la première partie se trouve dans le répertoire app , vous pouvez donc y cd exécuter run find / grep / xargs / ag / ack / etc et ne pas être distrait par les correspondances tierces
  • Utiliser des noms simples et évidents
    • npm semble maintenant nécessiter des noms de paquets en minuscules. Je trouve cela particulièrement terrible mais je dois suivre le troupeau, donc les noms de fichiers doivent utiliser kebab-case même si le nom de la variable en JavaScript doit être camelCase car - est un signe moins en JavaScript.
    • nom de la variable correspond au nom de base du chemin du module, mais avec kebab-case transformé en camelCase
  • Grouper par couplage, pas par fonction
    • C’est un changement majeur par rapport à la convention Ruby on Rails des app/views , des app/controllers , des app/models , etc.
    • Les fonctionnalités sont ajoutées à une stack complète. Je veux donc me concentrer sur une stack complète de fichiers pertinents pour ma fonctionnalité. Lorsque j’ajoute un champ de numéro de téléphone au modèle utilisateur, je ne me soucie pas des contrôleurs autres que le contrôleur utilisateur, et je me moque des modèles autres que le modèle utilisateur.
    • Ainsi, au lieu d’éditer 6 fichiers qui se trouvent chacun dans leur propre répertoire et d’ignorer des tonnes d’autres fichiers de ces répertoires, ce référentiel est organisé de telle sorte que tous les fichiers nécessaires à la création d’une fonctionnalité soient regroupés.
    • De par la nature de MVC, la vue utilisateur est couplée au contrôleur utilisateur qui est couplé au modèle utilisateur. Donc, lorsque je change de modèle d’utilisateur, ces 3 fichiers changent souvent ensemble, mais le contrôleur de transactions ou le contrôleur client sont découplés et ne sont donc pas impliqués. Il en va de même pour les conceptions non-MVC.
    • Le découplage de style MVC ou MOVE en termes de code dans quel module est toujours encouragé, mais la diffusion des fichiers MVC dans des répertoires frères est tout simplement agaçante.
    • Ainsi, chacun de mes fichiers de routage comporte la partie des itinéraires qu’il possède. Un fichier routes.rb style routes.rb est pratique si vous souhaitez avoir un aperçu de tous les itinéraires de l’application, mais lorsque vous routes.rb fonctionnalités et corrigez des bogues, vous ne vous préoccupez que des itinéraires pertinents pour la pièce que vous modifiez.
  • Stocker les tests à côté du code
    • Ceci est juste une instance de “groupe par couplage”, mais je voulais l’appeler spécifiquement. J’ai écrit beaucoup de projets où les tests vivent sous un système de fichiers parallèle appelé “tests” et maintenant que j’ai commencé à placer mes tests dans le même répertoire que le code correspondant, je ne reviendrai jamais. Ceci est plus modulaire et beaucoup plus facile à utiliser dans les éditeurs de texte et permet de réduire une grande partie du non-sens du chemin “../../ ..”. En cas de doute, essayez-le sur quelques projets et décidez vous-même. Je ne vais rien faire de plus pour vous convaincre que c’est mieux.
  • Réduire le couplage transversal avec les événements
    • Il est facile de penser “OK, chaque fois qu’un nouveau Deal est créé, je veux envoyer un email à tous les commerciaux”, puis simplement mettre le code pour envoyer ces emails dans l’itinéraire qui crée les accords.
    • Cependant, ce couplage finira par transformer votre application en une boule de boue géante.
    • Au lieu de cela, DealModel devrait simplement déclencher un événement “create” et ne pas savoir ce que le système pourrait faire en réponse à cela.
    • Lorsque vous codez de cette façon, il devient beaucoup plus possible de mettre tout le code associé à l’utilisateur dans l’ app/users car il n’y a pas de logique métier couplée partout qui pollue la pureté du code utilisateur.
  • Le stream de code peut être suivi
    • Ne fais pas de choses magiques. Ne pas charger automatiquement les fichiers des répertoires magiques du système de fichiers. Ne soyez pas Rails. L’application démarre à app/server.js:1 et vous pouvez voir tout ce qu’elle charge et s’exécuter en suivant le code.
    • Ne faites pas de DSL pour vos routes. Ne faites pas de métaprogrammation idiote quand ce n’est pas nécessaire.
    • Si votre application est si grosse que magicRESTRouter.route(somecontroller, {except: 'POST'}) est un gros gain pour vous sur 3 applications de base app.get , app.put , app.del , vous construisez probablement une application monolithique trop grosse pour fonctionner efficacement. Obtenez la fantaisie pour les gains BIG, pas pour convertir 3 lignes simples en 1 ligne complexe.
  • Utiliser des noms de fichiers avec un kebab inférieur

    • Ce format évite les problèmes de sensibilité à la casse des systèmes de fichiers sur les plates-formes
    • npm interdit les majuscules dans les nouveaux noms de paquets, et cela fonctionne bien avec

      express.js les spécificités

  • N’utilisez pas app.configure . C’est presque totalement inutile et vous n’en avez pas besoin. Il est dans beaucoup de passe-partout en raison de copypasta stupide.

  • L’ORDRE DE MIDDLEWARE ET ROUTES EN EXPRESSE !!!
    • Presque chaque problème de routage que je vois sur stackoverflow est un middleware express hors service
    • En général, vous voulez que vos routes soient découplées et ne pas trop compter sur la commande
    • N’utilisez pas app.use pour l’ensemble de votre application si vous n’avez vraiment besoin que de ce middleware pour 2 routes (je vous regarde, body-parser )
    • Assurez-vous que tout est dit et fait, vous avez exactement cette commande:
      1. Tout middleware d’application important
      2. Tous vos itinéraires et parcours intermédiaires
      3. ENSUITE les gestionnaires d’erreurs
  • Malheureusement, express.js étant inspiré de sinatra, il suppose que toutes vos routes seront dans server.js et que leur ordre sera clair. Pour une application de taille moyenne, il est intéressant de décomposer les modules en différents itinéraires, mais cela introduit un risque de middleware hors service

L’astuce du lien symbolique de l’application

Il y a beaucoup d’approches décrites et discutées en détail par la communauté dans la grande liste. Les meilleurs chemins de require local () pour Node.js. Je déciderai peut-être bientôt de préférer soit “traiter avec beaucoup de ../../../ ..”, soit utiliser le modlue requireFrom. Cependant, pour le moment, j’utilise le truc du lien symbolique détaillé ci-dessous.

Donc, une façon d’éviter les require("../../../config") intra-projet avec des chemins relatifs ennuyeux comme require("../../../config") est d’utiliser l’astuce suivante:

  • créer un lien symbolique sous node_modules pour votre application
    • cd node_modules && ln -nsf ../app
  • ajoutez simplement le lien symbolique node_modules / app luimême , pas le dossier node_modules en entier, à git
    • git add -f node_modules / app
    • Oui, vous devriez toujours avoir “node_modules” dans votre fichier .gitignore
    • Non, vous ne devriez pas mettre “node_modules” dans votre repository git. Certaines personnes vous recommanderont de le faire. Ils sont incorrects
  • Maintenant, vous pouvez exiger des modules intra-projet en utilisant ce préfixe
    • var config = require("app/config");
    • var DealModel = require("app/deals/deal-model") ;
  • Fondamentalement, cela fait que le travail intra-projet nécessite un travail très similaire à celui requirejs pour les modules npm externes.
  • Désolé, les utilisateurs de Windows, vous devez vous en tenir aux chemins relatifs du répertoire parent.

Configuration

Généralement, coder les modules et les classes pour ne s’attendre qu’à un object JavaScript basique. Seul app/server.js doit charger le module app/config.js . À partir de là, il peut synthétiser de petits objects d’ options pour configurer des sous-systèmes selon les besoins, mais coupler chaque sous-système à un grand module de configuration global rempli d’informations supplémentaires est un mauvais couplage.

Essayez de centraliser la création de connexions de firebase database et de les transférer dans des sous-systèmes, au lieu de passer des parameters de connexion et de faire eux-mêmes des sous-systèmes.

NODE_ENV

C’est une autre idée séduisante mais terrible qui a été reprise par Rails. Il devrait y avoir exactement 1 place dans votre application, app/config.js qui examine la variable d’environnement NODE_ENV . Tout le rest devrait prendre une option explicite comme argument de constructeur de classe ou paramètre de configuration de module.

Si le module de messagerie a une option quant à la manière de livrer les emails (SMTP, se connecter à stdout, mettre en queue, etc.), il devrait prendre une option comme {deliver: 'stdout'} mais il ne devrait absolument pas cocher NODE_ENV .

Des tests

Je conserve maintenant mes fichiers de test dans le même répertoire que le code correspondant et utilise les conventions de dénomination des extensions de nom de fichier pour distinguer les tests du code de production.

  • foo.js a le module “foo” ‘s code
  • foo.tape.js a les tests basés sur les nœuds pour foo et vit dans le même répertoire
  • foo.btape.js peut être utilisé pour des tests foo.btape.js être foo.btape.js dans un environnement de navigateur

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

Comment organiser le code dans chaque fichier de module .js

La scope de ce projet concerne principalement l’emplacement des fichiers et des répertoires, et je ne souhaite pas append beaucoup plus de scope, mais je mentionnerai simplement que j’organise mon code en 3 sections distinctes.

  1. Le bloc d’ouverture de CommonJS nécessite des appels aux dépendances d’état
  2. Bloc de code principal de pure-JavaScript. Pas de pollution CommonJS ici. Ne faites pas référence aux exportations, aux modules ou aux besoins.
  3. Bloc de clôture de CommonJS pour mettre en place des exportations

MISE À JOUR (2013-10-29) : S’il vous plaît voir mon autre réponse qui a JavaScript au lieu de CoffeeScript par la demande populaire ainsi qu’un repo github passe-partout et un README détaillé détaillant mes dernières recommandations sur ce sujet.

Config

Ce que vous faites va bien. J’aime avoir mon propre espace de noms de configuration configuré dans un fichier config.coffee premier niveau avec un espace de noms nested comme celui-ci.

 #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}" 

Ceci est convivial pour l’édition de sysadmin. Ensuite, quand j’ai besoin de quelque chose, comme les informations de connexion à la firebase database,

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

Routes / Controllers

J’aime laisser mes itinéraires avec mes contrôleurs et les organiser dans un sous-répertoire app/controllers . Ensuite, je peux les charger et les laisser append les itinéraires dont ils ont besoin.

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

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

J’ai donc 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 domaine, j’ai une fonction de 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 

Des vues

Mettre des vues dans app/views devient le lieu habituel. Je pose ça comme ça.

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

Fichiers statiques

Aller dans un sous-répertoire public .

Github / Semver / NPM

Placez un fichier README.md dans votre racine git repo pour github.

Placez un fichier package.json avec un numéro de version sémantique dans votre racine de repository git pour NPM.

Ce qui suit est la réponse de Peter Lyons mot à mot, transférée à la vanille JS de Coffeescript, comme demandé par plusieurs autres. La réponse de Peter est tout à fait capable, et toute personne votant sur ma réponse devrait également voter.


Config

Ce que vous faites va bien. J’aime avoir mon propre espace de noms de configuration configuré dans un fichier config.js niveau config.js avec un espace de noms nested 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}" }; 

Ceci est convivial pour l’édition de sysadmin. Ensuite, quand j’ai besoin de quelque chose, comme les informations de connexion à la firebase database,

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

Routes / Controllers

J’aime laisser mes itinéraires avec mes contrôleurs et les organiser dans un sous-répertoire app/controllers . Ensuite, je peux les charger et les laisser append les itinéraires dont ils ont besoin.

Dans mon fichier 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); }); 

J’ai donc 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 domaine, j’ai une fonction de 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); }); } 

Des vues

Mettre des vues dans app/views devient le lieu habituel. Je pose ça comme ça.

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

Fichiers statiques

Aller dans un sous-répertoire public .

Github / Semver / NPM

Placez un fichier README.md dans votre racine git repo pour github.

Placez un fichier package.json avec un numéro de version sémantique dans votre racine de repository git pour NPM.

Ma question a été introduite en avril 2011, elle est ancienne. Pendant ce temps, j’ai pu améliorer mon expérience avec Express.js et comment concevoir une application écrite à l’aide de cette bibliothèque. Donc, je partage ici mon expérience.

Voici ma structure de répertoires:

 ├── app.js // main entry ├── config // The configuration of my applications (logger, global config, ...) ├── models // The model data (eg 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 (eg Jade, EJS, ...) 

App.js

Le fichier app.js but de app.js l’application expressjs. Il charge le module de configuration, le module de journalisation, attend la connexion à la firebase database, … et exécute le serveur express.

 'use ssortingct'; 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 routes contient un fichier index.js . Son but est d’introduire une sorte de magie pour charger tous les autres fichiers dans le répertoire routes/ . Voici la mise en œuvre:

 /** * This module loads dynamically all routes modules located in the routes/ * directory. */ 'use ssortingct'; 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, il est très facile de créer une nouvelle définition et une nouvelle implantation. Pour des exemples, hello.js :

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

Chaque module de routage est autonome .

J’aime utiliser une “application” globale plutôt que d’exporter une fonction, etc.

Je pense que c’est un excellent moyen de le faire. Non limité à exprimer, mais j’ai vu pas mal de projets node.js sur github faisant la même chose. Ils suppriment les parameters de configuration + les plus petits modules (dans certains cas, chaque URI) sont pris en compte dans des fichiers séparés.

Je recommanderais de passer par des projets spécifiques à Express sur github pour avoir une idée. IMO la façon dont vous faites est correcte.

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

Ne faites pas un grand MVC, mais séparez-le en modules

Alors…

Pourquoi?

  • Généralement, on travaille sur un module (par exemple, Produits), que vous pouvez modifier indépendamment.

  • Vous pouvez réutiliser des modules

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

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

  • Ils ont des interfaces claires (stables)

    -Au plus tard, si plusieurs développeurs fonctionnaient, la séparation des modules aide

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

A quoi ressemble cette structure?

  1. Petits modules encapsulés , chacun avec MVC séparé

  2. Chaque module a un package.json

  3. Tester dans le cadre de la structure (dans chaque module)

  4. Configuration globale , bibliothèques et services

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

Folderoverview (voir le dossier lib pour les modules):

structure nodebootstrap

Cela fait un bon bout de temps depuis la dernière réponse à cette question et Express a également récemment publié la version 4, qui a ajouté quelques éléments utiles pour organiser la structure de votre application.

Vous trouverez ci-dessous un article de blog actualisé sur les meilleures pratiques pour structurer votre application Express. http://www.terlici.com/2014/08/25/best-practices-express-structure.html

Il existe également un repository GitHub qui applique les conseils de l’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 pour append des routes à la configuration. 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... 

Donc, products.js et users.js contiendront tous vos itinéraires dans toute la logique.

Eh bien, je mets mes routes sous forme de fichier json, que j’ai lu au début et dans une boucle for dans app.js pour configurer les routes. La route.json inclut la vue à appeler et la clé pour les valeurs qui seront envoyées à la route.
Cela fonctionne pour beaucoup de cas simples, mais j’ai dû créer manuellement des itinéraires pour des cas particuliers.

Cela peut être intéressant:

https://github.com/flatiron/nconf

Configuration hiérarchique de node.js avec les fichiers, les variables d’environnement, les arguments de ligne de commande et la fusion d’object atomique.

J’ai écrit un article exactement à ce sujet. Il utilise essentiellement un routeRegistrar qui parcourt les fichiers du dossier /controllers appelant sa fonction init . La fonction init prend la variable de l’ app express comme paramètre afin que vous puissiez enregistrer vos itinéraires 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 de projet Express peut-être:

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

app.js – votre conteneur d’application global

2) Fichier principal du module (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 app.js principale

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

4) logique d’échantillon

 lib/login lib/db lib/config lib/users lib/verify lib/ /api/ ... lib/ /admin/ /users/ /settings/ /groups/ ... 
  • Idéal pour les tests
  • Meilleur pour l’échelle
  • Séparer dépend du module
  • Grouper la route par fonctionnalité (ou modules)

tj dit / montre sur Vimeo une idée intéressante de la façon dont une application express modulaire – des applications web modulaires avec Node.js et Express . Puissant et simple

http://locomotivejs.org/ permet de structurer une application créée avec Node.js et Express.

Depuis le site:

“Locomotive is a web framework for Node.js. Locomotive supports MVC patterns, RESTful routes, and convention over configuration, while integrating seamlessly with any database and template engine. Locomotive builds on Express, preserving the power and simplicity you’ve come to expect from Node.”

I am giving MVC style folder structure please find bellow .

We used bellow folder structure for our big and medium web applications .

  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 

I have created one npm module for generation express mvc folder structurer.

Please find the bellow https://www.npmjs.com/package/express-mvc-generator

Just simple steps to generate and use this modules .

i) install module npm install express-mvc-generator -g

ii) check options express -h

iii) Generate express mvc structure express myapp

iv) Install dependencies: npm install :

v)Open your config/database.js , Please configure your mongo db.

vi)Run the application node app or nodemon app

vii)Check URL http://localhost:8042/signup OR http://yourip:8042/signup

I recently embraced modules as independent mini-apps.

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

Now for any module routing (#.js), views (*.ejs), js, css and assets are next to each other. submodule routing is set up in the parent #.js with two additional lines

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

This way even subsubmodules are possible.

Don’t forget to set view to the src directory

 app.set('views', path.join(__dirname, 'src')); 

This is how most of my express project directory structure looks.

I usually do a express dirname to initialise the project, forgive my laziness, but it’s very flexible and extendable. PS – you need to get express-generator for that (for those who’re looking for it sudo npm install -g express-generator , sudo because you’re installing it globally)

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

You must be wondering why .env files? Because they work! I use dotenv module in my projects (a lot recently) and it works! Pop in these 2 statements in app.js or www

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

And another line to quickly set /bower_components to serve static content under the resource /ext

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

It probably can be a fit for people who’re looking to use Express and Angular together, or just express without that javascripts hierarchy of course.

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

Paquets

 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