tutorial servidor nodejs node entre diferencia con app node.js express

node.js - servidor - ExpressJS ¿Cómo estructurar una aplicación?



servidor con express node (18)

Estoy usando el framework web ExpressJS para NodeJS.

Las personas que usan ExpressJS ponen sus entornos (desarrollo, producción, prueba ...), sus rutas, etc. en app.js Creo que no es una forma hermosa porque cuando tienes una aplicación grande, ¡app.js es demasiado grande!

Me gustaría tener esta estructura de directorio:

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

Aquí está mi código:

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 / route.js

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

Mi código funciona bien y creo que la estructura de los directorios es hermosa. Sin embargo, el código tuvo que ser adaptado y no estoy seguro de que sea bueno / hermoso.

¿Es mejor usar mi estructura de directorios y adaptar el código o simplemente usar un archivo (app.js)?

¡Gracias por tus consejos!


1) El sistema de archivos de su proyecto Express tal como:

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

app.js - tu contenedor global de aplicaciones

2) Archivo principal del módulo (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) Conectar módulo en app.js principal

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

4) Lógica de muestra

lib/login lib/db lib/config lib/users lib/verify lib/ /api/ ... lib/ /admin/ /users/ /settings/ /groups/ ...

  • Lo mejor para probar
  • Mejor para la escala
  • Separa depende por módulo
  • Agrupación de rutas por funcionalidad (o módulos).

dice / muestra en Vimeo una idea interesante de cómo modularizar la aplicación Express - Aplicaciones web modulares con Node.js y Express . Potente y simple.


Bien, ha pasado un tiempo y esta es una pregunta popular, así que seguí adelante y creé un repositorio de github de andamios con código JavaScript y un largo README sobre cómo me gusta estructurar una aplicación express.js de tamaño mediano.

focusaurus/express_code_structure es el repositorio con el último código para esto. Tire de las solicitudes de bienvenida.

Aquí hay una instantánea del archivo README ya que no le gustan las respuestas de solo un enlace. Haré algunas actualizaciones ya que este es un nuevo proyecto que continuaré actualizando, pero en última instancia, el repositorio de github será el lugar actualizado para esta información.

Estructura de código Express

Este proyecto es un ejemplo de cómo organizar una aplicación web express.js de tamaño mediano.

Actual al menos expreso v4.14 diciembre 2016

¿Qué tan grande es tu aplicación?

Las aplicaciones web no son todas iguales, y no hay, en mi opinión, una estructura de código única que deba aplicarse a todas las aplicaciones express.js.

Si su aplicación es pequeña, no necesita una estructura de directorios tan profunda como se ejemplifica aquí. Simplemente manténgalo simple y pegue un puñado de archivos .js en la raíz de su repositorio y listo. Voilà.

Si su aplicación es enorme, en algún momento deberá dividirla en distintos paquetes npm. En general, el enfoque de node.js parece favorecer a muchos paquetes pequeños, al menos para las bibliotecas, y debe crear su aplicación utilizando varios paquetes npm, ya que esto comienza a tener sentido y justifica la sobrecarga. Entonces, a medida que su aplicación crece y alguna parte del código se vuelve claramente reutilizable fuera de su aplicación o es un subsistema claro, muévalo a su propio repositorio git y conviértalo en un paquete npm independiente.

Así que el enfoque de este proyecto es ilustrar una estructura viable para una aplicación de tamaño mediano.

¿Cuál es su arquitectura en general?

Hay muchos enfoques para construir una aplicación web, como

  • Server Side MVC a la Ruby on Rails
  • Estilo de aplicación de una sola página a la MongoDB / Express / Angular / Node (MEAN)
  • Sitio web básico con algunas formas.
  • El estilo de Modelos / Operaciones / Vistas / Eventos a la MVC está muerto, es hora de MOVERSE
  • y muchos otros tanto actuales como históricos.

