web-dev-qa-db-fra.com

Node.js/Express.js - Comment fonctionne app.router?

Avant de poser des questions sur app.router, je pense que je devrais au moins expliquer ce que je pense lorsqu’on travaille avec un middleware. Pour utiliser un middleware, la fonction à utiliser est app.use(). Lorsque le middleware est en cours d'exécution, il appelle le prochain middleware à l'aide de next() ou le fait pour qu'aucun autre middleware ne soit appelé. Cela signifie que l'ordre dans lequel je place mes appels de middleware est important, car certains middleware dépendent d'autres middleware, et certains middleware proches de la fin pourraient même ne pas être appelés.

Aujourd'hui, je travaillais sur mon application et mon serveur fonctionnait en arrière-plan. Je voulais apporter des modifications et actualiser ma page et voir les modifications immédiatement. Plus précisément, je modifiais ma mise en page. Je ne pouvais pas le faire fonctionner alors j'ai cherché Stack Overflow pour la réponse et trouvé cette question . Il est indiqué de s’assurer que express.static() est inférieur à require('stylus'). Mais lorsque je regardais le code de cet OP, j'ai vu qu'il avait son appel app.router à la fin de ses appels de middleware, et j'ai essayé de comprendre pourquoi.

Lorsque j'ai créé mon application Express.js (version 3.0.0rc4), j'ai utilisé la commande express app --sessions --css stylus et, dans mon fichier app.js, le code a été configuré avec mon app.router au-dessus des appels express.static() et require('stylus'). Il semble donc que, si cela est déjà installé de cette façon, il devrait le rester.

Après avoir réorganisé mon code pour que je puisse voir les modifications de mon stylet, voici ce qui se passe:

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

J'ai donc décidé que la première étape serait de découvrir pourquoi il est important d'avoir même app.router dans mon code. Alors j'ai commenté, démarré mon application et navigué vers /. Il a bien affiché ma page d’index. Hmm, peut-être que cela a fonctionné parce que j'exportais le routage à partir de mon fichier de routes (routes.index). Alors ensuite, j'ai navigué vers /test et il a affiché Test à l'écran. Haha, OK, je n'ai aucune idée de ce que app.router fait. Que cela soit inclus dans mon code ou non, mon routage va bien. Donc, il me manque définitivement quelque chose.

Voici donc ma question:

Quelqu'un pourrait-il expliquer ce que app.router fait, son importance et où le placer dans mes appels de middleware? Ce serait aussi bien si j'avais une brève explication sur express.static(). Autant que je sache, express.static() est un cache de mes informations. Si l'application ne parvient pas à trouver la page demandée, elle le vérifiera pour voir si elle existe.

291
Aust

Remarque: Ceci décrit le fonctionnement d'Express dans les versions 2 et 3. Voir la fin de ce message pour plus d'informations sur Express 4.


static sert simplement des fichiers (static ressources) à partir du disque. Vous lui donnez un chemin (parfois appelé point de montage) et sert les fichiers de ce dossier.

Par exemple, express.static('/var/www') servira les fichiers de ce dossier. Ainsi, une demande adressée à votre serveur Node pour http://server/file.html servirait /var/www/file.html.

router est le code qui gère vos itinéraires. Lorsque vous faites app.get('/user', function(req, res) { ... });, c'est le router qui appelle réellement la fonction de rappel pour traiter la demande.

L'ordre dans lequel vous transmettez les éléments à app.use détermine l'ordre dans lequel chaque logiciel intermédiaire a la possibilité de traiter une demande. Par exemple, si vous avez un fichier appelé test.html dans votre dossier statique et une route:

app.get('/test.html', function(req, res) {
    res.send('Hello from route handler');
});

Lequel est envoyé à un client demandant http://server/test.html? Quel que soit le middleware donné à use en premier.

Si tu fais ça:

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

Ensuite, le fichier sur le disque est servi.

Si vous le faites dans l'autre sens,

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

Ensuite, le gestionnaire d'itinéraire reçoit la demande et "Hello from hand handler" est envoyé au navigateur.

Habituellement, vous voulez placer le routeur ci-dessus le middleware statique afin qu'un fichier nommé par inadvertance ne puisse pas remplacer l'un de vos itinéraires.

Notez que si vous n'avez pas explicitement use, router, il est ajouté implicitement par Express au moment où vous définissez un itinéraire (c'est pourquoi vos itinéraires ont toujours fonctionné même si vous avez commenté app.use(app.router)).


