Node.js / Express.js – ¿Cómo funciona app.router?

Antes de preguntar sobre la app.router , creo que debería explicar al menos lo que creo que sucede cuando se trabaja con middleware. Para usar middleware, la función que se debe usar es app.use() . Cuando se ejecuta el middleware, llamará al siguiente middleware utilizando next() o lo hará para que no se vuelva a llamar al middleware. Eso significa que el orden en el que coloco mis llamadas de middleware es importante, porque algunos middleware dependen de otros middleware, y es posible que ni siquiera se invoque algún middleware cerca del final.

Hoy estaba trabajando en mi aplicación y tenía mi servidor ejecutándose en segundo plano. Quería hacer algunos cambios y actualizar mi página y ver los cambios de inmediato. Específicamente, estaba haciendo cambios en mi diseño. No pude hacer que funcionara, así que busqué en Stack Overflow la respuesta y encontré esta pregunta . Dice para asegurarse de que express.static() esté debajo de require('stylus') . Pero cuando estaba mirando el código de ese OP, vi que tenía su app.router Llamada al teléfono al final de sus llamadas al middleware, e intenté averiguar por qué.

Cuando hice 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 mi app.router sobre ambos express.static() y require('stylus') llamadas. Entonces parece que, si ya viene configurado de esa manera, entonces debería seguir así.

Después de reorganizar mi código para poder ver mis cambios en el lápiz óptico, 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'); }); 

Así que decidí que el primer paso sería averiguar por qué es importante tener incluso una app.router en mi código. Así que lo comenté, comencé mi aplicación y navegué a / . Mostró mi página de índice muy bien. Hmm, tal vez funcionó porque estaba exportando el enrutamiento desde mi archivo de rutas (routes.index). Luego, navegué a /test y se muestra Test en la pantalla. Jaja, está bien, no tengo idea de qué app.router hace. Ya sea que esté incluido en mi código o no, mi ruta está bien. Así que definitivamente me estoy perdiendo algo.

Ésta es mi pregunta:

¿Podría alguien explicar qué app.router hace, qué importancia tiene y dónde debo app.router en mis llamadas de middleware? También sería bueno si tuviera una breve explicación sobre express.static() . Por lo que puedo decir, express.static() es un caché de mi información, y si la aplicación no puede encontrar la página solicitada, comprobará el caché para ver si existe.

Nota: Esto describe cómo Express trabajó 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 ) del disco. Le da una ruta (a veces llamada punto de assembly) y sirve los archivos en esa carpeta.

Por ejemplo, express.static('/var/www') serviría los archivos en esa carpeta. Entonces, una solicitud a su servidor Node para http://server/file.html serviría a /var/www/file.html .

router es un código que ejecuta tus rutas. Cuando haces app.get('/user', function(req, res) { ... }); , es el router que realmente invoca la función de callback para procesar la solicitud.

El orden en que pasa las cosas a app.use determina el orden en que se le da a cada middleware 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 solicita http://server/test.html ? Cualquiera que sea el middleware que se use primero.

Si haces esto:

 app.use(express.static(__dirname + '/public')); app.use(app.router); 

Luego se sirve el archivo en el disco.

Si lo haces de otra manera,

 app.use(app.router); app.use(express.static(__dirname + '/public')); 

Luego, el manejador de ruta recibe la solicitud y se envía “Hola desde el manejador de ruta” al navegador.

Por lo general, desea colocar el enrutador sobre el middleware estático para que un archivo con nombre accidental no pueda anular una de sus rutas.

Tenga en cuenta que si no use explícitamente el router , Express lo agrega implícitamente en el punto en que define una ruta (razón por la cual sus rutas aún funcionaron a pesar de que usted comentó sobre app.use(app.router) ).


Un comentarista ha mencionado otro punto sobre el orden de la static y el router que no había abordado: el impacto en el rendimiento general de su aplicación.

Otra razón para use router encima de la static es optimizar el rendimiento. Si coloca la static primero, golpeará el 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 el router primero, una solicitud que coincida con una ruta nunca debe golpear el disco, lo que ahorra preciosos milisegundos.

Por supuesto, hay formas de mitigar los gastos generales static .

La mejor opción es colocar todos sus recursos estáticos en una carpeta específica. (IE /static ) Puede montar static en 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ía este router encima. 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 staticCache caché los recursos estáticos en la memoria para que no tenga que presionar el disco para buscar los archivos solicitados comúnmente. ( Advertencia: staticCache aparentemente será eliminado en el futuro).

Sin embargo, no creo que staticCache caché las respuestas negativas (cuando un archivo no existe), por lo que no ayuda si ha colocado staticCache encima del router sin montarlo en una ruta.

Al igual que con todas las preguntas sobre el rendimiento, mida y compare su aplicación real (bajo carga) para ver dónde están realmente los cuellos de botella.


Express 4

Express 4.0 elimina app.router . Todo el middleware ( app.use ) y las rutas ( app.get et al) ahora se procesan exactamente 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 debes hacer app.use(app.router) . Esto elimina el problema más común con Express.

En otras palabras, la app.use() y la app[VERB]() funcionará exactamente en el orden en que se app.use() .

 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 del cliente a un punto final en 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 se corresponde.

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 ()”.

aplicación.ruta () utilizada como acceso directo al enrutador para definir múltiples solicitudes en una ruta

cuando estamos usando app.route (), estamos adjuntando 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') })