Cada uno de estos encaja perfectamente en una estructura de directorio diferente. Para los propósitos de este ejemplo, es solo un andamio y no una aplicación que funcione completamente, pero asumo los siguientes puntos clave de la arquitectura:

  • El sitio tiene algunas páginas / plantillas estáticas tradicionales.
  • La parte de "aplicación" del sitio se desarrolla como un estilo de aplicación de una sola página.
  • La aplicación expone una API de estilo REST / JSON al navegador
  • La aplicación modela un dominio empresarial simple, en este caso, es una aplicación de concesionario de automóviles.

¿Y qué pasa con Ruby on Rails?

Será un tema a lo largo de este proyecto que muchas de las ideas incorporadas en Ruby on Rails y las decisiones de la "Convención sobre la Configuración" que han adoptado, aunque son ampliamente aceptadas y utilizadas, no son realmente útiles y, a veces, son lo contrario de lo que este repositorio recomienda.

Mi punto principal aquí es que existen principios subyacentes para organizar el código, y en base a esos principios, las convenciones de Ruby on Rails tienen sentido (en su mayoría) para la comunidad de Ruby on Rails. Sin embargo, el mero hecho de imitar esas convenciones pierde el sentido. Una vez que haya asimilado los principios básicos, TODOS sus proyectos estarán bien organizados y claros: scripts de shell, juegos, aplicaciones móviles, proyectos empresariales, incluso su directorio principal.

Para la comunidad de Rails, desean poder tener un solo desarrollador de Rails que cambie de aplicación en aplicación y estar familiarizado y cómodo con él cada vez. Esto tiene mucho sentido si tiene 37 señales o Pivotal Labs, y tiene beneficios. En el mundo de JavaScript del lado del servidor, el espíritu general es mucho más salvaje del oeste, y no tenemos ningún problema con eso. Así es como nosotros lo hacemos. Estamos acostumbrados a ello. Incluso dentro de Express.js, es un pariente cercano de Sinatra, no de Rails, y tomar convenciones de Rails generalmente no ayuda en nada. Incluso diría Principios sobre la Convención sobre la Configuración .

