web-dev-qa-db-fra.com

Comment créer des variables globales accessibles dans toutes les vues en utilisant Express / Node.JS?

Ok, j'ai donc construit un blog en utilisant Jekyll et vous pouvez définir des variables dans un fichier _config.yml qui sont accessibles dans tous les modèles/mises en page. J'utilise actuellement Node.JS / Express avec EJS templates et ejs- locals (pour les partiels/mises en page. Je cherche à faire quelque chose de similaire aux variables globales comme site.title qui se trouvent dans _config.yml si quelqu'un connaît Jekyll. J'ai des variables telles que le titre du site (plutôt que le titre de la page), l'auteur/le nom de l'entreprise, qui restent les mêmes sur toutes mes pages.

Voici un exemple de ce que je suis en train de faire:

exports.index = function(req, res){
    res.render('index', { 
        siteTitle: 'My Website Title',
        pageTitle: 'The Root Splash Page',
        author: 'Cory Gross',
        description: 'My app description',
        indexSpecificData: someData
    });
};

exports.home = function (req, res) {
    res.render('home', {
        siteTitle: 'My Website Title',
        pageTitle: 'The Home Page',
        author: 'Cory Gross',
        description: 'My app description',
        homeSpecificData: someOtherData
    });
};

J'aimerais pouvoir définir des variables telles que le titre, la description, l'auteur, etc. du site, et les avoir accessibles dans mes mises en page/modèles via EJS sans devoir les transmettre en tant qu'options à chaque appel de res.render. Y a-t-il un moyen de faire cela tout en me permettant de passer d'autres variables spécifiques à chaque page?

73
Cory Gross

Après avoir eu l'occasion d'étudier Express 3 API Reference un peu plus, j'ai découvert ce que je cherchais. Plus précisément, les entrées pour app.locals puis un peu plus loin res.locals _ contenait les réponses dont j'avais besoin.

J'ai découvert par moi-même que la fonction app.locals prend un objet et stocke toutes ses propriétés sous forme de variables globales étendues à l'application. Ces globales sont transmises en tant que variables locales à chaque vue. La fonction res.locals, cependant, est limité à la demande et, par conséquent, les variables locales de réponse ne sont accessibles qu’aux vues affichées au cours de cette demande/réponse particulière.

Donc, pour mon cas dans mon app.js ce que j'ai fait a été ajouté:

app.locals({
    site: {
        title: 'ExpressBootstrapEJS',
        description: 'A boilerplate for a simple web application with a Node.JS and Express backend, with an EJS template with using Twitter Bootstrap.'
    },
    author: {
        name: 'Cory Gross',
        contact: '[email protected]'
    }
});

Ensuite, toutes ces variables sont accessibles dans mes vues en tant que site.title, site.description, author.name, author.contact.

Je pourrais aussi définir des variables locales pour chaque réponse à une requête avec res.locals, ou simplement passer des variables comme le titre de la page en tant que paramètre options dans l'appel render.

EDIT: Cette méthode va pas vous permettre d’utiliser ces locales dans votre middleware. J'ai effectivement rencontré ce problème, comme le suggère Pickels dans le commentaire ci-dessous. Dans ce cas, vous devrez créer une fonction middleware en tant que telle dans sa réponse alternative (et appréciée). Votre fonction middleware devra les ajouter à res.locals pour chaque réponse, puis appelez next. Cette fonction de middleware devra être placée au-dessus de tout autre middleware devant utiliser ces locaux.

EDIT: Une autre différence entre déclarer des sections locales via app.locals et res.locals est-ce avec app.locals les variables sont définies une seule fois et persistent toute la vie de l’application. Lorsque vous définissez des sections locales avec res.locals dans votre middleware, ils sont définis chaque fois que vous recevez une demande. Vous devriez fondamentalement préférer régler les globales via app.locals sauf si la valeur dépend de la variable requête req transmise au middleware. Si la valeur ne change pas, il sera plus efficace de la définir une seule fois dans app.locals.

100
Cory Gross

Vous pouvez le faire en les ajoutant à l’objet locals dans un middleware général.

app.use(function (req, res, next) {
   res.locals = {
     siteTitle: "My Website's Title",
     pageTitle: "The Home Page",
     author: "Cory Gross",
     description: "My app's description",
   };
   next();
});

Locals est également une fonction qui étend l'objet de la section locale au lieu de l'écraser. Donc, ce qui suit fonctionne aussi bien

res.locals({
  siteTitle: "My Website's Title",
  pageTitle: "The Home Page",
  author: "Cory Gross",
  description: "My app's description",
});

Exemple complet

var app = express();

var middleware = {

    render: function (view) {
        return function (req, res, next) {
            res.render(view);
        }
    },

    globalLocals: function (req, res, next) {
        res.locals({ 
            siteTitle: "My Website's Title",
            pageTitle: "The Root Splash Page",
            author: "Cory Gross",
            description: "My app's description",
        });
        next();
    },

    index: function (req, res, next) {
        res.locals({
            indexSpecificData: someData
        });
        next();
    }

};


app.use(middleware.globalLocals);
app.get('/', middleware.index, middleware.render('home'));
app.get('/products', middleware.products, middleware.render('products'));

J'ai également ajouté un middleware de rendu générique. De cette façon, vous n'avez pas besoin d'ajouter res.render à chaque route, ce qui signifie que vous avez une meilleure réutilisation du code. Une fois que vous aurez emprunté la voie du middleware réutilisable, vous remarquerez que vous disposerez de nombreux éléments de base qui accéléreront considérablement le développement.

49
Pickels

Pour Express 4.0, j'ai constaté que l'utilisation de variables au niveau de l'application fonctionnait un peu différemment et que la réponse de Cory ne fonctionnait pas pour moi.

De la documentation: http://expressjs.com/en/api.html#app.locals

J'ai trouvé que vous pouviez déclarer une variable globale pour l'application dans

app.locals

par exemple

app.locals.baseUrl = "http://www.google.com"

Et ensuite, dans votre application, vous pouvez accéder à ces variables et dans votre middleware express, vous pouvez y accéder dans l'objet req en tant que

req.app.locals.baseUrl

par exemple.

console.log(req.app.locals.baseUrl)
//prints out http://www.google.com
16
RamRovi

Dans votre application, vous devez ajouter quelque chose comme ceci

global.myvar = 100;

Maintenant, dans tous vos fichiers que vous voulez utiliser cette variable, vous pouvez simplement y accéder en tant que myvar

11
Fernando Bustos

vous pouvez aussi utiliser "global"

Exemple:

déclarer comme ceci:

  app.use(function(req,res,next){
      global.site_url = req.headers.Host;   // hostname = 'localhost:8080'
      next();
   });

Utilisez comme ceci: dans n’importe quelle vue ou fichier ejs <% console.log (site_url); %>

dans les fichiers js console.log (site_url);

1
Shaik Matheen

Une façon de le faire en mettant à jour le app.locals variable pour cette application dans app.js

Défini via le suivi

var app = express();
app.locals.appName = "DRC on FHIR";

Avoir accès

app.listen(3000, function () {
    console.log('[' + app.locals.appName + '] => app listening on port 3001!');
});

Élaborer avec une capture d'écran de l'exemple @RamRovi avec une légère amélioration.

enter image description here

1
Gajen Sunthara

Ce que je fais pour éviter d'avoir une portée globale polluée est de créer un script que je peux inclure n'importe où.

// my-script.js
const ActionsOverTime = require('@bigteam/node-aot').ActionsOverTime;
const config = require('../../config/config').actionsOverTime;
let aotInstance;

(function () {
  if (!aotInstance) {
    console.log('Create new aot instance');
    aotInstance = ActionsOverTime.createActionOverTimeEmitter(config);
  }
})();

exports = aotInstance;

Cela ne créera qu'une seule fois une nouvelle instance et le partagera partout où le fichier est inclus. Je ne sais pas si c'est parce que la variable est mise en cache ou en raison d'un mécanisme de référence interne pour l'application (pouvant inclure la mise en cache). Tout commentaire sur la résolution du nœud serait formidable.

Peut-être aussi que vous pouvez aussi lire ceci pour avoir la bonne idée de la nécessité d’exécuter des travaux: http://fredkschott.com/post/2014/06/require-and-the-module-system/

0
dewwwald