それでは、 Jekyll を使用してブログを作成しました。すべてのテンプレート/レイアウトでアクセス可能なファイル_config.yml
で変数を定義できます。現在、 Node.JS / ExpressEJS テンプレートと ejs-locals (パーシャル/レイアウト。Jekyllに慣れている人なら、site.title
にある_config.yml
のようなグローバル変数に似たものを探しています。サイトタイトル(ページタイトルではなく)などの変数があります。著者/会社名。すべてのページで同じです。
以下は、私が現在行っていることの例です。
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
});
};
サイトのタイトル、説明、著者などの変数を1か所で定義し、res.render
への各呼び出しのオプションとして渡すことなく、レイアウト/テンプレートでEJSを介してアクセスできるようにしたいと思います。これを行う方法はありますが、それでも各ページに固有の他の変数を渡すことができますか?
Express 3 APIリファレンス を勉強する機会を得た後、私は探しているものを発見しました。具体的には、 app.locals
のエントリと、さらに少し下の res.locals
必要な答えを保持しました。
関数app.locals
がオブジェクトを受け取り、そのすべてのプロパティをアプリケーションにスコープされたグローバル変数として保存することを自分で発見しました。これらのグローバルは、ローカル変数として各ビューに渡されます。ただし、関数res.locals
はスコープが要求に限定されているため、応答ローカル変数は、その特定の要求/応答中にレンダリングされたビューにのみアクセスできます。
したがって、私の場合はapp.js
で追加したことは次のとおりです。
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]'
}
});
その後、これらの変数はすべて、site.title
、site.description
、author.name
、author.contact
としてビューでアクセスできます。
また、res.locals
を使用してリクエストへの応答ごとにローカル変数を定義することも、ページのタイトルなどの変数をoptions
呼び出しのrender
parameterとして渡すこともできます。
EDIT:このメソッドは、notこれらのローカルをミドルウェアで使用できるようにします。 Pickelsが以下のコメントで示唆しているように、実際にこれに遭遇しました。この場合、あなたは彼の代わりの(そして高く評価された)回答でミドルウェア関数を作成する必要があります。ミドルウェア関数は、応答ごとにそれらをres.locals
に追加し、next
を呼び出す必要があります。このミドルウェア機能は、これらのローカルを使用する必要がある他のミドルウェアの上に配置する必要があります。
EDIT:app.locals
とres.locals
を介してローカルを宣言することのもう1つの違いは、app.locals
を使用すると、変数が1回設定され、アプリケーションの存続期間中持続することです。ミドルウェアでres.locals
を使用してローカルを設定すると、これらはリクエストを取得するたびに設定されます。値がミドルウェアに渡されるリクエストreq
変数に依存しない限り、基本的にapp.locals
を介してグローバルを設定することを好むはずです。値が変わらない場合は、app.locals
で一度だけ設定する方が効率的です。
これを行うには、一般的なミドルウェアのローカルオブジェクトにそれらを追加します。
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は、localsオブジェクトを上書きするのではなく拡張する関数でもあります。したがって、次のようにも動作します
res.locals({
siteTitle: "My Website's Title",
pageTitle: "The Home Page",
author: "Cory Gross",
description: "My app's description",
});
完全な例
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'));
また、汎用レンダーミドルウェアも追加しました。この方法では、res.renderを各ルートに追加する必要がないため、コードの再利用が向上します。再利用可能なミドルウェアのルートをたどると、開発を大幅にスピードアップする多くのビルディングブロックがあることに気付くでしょう。
Express 4.0の場合、アプリケーションレベルの変数を使用すると動作が少し異なり、Coryの答えは機能しませんでした。
ドキュメントから: http://expressjs.com/en/api.html#app.locals
アプリのグローバル変数を宣言できることがわかりました
app.locals
例えば
app.locals.baseUrl = "http://www.google.com"
そして、アプリケーションでこれらの変数にアクセスできます。エクスプレスミドルウェアでは、reqオブジェクトで次のようにアクセスできます。
req.app.locals.baseUrl
例えば.
console.log(req.app.locals.baseUrl)
//prints out http://www.google.com
App.jsに次のようなものを追加する必要があります
global.myvar = 100;
これで、この変数を使用するすべてのファイルで、myvar
としてアクセスできます。
「グローバル」を使用することもできます
例:
このように宣言します:
app.use(function(req,res,next){
global.site_url = req.headers.Host; // hostname = 'localhost:8080'
next();
});
次のように使用します。任意のビューまたはejsファイルで<%console.log(site_url); %>
jsファイルにconsole.log(site_url);
汚染されたグローバルスコープを持たないようにするために、どこにでも含めることができるスクリプトを作成します。
// 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;
これを行うと、新しいインスタンスが一度だけ作成され、ファイルが含まれるすべての場所で共有されます。変数がキャッシュされているのか、アプリケーションの内部参照メカニズム(キャッシュを含む可能性がある)が原因であるのかはわかりません。ノードがこれを解決する方法に関するコメントは素晴らしいでしょう。
たぶん、これを読んでrequireがどのように機能するかについての要点を入手してください: http://fredkschott.com/post/2014/06/require-and-the-module-system/