Principios y Motivaciones Subyacentes

  • Ser mentalmente manejable
    • El cerebro solo puede tratar y pensar en un pequeño número de cosas relacionadas al mismo tiempo. Por eso utilizamos directorios. Nos ayuda a lidiar con la complejidad al concentrarnos en pequeñas porciones.
  • Sea del tamaño apropiado
    • No cree "Directorios de Mansion" donde solo hay 1 archivo de solo 3 directorios hacia abajo. Puede ver que esto sucede en Ansible Best Practices, que confunde proyectos pequeños para crear más de 10 directorios con capacidad para más de 10 archivos cuando 1 directorio con 3 archivos sería mucho más apropiado. No conduzca un autobús para ir al trabajo (a menos que sea un conductor de autobús, pero incluso entonces está manejando un autobús para NO trabajar), así que no cree estructuras de sistemas de archivos que no estén justificadas por los archivos reales que contienen. .
  • Ser modular pero pragmático.
    • La comunidad de nodos en general prefiere pequeños módulos. Cualquier cosa que se pueda separar completamente de su aplicación debe extraerse en un módulo para uso interno o publicarse públicamente en npm. Sin embargo, para las aplicaciones de tamaño mediano que son el alcance aquí, la sobrecarga de esto puede agregar tedio a su flujo de trabajo sin un valor proporcional. Por lo tanto, para el momento en que tenga algún código que se haya factorizado pero no sea suficiente para justificar un módulo npm completamente independiente, simplemente considérelo un " proto-módulo " con la expectativa de que cuando se cruce un umbral de tamaño, se extraerá.
    • Algunas personas como @hij1nx incluso incluyen un directorio app/node_modules y tienen archivos package.json en los directorios de proto-módulos para facilitar esa transición y actuar como un recordatorio.
  • Ser fácil de localizar código
    • Dada una característica para construir o un error para corregir, nuestro objetivo es que un desarrollador no tenga problemas para localizar los archivos de origen involucrados.
    • Los nombres son significativos y precisos
    • El código crufty se elimina completamente, no se deja en un archivo huérfano o simplemente se comenta
  • Ser amigable con las búsquedas
    • todo el código fuente de la primera parte está en el directorio de la app , de modo que puede hacer cd ejecutar run / grep / xargs / ag / ack / etc y no ser distraído por coincidencias de terceros
  • Use nombres simples y obvios
    • npm ahora parece requerir nombres de paquetes en minúsculas. Lo encuentro en su mayoría terrible, pero debo seguir la manada, por lo tanto, los nombres de archivos deben usar kebab-case , aunque el nombre de la variable para JavaScript debe ser camelCase porque - es un signo menos en JavaScript.
    • el nombre de la variable coincide con el nombre base de la ruta del módulo, pero con kebab-case transformado a camelCase
  • Agrupar por acoplamiento, no por función
    • Esta es una salida importante de la convención de app/views , app/controllers , app/models Ruby on Rails, etc.
    • Las características se agregan a una pila completa, por lo que quiero centrarme en una pila completa de archivos que son relevantes para mi característica. Cuando agrego un campo de número de teléfono al modelo de usuario, no me importa ningún controlador que no sea el controlador de usuario, y no me importa ningún otro modelo que no sea el modelo de usuario.
    • Entonces, en lugar de editar 6 archivos que están en su propio directorio e ignorar toneladas de otros archivos en esos directorios, este repositorio está organizado de tal manera que todos los archivos que necesito para construir una característica están colocados
    • Por la naturaleza de MVC, la vista de usuario está acoplada al controlador de usuario que está acoplado al modelo de usuario. Entonces, cuando cambio el modelo de usuario, esos 3 archivos a menudo cambian juntos, pero el controlador de transacciones o el controlador del cliente están desacoplados y, por lo tanto, no están involucrados. Lo mismo se aplica a los diseños que no son MVC por lo general también.
    • El estilo MVC o MOVE se desacopla en términos de qué código va en qué módulo aún se recomienda, pero la distribución de los archivos MVC en directorios de hermanos es una molestia.
    • Así, cada uno de mis archivos de rutas tiene la porción de las rutas que posee. Un archivo de routes.rb estilo routes.rb es muy útil si desea obtener una visión general de todas las rutas en la aplicación, pero cuando en realidad está creando características y corrigiendo errores, solo le interesan las rutas relevantes para la pieza que está cambiando.
  • Almacenar las pruebas junto al código.
    • Esto es solo una instancia de "agrupar por acoplamiento", pero quería llamarlo específicamente. He escrito muchos proyectos en los que las pruebas se realizan bajo un sistema de archivos paralelo llamado "pruebas" y ahora que comencé a colocar mis pruebas en el mismo directorio que su código correspondiente, nunca volveré. Esto es más modular y mucho más fácil de trabajar en los editores de texto y alivia un montón de tonterías "../../ ..". Si tiene dudas, pruébelo en algunos proyectos y decida usted mismo. No voy a hacer nada más allá de esto para convencerte de que es mejor.
  • Reducir el acoplamiento transversal con los eventos.
    • Es fácil pensar "OK, cada vez que se crea un nuevo acuerdo, deseo enviar un correo electrónico a todos los vendedores", y luego simplemente coloque el código para enviar esos correos electrónicos en la ruta que crea acuerdos.
    • Sin embargo, este acoplamiento eventualmente convertirá tu aplicación en una bola de barro gigante.
    • En su lugar, DealModel debería simplemente disparar un evento "crear" y no ser consciente de qué otra cosa podría hacer el sistema en respuesta a eso.
    • Cuando se codifica de esta manera, es mucho más posible colocar todo el código relacionado con el usuario en la app/users porque no hay un nido de lógica de negocios acoplada en todo el lugar que contamina la pureza de la base del código de usuario.
  • El flujo de código es seguir
    • No hagas cosas mágicas. No cargue automáticamente archivos desde directorios mágicos en el sistema de archivos. No seas rieles. La aplicación comienza en app/server.js:1 y puedes ver todo lo que carga y ejecuta siguiendo el código.
    • No hagas DSL para tus rutas. No hagas una metaprogramación tonta cuando no se requiere.
    • Si su aplicación es tan grande que hacer magicRESTRouter.route(somecontroller, {except: ''POST''}) es una gran victoria para usted sobre 3 app.get básica, app.put , app.del , llamadas, probablemente esté construyendo una aplicación monolítica que es demasiado grande para trabajar con eficacia. Disfrute de las grandes ganancias, no para convertir 3 líneas simples en 1 línea compleja.
  • Usa nombres de archivo de kebabs inferiores

    • Este formato evita problemas de sensibilidad de mayúsculas y minúsculas en el sistema de archivos en todas las plataformas
    • npm prohíbe mayúsculas en los nuevos nombres de paquetes, y esto funciona bien con eso

      específicos de express.js

  • No utilice app.configure . Es casi completamente inútil y simplemente no lo necesitas. Está en un montón de repetitivo debido a copypasta sin sentido.

  • LA ORDEN DE MIDDLEWARE Y LAS RUTAS EN MATERIA EXPRESA !!!
    • Casi todos los problemas de enrutamiento que veo en son middleware express fuera de orden
    • En general, usted desea que sus rutas estén desacopladas y que no confíen tanto en el pedido.
    • No use app.use para su aplicación completa si realmente solo necesita ese middleware para 2 rutas (lo estoy viendo, body-parser )
    • Asegúrese de que cuando todo esté dicho y hecho tenga EXACTAMENTE este orden:
      1. Cualquier middleware de aplicación super importante
      2. Todas sus rutas y middlewares de rutas variadas.
      3. ENTONCES manejadores de errores
  • Lamentablemente, al estar inspirado en sinatra, express.js generalmente asume que todas sus rutas estarán en server.js y quedará claro cómo se ordenan. Para una aplicación de tamaño mediano, dividir las cosas en módulos de rutas separadas es bueno, pero sí implica un peligro de middleware fuera de orden

