¿Existe una convención común para dividir y modularizar el app.js
archivo en una aplicación Express.js ? ¿O es común mantener todo en un solo archivo?
¿Existe una convención común para dividir y modularizar el app.js
archivo en una aplicación Express.js ? ¿O es común mantener todo en un solo archivo?
Respuestas:
Tengo el mío dividido de la siguiente manera:
~/app
|~controllers
| |-monkey.js
| |-zoo.js
|~models
| |-monkey.js
| |-zoo.js
|~views
| |~zoos
| |-new.jade
| |-_form.jade
|~test
| |~controllers
| |-zoo.js
| |~models
| |-zoo.js
|-index.js
Utilizo Exportaciones para devolver lo que es relevante. Por ejemplo, en los modelos que hago:
module.exports = mongoose.model('PhoneNumber', PhoneNumberSchema);
y luego, si necesito crear un número de teléfono, es tan simple como:
var PhoneNumber = require('../models/phoneNumber');
var phoneNumber = new PhoneNumber();
si necesito usar el esquema, entonces PhoneNumber.schema
(lo que supone que estamos trabajando desde la carpeta de rutas y necesitamos subir 1 nivel y luego bajar a los modelos)
El wiki express tiene una lista de frameworks construidos sobre él.
De ellos, creo que el matador de Twitter está bastante bien estructurado. De hecho, usamos un enfoque muy similar a cómo cargan partes de la aplicación.
derby.js también parece muy interesante. Es similar a un meteoro sin toda la publicidad y, de hecho, da crédito a quien se lo merece (en particular, nodo y expreso).
Si eres fanático de CoffeeScript (yo no lo soy) y reeeeaaaaaally quieres el L&F de Rails, también está Tower.js .
Si está familiarizado con Rails y no le importa que algunos conceptos se derramen, hay Locomotive . Es un marco ligero construido sobre Express. Tiene una estructura muy similar a RoR y transmite algunos de los conceptos más rudimentarios (como el enrutamiento).
Vale la pena echarle un vistazo incluso si no planea usarlo.
nodejs-express-mongoose-demo es muy similar a cómo he estructurado el mío. Echale un vistazo.
Advertencia: código de referencia que pirateé para eliminar el nodo, funciona, pero está lejos de ser elegante o pulido.
Para ser más específico sobre la división app.js
, tengo el siguiente archivo app.js
var express = require('express'),
bootstrap = require('./init/bootstrap.js'),
app = module.exports = express.createServer();
bootstrap(app);
Básicamente, esto significa que coloco todo mi bootstrapping en un archivo separado, luego arranco el servidor.
Entonces, ¿qué hace bootstrap ?
var configure = require("./app-configure.js"),
less = require("./watch-less.js"),
everyauth = require("./config-everyauth.js"),
routes = require("./start-routes.js"),
tools = require("buffertools"),
nko = require("nko"),
sessionStore = new (require("express").session.MemoryStore)()
module.exports = function(app) {
everyauth(app);
configure(app, sessionStore);
less();
routes(app, sessionStore);
nko('/9Ehs3Dwu0bSByCS');
app.listen(process.env.PORT);
console.log("server listening on port xxxx");
};
Bueno, divide toda la configuración de inicialización del servidor en buenos trozos. Específicamente
app.configure
)Por ejemplo, veamos el archivo de enrutamiento
var fs = require("fs"),
parseCookie = require('connect').utils.parseCookie;
module.exports = function(app, sessionStore) {
var modelUrl = __dirname + "/../model/",
models = fs.readdirSync(modelUrl),
routeUrl = __dirname + "/../route/"
routes = fs.readdirSync(routeUrl);
Aquí cargo todos mis modelos y rutas como matrices de archivos.
Descargo de responsabilidad: readdirSync
solo está bien cuando se llama antes de iniciar el servidor http (antes .listen
). Llamar a llamadas de bloqueo sincrónico a la hora de inicio del servidor solo hace que el código sea más legible (es básicamente un truco)
var io = require("socket.io").listen(app);
io.set("authorization", function(data, accept) {
if (data.headers.cookie) {
data.cookie = parseCookie(data.headers.cookie);
data.sessionId = data.cookie['express.sid'];
sessionStore.get(data.sessionId, function(err, session) {
if (err) {
return accept(err.message, false);
} else if (!(session && session.auth)) {
return accept("not authorized", false)
}
data.session = session;
accept(null, true);
});
} else {
return accept('No cookie', false);
}
});
Aquí presiono socket.io para usar la autorización en lugar de dejar que cualquier tom y jack hable con mi servidor socket.io
routes.forEach(function(file) {
var route = require(routeUrl + file),
model = require(modelUrl + file);
route(app, model, io);
});
};
Aquí comienzo mis rutas pasando el modelo relevante en cada objeto de ruta devuelto desde el archivo de ruta.
Básicamente, lo importante es que organizas todo en pequeños módulos agradables y luego tienes algún mecanismo de arranque.
Mi otro proyecto (mi blog) tiene un archivo de inicio con una estructura similar .
Descargo de responsabilidad: el blog está roto y no se construye, estoy trabajando en ello.
Para una organización de enrutamiento sostenible, puede consultar este artículo sobre el módulo de nodo express-routescan y probarlo. Esta es la mejor solución para mí.
Tengo mis aplicaciones construidas sobre la herramienta de generación rápida. Puede instalarlo ejecutándolo npm install express-generator -g
y ejecutándolo usando express <APP_NAME>
.
Para darle una perspectiva, una de las estructuras de mi aplicación más pequeña se veía así:
~/
|~bin
| |-www
|
|~config
| |-config.json
|
|~database
| |-database.js
|
|~middlewares
| |-authentication.js
| |-logger.js
|
|~models
| |-Bank.js
| |-User.js
|
|~routes
| |-index.js
| |-banks.js
| |-users.js
|
|~utilities
| |-fiat-converersion.js
|
|-app.js
|-package.json
|-package-lock.json
Una cosa interesante que me gusta de esta estructura que termino adoptando para cualquier aplicación express que desarrolle es la forma en que se organizan las rutas. No me gustó tener que requerir los archivos de cada ruta en el app.js y app.use()
cada ruta, especialmente a medida que el archivo crece. Como tal, me resultó útil agrupar y centralizar todos mis app.use()
archivos en un archivo ./routes/index.js.
Al final, mi app.js se verá así:
...
const express = require('express');
const app = express();
...
require('./routes/index')(app);
y mi ./routes/index.js se verá así:
module.exports = (app) => {
app.use('/users', require('./users'));
app.use('/banks', require('./banks'));
};
Puedo hacerlo simplemente require(./users)
porque escribí la ruta de los usuarios usando express.Router () que me permite "agrupar" múltiples rutas y luego exportarlas a la vez, con el objetivo de hacer la aplicación más modular.
Este es un ejemplo de lo que estaría bien en mi ruta ./routers/users.js:
const router = require('express').Router();
router.post('/signup', async (req, res) => {
// Signup code here
});
module.exports = router;
¡Esperamos que esto haya ayudado a responder su pregunta! ¡La mejor de las suertes!