¿Cómo crear variables globales accesibles en todas las vistas usando Express / Node.JS?

Ok, entonces construí un blog usando Jekyll y puedes definir variables en un archivo _config.yml que se puede acceder en todas las plantillas / diseños. Actualmente estoy usando Node.JS / Express con EJS templates y ejs-locals (para parciales / diseños. Estoy buscando hacer algo similar a las variables globales como site.title que se encuentran en _config.yml si alguien está familiarizado con Jekyll Tengo variables como el título del sitio, (en lugar del título de la página), el nombre del autor / empresa, que permanecen igual en todas mis páginas.

Aquí hay un ejemplo de lo que estoy haciendo actualmente:

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

Me gustaría poder definir variables como el título, la descripción, el autor, etc. de mi sitio en un solo lugar y tenerlos accesibles en mis diseños / plantillas a través de EJS sin tener que pasarlos como opciones a cada llamada a res.render . ¿Hay alguna manera de hacer esto y aún así permitirme pasar otras variables específicas para cada página?

Después de tener la oportunidad de estudiar un poco más la API de Express 3 , descubrí lo que estaba buscando. Específicamente, las entradas para los app.locals y luego un poco más abajo res.locals contenían las respuestas que necesitaba.

Descubrí por mí mismo que la función app.locals toma un objeto y almacena todas sus propiedades como variables globales en el ámbito de la aplicación. Estos valores globales se pasan como variables locales a cada vista. La función res.locals , sin embargo, tiene un scope para la solicitud y, por lo tanto, las variables locales de respuesta solo son accesibles a la (s) vista (s) renderizadas durante esa solicitud / respuesta particular.

Entonces, para mi caso en mi app.js lo que hice fue agregar:

 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: 'CoryG89@gmail.com' } }); 

Entonces todas estas variables son accesibles en mis vistas como site.title , site.description , author.name , author.contact .

También podría definir variables locales para cada respuesta a una solicitud con res.locals , o simplemente pasar variables como el título de la página como el parámetro de options en la llamada de render .

EDITAR: Este método no le permitirá usar estos locales en su middleware. De hecho, me encontré con esto como Pickels sugiere en el comentario a continuación. En este caso, deberá crear una función de middleware como tal en su respuesta alternativa (y apreciada). Su función de middleware deberá agregarlos a res.locals en cada respuesta y luego llamar a next . Esta función de middleware deberá colocarse por encima de cualquier otro middleware que necesite utilizar estos locales.

EDITAR: Otra diferencia entre declarar locals vía app.locals y res.locals es que con app.locals las variables se establecen una sola vez y persisten durante la vida de la aplicación. Cuando configura locales con res.locals en su middleware, estos se configuran cada vez que recibe una solicitud. Básicamente, debería preferir establecer globales a través de app.locals menos que el valor dependa de la variable de petición de solicitud pasada al middleware. Si el valor no cambia, será más eficiente que se establezca solo una vez en app.locals .

Puede hacer esto agregándolos al objeto locals en un middleware general.

 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 es también una función que ampliará el objeto local en lugar de sobrescribirlo. Entonces, lo siguiente también funciona

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

Ejemplo completo

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

También agregué un middleware genérico de renderizado. De esta forma, no tiene que agregar res.render a cada ruta, lo que significa que tiene una mejor reutilización del código. Una vez que recorra la ruta del middleware reutilizable, notará que tendrá muchos bloques de construcción que acelerarán enormemente el desarrollo.

Para Express 4.0 descubrí que el uso de variables de nivel de aplicación funciona de manera un poco diferente y la respuesta de Cory no funcionó para mí.

De los documentos: http://expressjs.com/en/api.html#app.locals

Descubrí que puedes declarar una variable global para la aplicación en

 app.locals 

p.ej

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

Y luego en su aplicación puede acceder a estas variables y en su middleware express puede acceder a ellas en el objeto de solicitud como

 req.app.locals.baseUrl 

p.ej

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

En tu app.js necesitas agregar algo como esto

 global.myvar = 100; 

Ahora, en todos sus archivos que desee utilizar esta variable, puede acceder a ella como myvar

Una forma de hacerlo es actualizando la variable app.locals para esa aplicación en app.js

Establecer siguiendo

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

Tener acceso

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

Elaborando con una captura de pantalla del ejemplo de @RamRovi con una ligera mejora.

enter image description here

también puedes usar “global”

Ejemplo:

declara así:

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

Úselo así: en cualquier vista o archivo ejs <% console.log (site_url); %>

en archivos js console.log (site_url);

Lo que hago para evitar tener un scope global contaminado es crear un script que pueda incluir en cualquier lugar.

 // 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; 

Hacer esto solo creará una nueva instancia una vez y la compartirá en todos los lugares donde se incluye el archivo. No estoy seguro de si es porque la variable está almacenada en caché o por un mecanismo de referencia interno para la aplicación (que podría incluir el almacenamiento en caché). Cualquier comentario sobre cómo el nodo resuelve esto sería genial.

Tal vez también lea esto para obtener la esencia sobre cómo requieren los trabajos: http://fredkschott.com/post/2014/06/require-and-the-module-system/

    Intereting Posts