La aplicación del enlace simbólico truco

Hay muchos enfoques descritos y discutidos en detalle por la comunidad en el gran sentido local. Mejor requiere () rutas para Node.js. Es posible que pronto decida preferir "simplemente tratar con un montón de ../../../ .." o usar el requireFrom requireFrom. Sin embargo, en este momento, he estado usando el truco del enlace simbólico que se detalla a continuación.

Por lo tanto, una forma de evitar las necesidades internas del proyecto con rutas relativas molestas como require("../../../config") es usar el siguiente truco:

  • crea un enlace simbólico bajo node_modules para tu aplicación
    • cd node_modules && ln -nsf ../app
  • añada solo el enlace simbólico node_modules / app , no toda la carpeta node_modules, a git
    • git add -f node_modules / app
    • Sí, todavía debe tener "node_modules" en su archivo .gitignore
    • No, no debes poner "node_modules" en tu repositorio de git. Algunas personas te recomendarán que hagas esto. Son incorrectos
  • Ahora puede requerir módulos dentro del proyecto usando este prefijo
    • var config = require("app/config");
    • var DealModel = require("app/deals/deal-model") ;
  • Básicamente, esto hace que el trabajo dentro del proyecto requiera un trabajo muy similar al requerido para los módulos npm externos.
  • Lo sentimos, los usuarios de Windows, deben atenerse a las rutas relativas del directorio principal.

Configuración

