Node.js | EJSテンプレートエンジン

HTMLファイルを使ってWebページを表示するなら、テンプレートエンジンを使うと便利である。ここではEJSというテンプレートエンジンの基本的な使い方を説明する。

npmでEJSをインストール

以前はHTMLファイルを読み込んで表示しようとしたが、ファイル読み込みに非同期メソッドを使う必要があり、HTML内の値もreplaceで置き換える必要があって面倒だった。もっと簡単な方法がテンプレートエンジンである。Node.jsではさまざまなテンプレートエンジンを利用でき、よく使われるものの1つがEJSである。

EJSはnpmでインストールする。

npm install ejs

npmはNode.jsを利用する場合に必須であり、必要なものの多くはnpm installでインストールできる。EJS自体はGitHubから入手することもできる。

https://github.com/visionmedia/ejs

テンプレートで使える特殊タグ

EJSでは、テンプレートとなるHTMLコードに特殊タグを使って必要な情報を埋め込める。

<%= 値 %>

値をその場所に書き出す。スクリプト側で用意した変数などを表示するために使う。HTMLタグなどはエスケープされる。

<%- 値 %>

同じく値を書き出すが、HTML関連タグはエスケープされずそのまま書き出される。

<% スクリプト %>

スクリプトを書き、レンダリング時に実行する。ブラウザに送られて実行される<script>タグとは異なり、これはサーバー側、つまりNode.js内で実行され、その結果がクライアントへ送られる。

hello.ejsをNode.jsスクリプトと同じ場所に保存する。

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <title><%=title %></title>
</head>
<body>
    <header>
        <h1 id="h1"><%=title %></h1>
    </header>
    <div role="main">
        <p><%-content %></p>
    </div>
</body>
</html>

<%=title %><%-content %>は、それぞれtitlecontentという変数を出力する。

EJSでテンプレートを表示する

テンプレートファイルを読み込みWebページを表示するには、ファイル読み込み、テンプレートのレンダリング、生成データのレスポンス書き込みが必要である。

var http = require('http');
var fs = require('fs');
var ejs = require('ejs');
 
var hello = fs.readFileSync('./hello.ejs', 'utf8');
 
var server = http.createServer();
server.on('request', doRequest);
server.listen(1234);
console.log('Server running!');
 
function doRequest(req, res) {
    var hello2 = ejs.render(hello, {
        title:"タイトルです。",
        content:"これはサンプルで作成したテンプレートです。",
    });
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.write(hello2);
    res.end();
}

EJSはrequire('ejs')でロードする。テンプレートファイルはfs.readFileSyncで読み込む。同期処理だが、サーバー作成前に読み込むため、テンプレートを最初にグローバル変数へ読み込んでおく用途に向いている。

テンプレートは次のようにレンダリングする。

ejs.render(テンプレートデータ, オプション);

第1引数はテンプレート文字列、第2引数はテンプレートへ渡す変数をまとめた連想配列である。最後にContent-Typetext/htmlに設定してレスポンスへ書き込む。

テンプレート部分の結合

テンプレートは別のテンプレートと組み合わせることもできる。たとえば、ページ全体のテンプレートを用意し、その中にコンテンツ用テンプレートを挿入する。

content1.ejsを作成する。

<p>例で作成したテンプレートです。</p>
<p>別ファイルで用意したものを読み込んで使います。</p>
<p><%= message %></p>

内側のテンプレートを先にレンダリングし、その結果を外側のテンプレートに渡す。

var hello2 = ejs.render(hello, {
    title: "タイトルです。",
    content: ejs.render(content1,{
        message:"テキストメッセージ"
    })
});

複数のテンプレートを組み合わせる場合の基本は、内側を先にレンダリングし、その結果をオプションとして外側へ渡すことである。

配列データの繰り返し出力

EJSテンプレートでは<% %>タグを使ってJavaScriptを実行できる。サーバー側で実行されるため、ブラウザに表示されるページには処理結果だけが現れる。

注意点は次のとおりである。

  1. <% %>内に書いたものは表示されない。値を出力するには<%= %>を使う。
  2. JavaScriptだが、alertdocumentのようなブラウザ依存機能は使えない。
  3. レンダリング時に渡された変数は<% %>内でそのまま使用できる。

content1.ejsを次のように変更する。

<p>例で作成したテンプレートです。</p>
<p>配列データを受け取り、リストとして表示します。</p>
<p><ol>
<% data.forEach(function(val){ %>
    <li><%= val %></li>
<% }) %>
</ol></p>

スクリプト側から配列データを渡す。

var hello2 = ejs.render(hello, {
    title: "タイトルです。",
    content: ejs.render(content1, {
        data: [
            "これは最初のデータです。",
            "次のデータです。",
            "最後のデータです。"
        ]
    })
});

処理部分は<% %>に書き、値を出力する部分は<%= %>に書く。

<% data.forEach(function(val){ %>
    <li><%= val %></li>
<% }) %>

forEachが分かりにくい場合は、通常のfor文でもよい。

<% for (var i = 0;i < data.length;i++){ %>
    <li><%= data[i] %></li>
<% } %>

<% %>を使う場合は、処理と出力をきちんと分けて考える必要がある。