OK, ha pasado un tiempo y esta es una pregunta popular, así que seguí adelante y creé un repositorio de andamios github con código JavaScript y un largo archivo 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. Solicitudes de extracción bienvenidas.
Aquí hay una instantánea de README ya que stackoverflow no le gusta las respuestas de solo un enlace. Haré algunas actualizaciones ya que este es un nuevo proyecto que continuaré actualizando, pero finalmente el repositorio de github será el lugar actualizado para esta información.
Estructura de código expreso
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 de diciembre de 2016
¿Qué tan grande es su aplicación?
Las aplicaciones web no son todas iguales y, en mi opinión, no hay una única estructura de código que deba aplicarse a todas las aplicaciones express.js.
Si su aplicación es pequeña, no necesita una estructura de directorio tan profunda como se ejemplifica aquí. Simplemente manténgalo simple y pegue un puñado de .js
archivos en la raíz de su repositorio y listo. Voilà.
Si su aplicación es enorme, en algún momento deberá dividirla en paquetes npm distintos. En general, el enfoque de node.js parece favorecer muchos paquetes pequeños, al menos para las bibliotecas, y debe construir su aplicación utilizando varios paquetes npm, ya que eso comienza a tener sentido y justifica la sobrecarga. Entonces, a medida que su aplicación crece y una 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.
Por lo tanto, el objetivo de este proyecto es ilustrar una estructura viable para una aplicación de tamaño mediano.
¿Cuál es su arquitectura general?
Existen muchos enfoques para crear una aplicación web, como
- Lado del servidor MVC a la Ruby on Rails
- Estilo de aplicación de página única a la MongoDB / Express / Angular / Node (MEAN)
- Sitio web básico con algunas formas
- Estilo de Modelos / Operaciones / Vistas / Eventos a la MVC está muerto, es hora de MUDARSE
- 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, solo se trata de andamios y no es una aplicación que funciona completamente, pero supongo que 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 página única
- La aplicación expone una API de estilo REST / JSON al navegador
- La aplicación modela un dominio comercial simple, en este caso, es una aplicación de concesionario de automóviles
¿Y qué hay de 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 "Convención sobre la configuración" que han adoptado, aunque ampliamente aceptadas y utilizadas, en realidad no son muy ú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 basados en esos principios, las convenciones de Ruby on Rails tienen sentido (principalmente) para la comunidad de Ruby on Rails. Sin embargo, simplemente imitar esas convenciones sin pensarlo pasa por alto el punto. Una vez que comprenda 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 de inicio.
Para la comunidad de Rails, quieren poder tener un solo desarrollador de Rails para cambiar de una aplicación a otra y estar familiarizados y cómodos 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 ethos general es mucho más salvaje que cualquier cosa, y realmente no tenemos ningún problema con eso. Así es como nosotros lo hacemos. Estamos acostumbrados 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 Convención sobre Configuración .
Principios y motivaciones subyacentes
El truco del enlace simbólico de la aplicación
Hay muchos enfoques descritos y discutidos ampliamente por la comunidad en la gran GIST Mejor locales requieren caminos () para Node.js . Pronto puedo decidir preferir "tratar con muchos ../../../ .." o usar el módulo requireFrom. Sin embargo, por el momento, he estado usando el truco de enlace simbólico que se detalla a continuación.
Entonces, una forma de evitar el intraproyecto requiere con rutas relativas molestas como require("../../../config")
es usar el siguiente truco:
- crear un enlace simbólico debajo de node_modules para su aplicación
- cd node_modules && ln -nsf ../app
- agregue solo el enlace simbólico node_modules / app en sí , no toda la carpeta node_modules, a git
- git add -f node_modules / app
- Sí, aún debe tener "node_modules" en su
.gitignore
archivo
- No, no debe poner "node_modules" en su repositorio git. Algunas personas te recomendarán que hagas esto. Son incorrectos
- Ahora puede requerir módulos dentro del proyecto utilizando 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, usuarios de Windows, deben seguir las rutas relativas del directorio principal.
Configuración
Generalmente, los módulos y clases de código esperan que solo se options
pase un objeto JavaScript básico . Solo se app/server.js
debe cargar el app/config.js
módulo. A partir de ahí, puede sintetizar pequeños options
objetos para configurar subsistemas según sea necesario, pero acoplar 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 pasarlas a subsistemas en lugar de pasar parámetros de conexión y hacer que los subsistemas establezcan conexiones salientes.
NODE_ENV
Esta es otra idea tentadora pero terrible de Rails. Debe haber exactamente 1 lugar en su aplicación, app/config.js
que observe la NODE_ENV
variable de entorno. Todo lo demás debería tomar una opción explícita como 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 entregar correos electrónicos (SMTP, iniciar sesión en stdout, poner en cola, etc.), debería tomar una opción como, {deliver: 'stdout'}
pero no debería comprobarlo NODE_ENV
.
Pruebas
Ahora mantengo mis archivos de prueba en el mismo directorio que su código correspondiente y uso convenciones de nomenclatura de extensión de nombre de archivo para distinguir las pruebas del código de producción.
foo.js
tiene el código del módulo "foo"
foo.tape.js
tiene las pruebas basadas en nodos para foo y vive en el mismo directorio
foo.btape.js
se puede usar para pruebas que deben ejecutarse en un entorno de navegador
Uso globs del sistema de archivos y el find . -name '*.tape.js'
comando para obtener acceso a todas mis pruebas según sea necesario.
Cómo organizar el código dentro de cada .js
archivo de módulo
El alcance de este proyecto se trata principalmente de dónde van los archivos y directorios, y no quiero agregar mucho otro alcance, pero solo mencionaré que organizo mi código en 3 secciones distintas.
- El bloque de apertura de CommonJS requiere llamadas a dependencias de estado
- Bloque de código principal de JavaScript puro. No hay contaminación CommonJS aquí. No haga referencia a exportaciones, módulos o requisitos.
- Bloque de cierre de CommonJS para establecer exportaciones