Generalmente, los módulos de código y las clases esperan que solo se pase un objeto de options JavaScript básico. Solo app/server.js debe cargar el módulo app/config.js . A partir de ahí, puede sintetizar pequeños objetos de options para configurar subsistemas según sea necesario, pero el acoplamiento de cada subsistema a un gran módulo de configuración global lleno de información adicional es un mal acoplamiento.

Intente centralizar la creación de conexiones de base de datos y transfiéralas a los subsistemas en lugar de pasar parámetros de conexión y hacer que los subsistemas realicen las conexiones salientes.

NODE_ENV

Esta es otra idea atractiva pero terrible transmitida desde Rails. Debe haber exactamente 1 lugar en su aplicación, app/config.js que NODE_ENV la variable de entorno NODE_ENV . Todo lo demás debería tomar una opción explícita como un argumento de constructor de clase o parámetro de configuración del módulo.

Si el módulo de correo electrónico tiene una opción sobre cómo enviar correos electrónicos (SMTP, iniciar sesión en stdout, poner en cola, etc.), debería elegir una opción como {deliver: ''stdout''} pero no debería verificar NODE_ENV .

Pruebas

Ahora guardo mis archivos de prueba en el mismo directorio que su código correspondiente y uso las convenciones de nombres de extensión de nombre de archivo para distinguir las pruebas del código de producción.

  • foo.js tiene el módulo "foo" código de
  • foo.tape.js tiene las pruebas basadas en nodos para foo y vive en el mismo directorio
  • foo.btape.js puede usarse para pruebas que deben ejecutarse en un entorno de navegador

Yo uso globs del sistema de archivos y el find . -name ''*.tape.js'' find . -name ''*.tape.js'' para obtener acceso a todas mis pruebas según sea necesario.

Cómo organizar el código dentro de cada archivo de módulo .js

El alcance de este proyecto es principalmente acerca de dónde van los archivos y directorios, y no quiero agregar otro alcance, pero solo mencionaré que organizo mi código en 3 secciones distintas.

  1. El bloque de apertura de CommonJS requiere llamadas a dependencias estatales
  2. Bloque de código principal de JavaScript puro. No hay contaminación de CommonJS aquí. No haga referencia a exportaciones, módulo, o requiera.
  3. Bloque de cierre de CommonJS para configurar exportaciones.

Bueno, puse mis rutas como un archivo json, que leí al principio, y en un bucle for en app.js configuré las rutas. Route.json incluye a qué vista debe llamarse y la clave para los valores que se enviarán a la ruta.
Esto funciona para muchos casos simples, pero tuve que crear manualmente algunas rutas para casos especiales.


Creo que es una gran manera de hacerlo. No se limita a expresar, pero he visto bastantes proyectos de node.js en github haciendo lo mismo. Se eliminan los parámetros de configuración + los módulos más pequeños (en algunos casos, cada URI) se factorizan en archivos separados.

Recomendaría ir a través de proyectos expresos específicos en github para tener una idea. OMI, la forma en que estás haciendo es correcta.


Esto puede ser de interés:

https://github.com/flatiron/nconf

Configuración jerárquica de node.js con archivos, variables de entorno, argumentos de línea de comandos y fusión de objetos atómicos.


Ha pasado bastante tiempo desde la última respuesta a esta pregunta y Express también lanzó recientemente la versión 4, que agregó algunas cosas útiles para organizar la estructura de la aplicación.

A continuación se encuentra una publicación de blog actualizada sobre las mejores prácticas sobre cómo estructurar su aplicación Express. http://www.terlici.com/2014/08/25/best-practices-express-structure.html

También hay un repositorio de GitHub que aplica el consejo en el artículo. Siempre está al día con la última versión Express.
https://github.com/terlici/base-express


He escrito un post exactamente sobre este asunto. Básicamente hace uso de un routeRegistrar que recorre los archivos en la carpeta /controllers llaman a su función init . La función init toma la variable de app Express como un parámetro para que pueda registrar sus rutas de la forma que desee.

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


