579 votes

ExpressJS Comment structurer une application?

Je suis à l'aide de la ExpressJS framework web pour NodeJS.

Les personnes utilisant ExpressJS mettre leurs environnements (développement, production, essais ...), leurs itinéraires, ... sur la 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 !

Je voudrais avoir cette structure de répertoires :

| 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. Toutefois, le code doit être adapté et je ne suis pas sûr que c'est une bonne/belle.

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

Merci pour vos conseils !

157voto

Peter Lyons Points 47794

Mise à JOUR (2013-10-29): Veuillez voir mon autre réponse qui a JavaScript au lieu de CoffeeScript, à la demande populaire ainsi que d'un passe-partout de dépôt github et un vaste README détaillant mes recommandations les plus récentes sur ce sujet.

Config

Ce que vous faites est bien. J'aime avoir ma propre config espace de noms défini dans un niveau supérieur config.coffee le fichier avec un espace de noms imbriqué 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 sympathique pour les sysadmin édition. Puis, quand j'ai besoin de quelque chose, comme la connexion DB info, c'est

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

Routes/Contrôleurs

J'aime bien laisser mes itinéraires avec mon contrôleurs et les organiser dans un app/controllers sous-répertoire. Ensuite, je peux les charger et de les laisser ajouter toutes les routes dont ils ont besoin.

Dans mon app/server.coffee coffeescript fichier que j'ai à faire:

[
  '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 mes domaines de contrôleur, j'ai un setup fonction comme ceci.

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

Les Fichiers Statiques

Aller dans un public sous-répertoire.

Github/Semver/NPM

Mettre un fichier README.md markdown fichier à votre repo git racine pour github.

Mettre un paquet.fichier json avec une sémantique de version numéro de votre repo git racine de MNP.

53voto

dc2 Points 2357

Ce qui suit est Peter Lyons réponse mot à mot, porté sur vanilla JS de Coffeescript, comme demandé par plusieurs autres. La réponse de pierre est très capable, et toute personne à droit de vote sur ma réponse devrait voter sur son ainsi.

Config

Ce que vous faites est bien. J'aime avoir ma propre config espace de noms défini dans un niveau supérieur config.js le fichier avec un espace de noms imbriqué comme ça.

// 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 sympathique pour les sysadmin édition. Puis, quand j'ai besoin de quelque chose, comme la connexion DB info, c'est

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

Routes/Contrôleurs

J'aime bien laisser mes itinéraires avec mon contrôleurs et les organiser dans un app/controllers sous-répertoire. Ensuite, je peux les charger et de les laisser ajouter toutes les routes dont ils ont besoin.

Dans mon app/server.js fichier javascript que 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 mes domaines de contrôleur, j'ai un setup fonction comme ceci.

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

Les Fichiers Statiques

Aller dans un public sous-répertoire.

Github/Semver/NPM

Mettre un fichier README.md markdown fichier à votre repo git racine pour github.

Mettre un paquet.fichier json avec une sémantique de version numéro de votre repo git racine de MNP.

50voto

Sandro Munda Points 12808

Ma question a été introduite en avril 2011, c'est calme vieux. Pendant ce temps, j'ai pu 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 ma structure de 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

L'objectif de l' app.js le fichier est à l'amorçage de l'expressjs application. Il charge le module de configuration, le module logger, attendez que la connexion de base de données, ..., et d'exécuter l'express server.

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

Les routes répertoire a un index.js le fichier. Son objectif est d'introduire une sorte de magie pour charger tous les autres fichiers à l'intérieur de l' routes/ répertoire. 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 la route et l'application est vraiment facile. Pour des exemples, hello.js:

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

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

Chaque itinéraire module est autonome.

17voto

tjholowaychuk Points 171

J'aime utiliser une "application" globale, plutôt que d'exporter une fonction, etc.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X