Node.js/Express.js: ¿Cómo funciona app.router?
Antes de preguntar, app.router
creo que debería explicar al menos lo que creo que sucede cuando se trabaja con middleware. Para utilizar middleware, la función a utilizar es app.use()
. Cuando se ejecuta el middleware, llamará al siguiente middleware utilizandonext()
o hará que no se llame a más middleware. Eso significa que el orden en el que realizo mis llamadas de middleware es importante, porque algunos middleware dependen de otros middleware y es posible que algunos middleware cercanos al final ni siquiera sean llamados.
Hoy estaba trabajando en mi aplicación y tenía mi servidor ejecutándose en segundo plano. Quería hacer algunos cambios, actualizar mi página y ver los cambios inmediatamente. Específicamente, estaba haciendo cambios en mi diseño. No pude hacerlo funcionar, así que busqué la respuesta en Stack Overflow y encontré esta pregunta . Dice que se asegure de que express.static()
esté debajo require('stylus')
. Pero cuando estaba mirando el código de ese OP, vi que tenía suapp.router
llamada al final de sus llamadas de middleware, y traté de descubrir por qué era así.
Cuando creé mi aplicación Express.js (versión 3.0.0rc4), utilicé el comando express app --sessions --css stylus
y en mi archivo app.js el código vino configurado con los app.router
dos anteriores express.static()
yrequire('stylus')
. Entonces parece que, si ya viene configurado de esa manera, entonces debería permanecer así.
Después de reorganizar mi código para poder ver los cambios de mi Stylus, se ve así:
app.configure(function(){
//app.set() calls
//app.use() calls
//...
app.use(app.router);
app.use(require('stylus').middleware(__dirname + '/public'));
app.use(express.static(__dirname + '/public', {maxAge: 31557600000}));
});
app.get('/', routes.index);
app.get('/test', function(req, res){
res.send('Test');
});
Entonces decidí que el primer paso sería descubrir por qué es importante tenerlo app.router
en mi código. Así que lo comenté, inicié mi aplicación y navegué hasta /
. Mostró mi página de índice muy bien. Hmm, tal vez funcionó porque estaba exportando la ruta desde mi archivo de rutas (routes.index). Luego navegué /test
y mostró Prueba en la pantalla. Jaja, está bien, no tengo idea de qué lo app.router
hace. Ya sea que esté incluido en mi código o no, mi enrutamiento está bien. Entonces definitivamente me estoy perdiendo algo.
Ésta es mi pregunta:
¿Podría alguien explicar qué app.router
es, su importancia y dónde debo colocarlo en mis llamadas de middleware? También sería bueno si recibiera una breve explicación sobre express.static()
. Hasta donde puedo decir, express.static()
es un caché de mi información, y si la aplicación no puede encontrar la página solicitada, verificará el caché para ver si existe.
Nota: Esto describe cómo funcionó Express en las versiones 2 y 3. Consulte el final de esta publicación para obtener información sobre Express 4.
static
simplemente sirve archivos ( recursos estáticos ) desde el disco. Le asigna una ruta (a veces llamada punto de montaje) y entrega los archivos en esa carpeta.
Por ejemplo, express.static('/var/www')
serviría los archivos de esa carpeta. http://server/file.html
Por lo tanto, serviría una solicitud a su servidor Node /var/www/file.html
.
router
es el código que ejecuta tus rutas. Cuando lo hace app.get('/user', function(req, res) { ... });
, es el router
que realmente invoca la función de devolución de llamada para procesar la solicitud.
El orden en el que pasa las cosas app.use
determina el orden en el que cada middleware tiene la oportunidad de procesar una solicitud. Por ejemplo, si tiene un archivo llamado test.html
en su carpeta estática y una ruta:
app.get('/test.html', function(req, res) {
res.send('Hello from route handler');
});
¿Cuál se envía a un cliente que lo solicita http://server/test.html
? Cualquier middleware que se le dé use
primero.
Si haces esto:
app.use(express.static(__dirname + '/public'));
app.use(app.router);
Luego se entrega el archivo en el disco.
Si lo haces al revés,
app.use(app.router);
app.use(express.static(__dirname + '/public'));
Luego, el controlador de ruta recibe la solicitud y se envía "Hola desde el controlador de ruta" al navegador.
Por lo general, desea colocar el enrutador encima del middleware estático para que un archivo con un nombre accidental no pueda anular una de sus rutas.
Tenga en cuenta que si no use
lo hace explícitamente router
, Express lo agrega implícitamente en el momento en que define una ruta (razón por la cual sus rutas aún funcionaron aunque haya comentado app.use(app.router)
).
Un comentarista mencionó otro punto sobre el orden static
y router
que no había abordado: el impacto en el rendimiento general de su aplicación.
Otra razón para lo use
router
anterior static
es optimizar el rendimiento. Si pones static
primero, accederás al disco duro en cada solicitud para ver si existe o no un archivo. En una prueba rápida , descubrí que esta sobrecarga ascendía a ~1 ms en un servidor descargado. (Es muy probable que ese número sea mayor bajo carga, donde las solicitudes competirán por el acceso al disco).
Con router
el primero, una solicitud que coincida con una ruta nunca tiene que llegar al disco, lo que ahorra preciosos milisegundos.
Por supuesto, hay formas de mitigar static
los gastos generales.
La mejor opción es colocar todos sus recursos estáticos en una carpeta específica. (IE /static
) Luego puede montar static
esa ruta para que solo se ejecute cuando la ruta comience con /static
:
app.use('/static', express.static(__dirname + '/static'));
En esta situación, pondrías esto arriba router
. Esto evita procesar otro middleware/enrutador si hay un archivo presente, pero para ser honesto, dudo que gane tanto.
También puede usar staticCache
, que almacena en caché los recursos estáticos en la memoria para que no tenga que acceder al disco para archivos solicitados con frecuencia. ( Advertencia: staticCache
aparentemente se eliminará en el futuro).
Sin embargo, no creo que staticCache
almacene en caché las respuestas negativas (cuando un archivo no existe), por lo que no ayuda si lo coloca staticCache
arriba router
sin montarlo en una ruta.
Al igual que con todas las preguntas sobre rendimiento, mida y compare su aplicación del mundo real (bajo carga) para ver dónde están realmente los cuellos de botella.
expreso 4
Express 4.0 elimina app.router
. Todo el middleware ( app.use
) y las rutas ( app.get
et al) ahora se procesan precisamente en el orden en que se agregan.
En otras palabras:
Todos los métodos de enrutamiento se agregarán en el orden en que aparecen. No deberías hacerlo
app.use(app.router)
. Esto elimina el problema más común con Express.En otras palabras, mezclar
app.use()
yapp[VERB]()
funcionará exactamente en el orden en que se llaman.
app.get('/', home); app.use('/public', require('st')(process.cwd())); app.get('/users', users.list); app.post('/users', users.create);
Lea más sobre los cambios en Express 4.
Enrutamiento significa determinar cómo responde una aplicación a una solicitud de un cliente a un punto final particular, que es un URI (o ruta) y un método de solicitud HTTP específico (GET, POST, etc.). Cada ruta puede tener una o más funciones de controlador, que se ejecutan cuando la ruta coincide.
En Express 4.0 Router, tenemos más flexibilidad que nunca para definir nuestras rutas.
express.Router() se usa varias veces para definir grupos de rutas.
ruta utilizada como middleware para procesar solicitudes.
ruta utilizada como middleware para validar parámetros usando ".param()".
app.route() se utiliza como acceso directo al enrutador para definir múltiples solicitudes en una ruta
cuando usamos app.route(), conectamos nuestra aplicación con ese enrutador.
var express = require('express'); //used as middleware
var app = express(); //instance of express.
app.use(app.router);
app.use(express.static(__dirname + '/public')); //All Static like [css,js,images] files are coming from public folder
app.set('views',__dirname + '/views'); //To set Views
app.set('view engine', 'ejs'); //sets View-Engine as ejs
app.engine('html', require('ejs').renderFile); //actually rendering HTML files through EJS.
app.get('/', function (req, res) {
res.render('index');
})
app.get('/test', function (req, res) {
res.send('test')
})