Un intervenant a évoqué un autre point concernant l'ordre de static et router que je n'avais pas abordé: l'impact sur les performances globales de votre application.

Une autre raison pour userouter ci-dessus static est d'optimiser les performances. Si vous mettez static en premier, vous frappez le disque dur à chaque demande pour voir si un fichier existe ou non. Dans un test rapide , j'ai constaté que cette surcharge s'élevait à environ 1 ms sur un serveur non chargé. (Ce nombre est très susceptible d'être plus élevé sous charge, où les demandes entreront en concurrence pour l'accès au disque.)

Avec router en premier, une demande correspondant à un itinéraire ne doit jamais frapper le disque, économisant de précieuses millisecondes.

Bien sûr, il existe des moyens d’atténuer les frais généraux de static.

La meilleure option consiste à placer toutes vos ressources statiques dans un dossier spécifique. (IE /static) Vous pouvez ensuite monter static sur ce chemin afin qu'il ne s'exécute que lorsque le chemin commence par /static:

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

Dans cette situation, vous mettriez ceci au-dessus de router. Cela évite de traiter un autre middleware/routeur si un fichier est présent, mais pour être honnête, je doute que vous gagniez autant.

Vous pouvez également utiliser staticCache , qui met en cache des ressources statiques en mémoire afin que vous n'ayez pas à chercher sur le disque pour les fichiers fréquemment demandés. ( Avertissement: staticCachesera apparemment supprimé à l'avenir.)

Cependant, je ne pense pas que staticCache mette en cache les réponses négatives (lorsqu'un fichier n'existe pas), cela n'aide donc pas si vous avez mis staticCache au-dessus de router sans le monter sur un chemin.

Comme pour toutes les questions relatives aux performances, mesurez et testez votre application réelle (sous charge) pour voir où se trouvent réellement les goulots d'étranglement.


Express 4

Express 4.0 supprime app.router. Tous les middleware (app.use) et les routes (app.get et autres) sont maintenant traités dans l'ordre exact dans lequel ils ont été ajoutés.

En d'autres termes:

Toutes les méthodes de routage seront ajoutées dans l'ordre dans lequel elles apparaissent. Vous devriez ne pas faire app.use(app.router). Cela élimine le problème le plus courant avec Express.

En d’autres termes, mélanger app.use() et app[VERB]() fonctionnera exactement dans l’ordre dans lequel ils ont été appelés.

app.get('/', home);
app.use('/public', require('st')(process.cwd()));
app.get('/users', users.list);
app.post('/users', users.create);

En savoir plus sur les modifications apportées à Express 4.

328
josh3736

Routage signifie déterminer comment une application répond à une demande client adressée à un point de terminaison particulier, à savoir un URI (ou chemin) et une méthode de demande HTTP spécifique (GET, POST, etc.) . Chaque route peut avoir une ou plusieurs fonctions de gestionnaire, qui sont exécutées lorsque la route est appariée.

Dans Express 4.0 Router, nous avons plus de flexibilité que jamais pour définir nos itinéraires.

express.Router () utilise plusieurs fois pour définir des groupes de routes.

route utilisée comme middleware pour traiter les demandes.

route utilisée comme middleware pour valider les paramètres à l'aide de ".param ()".

app.route () utilisé comme raccourci vers le routeur pour définir plusieurs demandes sur une route

lorsque nous utilisons app.route (), nous attachons notre application à ce routeur.

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')
})
2
Parth Raval

Dans la version 4 express, nous pouvons facilement définir des itinéraires de la manière suivante:

server.js:

const express = require('express');
const app = express();
const route = require('./route');

app.use('/route', route);
// here we pass in the imported route object

app.listen(3000, () => console.log('Example app listening on port 3000!'));

route.js:

const express = require('express');
const router = express.Router();

router.get('/specialRoute', function (req, res, next) {
     // route is now http://localhost:3000/route/specialRoute
});

router.get('/', function (req, res, next) {
    // route is now http://localhost:3000/route
});

module.exports = router;

Dans server.js, nous avons importé l'objet routeur du fichier route.js et l'appliquons de la manière suivante dans server.js:

app.use('/route', route);

Désormais, tous les itinéraires du route.js ont l'URL de base suivante:

http: // localhost: 3000/route

Pourquoi cette approche:

Le principal avantage de cette approche est que notre application est désormais plus modulaire. Tous les gestionnaires d'itinéraire d'un itinéraire donné peuvent maintenant être placés dans différents fichiers, ce qui rend tout plus facile à gérer et à retrouver. 

0
Willem van der Veen