La siguiente es la respuesta literal de Peter Lyons, transferida a vanilla JS de Coffeescript, según lo solicitado por varios otros. La respuesta de Peter es muy capaz, y cualquiera que vote mi respuesta también debería votar la suya.

Config

Lo que estás haciendo está bien. Me gusta tener mi propio espacio de nombres de configuración configurado en un archivo config.js nivel config.js con un espacio de nombres anidado como este.

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

Esto es amigable para la edición sysadmin. Entonces cuando necesito algo, como la información de conexión de DB, es

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

Rutas / Controladores

Me gusta dejar mis rutas con mis controladores y organizarlos en un subdirectorio de app/controllers . Luego puedo cargarlos y dejar que agreguen las rutas que necesiten.

En mi app/server.js archivo javascript hago:

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

Así que tengo archivos como:

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

Y, por ejemplo, en mi controlador de dominios, tengo una función de setup como esta.

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

Puntos de vista

Poner vistas en la app/views está convirtiendo en el lugar habitual. Lo planteo así.

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

Archivos estáticos

Ir en un subdirectorio public .

Github / Semver / NPM

Coloque un archivo de rebajas README.md en su raíz de git repo para github.

Coloque un archivo package.json con un número de versión semántica en su raíz de git repo para NPM.


Me gusta usar una "aplicación" global, en lugar de exportar una función, etc.


Mi pregunta se introdujo en abril de 2011, es bastante viejo. Durante este tiempo, podría mejorar mi experiencia con Express.js y cómo crear una arquitectura de una aplicación escrita con esta biblioteca. Entonces, comparto aquí mi experiencia.

Aquí está mi estructura de directorio:

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

El objetivo del archivo app.js es arrancar la aplicación expressjs. Carga el módulo de configuración, el módulo de registrador, espera la conexión de la base de datos, ... y ejecuta el servidor 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(); });

rutas /

El directorio de rutas tiene un archivo index.js . Su objetivo es introducir un tipo de magia para cargar todos los demás archivos dentro del directorio de routes/ . Aquí está la implementación:

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

Con ese módulo, crear una nueva definición de ruta e implementación es realmente fácil. Por ejemplo, hello.js :

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

Cada módulo de ruta es independiente .


No creo que sea un buen enfoque para agregar rutas a la configuración. Una mejor estructura podría ser algo como esto:

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

Por lo tanto, products.js y users.js contendrán todas sus rutas dentro de las cuales toda la lógica.


ahora es Finales de 2015 y después de desarrollar mi estructura durante 3 años y en proyectos pequeños y grandes. ¿Conclusión?

No hagas un MVC grande, sino que lo separas en módulos

Asi que...

¿Por qué?

  • Por lo general, uno trabaja en un módulo (por ejemplo, Productos), que puede cambiar de forma independiente.

  • Eres capaz de reutilizar módulos

  • Eres capaz de probarlo por separado

  • Eres capaz de reemplazarlo por separado

  • Tienen interfaces claras (estables).

    -A más tardar, si hubiera varios desarrolladores trabajando, la separación de módulos ayuda

El proyecto nodebootstrap tiene un enfoque similar a mi estructura final. ( github )

¿Cómo se ve esta estructura?

  1. Módulos pequeños, encapsulados , cada uno con MVC separado

  2. Cada módulo tiene un package.json

  3. Pruebas como parte de la estructura (en cada módulo)

  4. Configuración global , bibliotecas y servicios.

  5. Docker integrado, Cluster, para siempre

Folderoverview (ver carpeta lib para módulos):


http://locomotivejs.org/ proporciona una forma de estructurar una aplicación creada con Node.js y Express.

Desde el sitio web:

"Locomotive es un marco web para Node.js. Locomotive admite patrones MVC, rutas RESTful y convención sobre la configuración, al tiempo que se integra a la perfección con cualquier base de datos y motor de plantillas. Locomotive se basa en Express, conservando la potencia y la simplicidad que espera. desde el nodo ".


ACTUALIZACIÓN (2013-10-29) : Por favor, vea también mi otra respuesta, que tiene JavaScript en lugar de CoffeeScript por demanda popular, así como un repositorio de github y un README extenso que detalla mis últimas recomendaciones sobre este tema.

Config

Lo que estás haciendo está bien. Me gusta tener mi propio espacio de nombres de configuración configurado en un archivo config.coffee nivel config.coffee con un espacio de nombres anidado como este.

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

Esto es amigable para la edición sysadmin. Entonces cuando necesito algo, como la información de conexión de DB, es

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

Rutas / Controladores

Me gusta dejar mis rutas con mis controladores y organizarlos en un subdirectorio de app/controllers . Luego puedo cargarlos y dejar que agreguen las rutas que necesiten.

En mi app/server.coffee coffeescript archivo que hago:

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

Así que tengo archivos como:

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

Y, por ejemplo, en mi controlador de dominios, tengo una función de setup como esta.

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

Puntos de vista

Poner vistas en la app/views está convirtiendo en el lugar habitual. Lo planteo así.

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

Archivos estáticos

Ir en un subdirectorio public .

Github / Semver / NPM

Coloque un archivo de rebajas README.md en su raíz de git repo para github.

Coloque un archivo package.json con un número de versión semántica en su raíz de git repo para NPM.


Así es como se ve la mayor parte de mi estructura de directorios de proyectos Express.

Por lo general hago una express dirnamepara inicializar el proyecto, perdona mi pereza, pero es muy flexible y extensible. PD: necesitas obtener express-generatoreso (para aquellos que lo buscan sudo npm install -g express-generator, sudo porque lo estás instalando globalmente)

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

Usted debe preguntarse por qué archivos .env? ¡Porque funcionan! ¡Utilizo el dotenvmódulo en mis proyectos (mucho recientemente) y funciona! Pop en estas 2 declaraciones en app.jsowww

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

Y otra línea para configurar rápidamente /bower_componentspara servir contenido estático bajo el recurso/ext

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

Probablemente puede ser adecuado para las personas que buscan utilizar Express y Angular juntas, o simplemente expresar sin esa javascriptsjerarquía, por supuesto.


Estoy dando la estructura de carpetas de estilo MVC, por favor encontrar a continuación.

Utilizamos la siguiente estructura de carpetas para nuestras aplicaciones web grandes y medianas.

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

He creado un módulo npm para el estructurador de carpetas mvc de express express.

Por favor, busque el siguiente https://www.npmjs.com/package/express-mvc-generator

Solo pasos simples para generar y usar estos módulos.

i) instalar el módulo npm install express-mvc-generator -g

ii) comprobar opciones express -h

iii) Generar estructura express mvc express myapp

iv) Instalar dependencias npm install:

v) Abra su config / database.js, configure su db mongo.

vi) Ejecutar la aplicación node apponodemon app

vii) Revisar la URL http://localhost:8042/signup O http://yourip:8042/signup


Recientemente he adoptado módulos como mini-aplicaciones independientes.

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

Ahora para cualquier módulo de enrutamiento (# .js), las vistas (* .ejs), js, css y los activos están uno al lado del otro. El enrutamiento de submódulos se configura en el # .js principal con dos líneas adicionales

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

De esta manera, incluso los sub-submódulos son posibles.

No te olvides de configurar la vista en el directorio src

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


Mi estructura expresa 4. https://github.com/odirleiborgert/borgert-express-boilerplate

Paquetes

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

Estructura

|-- app |-- controllers |-- helpers |-- middlewares |-- models |-- routes |-- services |-- bin |-- logs |-- node_modules |-- public |-- components |-- images |-- javascripts |-- stylesheets |-- views |-- .env |-- .env-example |-- app.js |-- README.md