この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:3
ページ更新者:T
更新日時:2026-06-11 07:07:02

タイトル: EJS
SEOタイトル: EJS 完全ガイド — Node.js テンプレートエンジン

この本文には実行可能なタグ等が含まれるため、安全のためHTMLソースとして表示しています。本文データは変更していません。

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;background:#fffbea;border:1px solid #f4c430;margin:1em 0;width:100%"><tr><td style="background:#f4c430;color:#000;font-weight:bold;padding:8px">この記事の要点</td></tr><tr><td style="padding:10px"><ul><li><strong>EJS (Embedded JavaScript)</strong> は Node.js / Express で広く使われるテンプレートエンジン</li><li>記法はシンプル: <code><%= var %></code> エスケープ出力、<code><%- var %></code> 生 HTML 出力、<code><% if/for %></code> 制御</li><li>部分テンプレート (partial) は <code><%- include("header", { user }) %></code></li><li>Express で利用: <code>app.set("view engine", "ejs")</code> + <code>views/</code> ディレクトリに <code>.ejs</code> 配置</li><li>Handlebars / Pug / Mustache と比較すると <strong>素の JavaScript が書ける</strong>のが最大の特徴</li></ul></td></tr></table>
<h2>EJS とは</h2>

<p>EJS (Embedded JavaScript templating) は Node.js 用のテンプレートエンジンの一つです。HTML に <code><% %></code> で JavaScript を埋め込めるシンプルな構文が特徴で、PHP や ERB (Ruby) に近い感覚で書けます。</p>

<ul>
<li>軽量 (依存ライブラリほぼゼロ)</li>
<li>独自 DSL がなく <strong>素の JavaScript が書ける</strong></li>
<li>Express の標準的なテンプレートエンジンとして長年使われている</li>
<li>クライアントサイドでも動く (browserify / webpack)</li>
</ul>

<h2>インストール</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-bash">npm install ejs

# Express プロジェクトの場合
npm install express ejs</code></pre>
<h2>基本構文</h2>

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>タグ</th><th>用途</th><th>例</th></tr></thead>
<tbody>
<tr><td><code><%= var %></code></td><td>HTML エスケープ出力</td><td><code><%= user.name %></code></td></tr>
<tr><td><code><%- var %></code></td><td>生 HTML 出力 (XSS 注意)</td><td><code><%- post.bodyHtml %></code></td></tr>
<tr><td><code><% code %></code></td><td>JS 実行 (出力なし)</td><td><code><% if (user) { %></code></td></tr>
<tr><td><code><%# comment %></code></td><td>コメント</td><td><code><%# このブロックは ... %></code></td></tr>
<tr><td><code><%_ ... _%></code></td><td>前後の空白除去</td><td>整形用</td></tr>
<tr><td><code><%% / %%></code></td><td>リテラル <code><%</code> / <code>%></code></td><td>EJS 構文を文字として書きたい</td></tr>
</tbody>
</table>

<h2>サンプルテンプレート</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><!-- views/users.ejs -->
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title><%= title %></title>
</head>
<body>
  <h1><%= title %></h1>

  <% if (users.length === 0) { %>
    <p>ユーザーが登録されていません。</p>
  <% } else { %>
    <ul>
      <% users.forEach(function(user) { %>
        <li>
          <%= user.name %> (<%= user.email %>)
          <% if (user.isAdmin) { %>
            <span class="badge">管理者</span>
          <% } %>
        </li>
      <% }); %>
    </ul>
  <% } %>

  <%- include(&apos;partials/footer&apos;) %>
</body>
</html></code></pre>
<h2>Express での利用</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-javascript">// app.js
const express = require(&apos;express&apos;);
const path = require(&apos;path&apos;);
const app = express();

// テンプレートエンジン設定
app.set(&apos;view engine&apos;, &apos;ejs&apos;);
app.set(&apos;views&apos;, path.join(__dirname, &apos;views&apos;));

app.get(&apos;/users&apos;, (req, res) => {
  const users = [
    { name: &apos;田中&apos;, email: &apos;tanaka@example.com&apos;, isAdmin: true },
    { name: &apos;佐藤&apos;, email: &apos;sato@example.com&apos;, isAdmin: false },
  ];
  res.render(&apos;users&apos;, { title: &apos;ユーザー一覧&apos;, users });
});

app.listen(3000);</code></pre>
<p>これで <code>views/users.ejs</code> がレンダリングされ、HTML として返されます。</p>

<h2>部分テンプレート (Partials / Include)</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><!-- views/partials/header.ejs -->
<header>
  <nav>
    <a href="/">トップ</a>
    <% if (user) { %>
      <a href="/logout">ログアウト (<%= user.name %>)</a>
    <% } else { %>
      <a href="/login">ログイン</a>
    <% } %>
  </nav>
</header>

<!-- views/index.ejs -->
<!DOCTYPE html>
<html>
<body>
  <%- include(&apos;partials/header&apos;, { user: currentUser }) %>
  <main>...</main>
  <%- include(&apos;partials/footer&apos;) %>
</body>
</html></code></pre>
<p><strong>注意</strong>: <code>include</code> は <code><%-</code> (生 HTML 出力) を使います。<code><%=</code> だとパーシャルの HTML がエスケープされてしまいます。</p>

<h2>レイアウト (express-ejs-layouts)</h2>

<p>EJS 本体にレイアウト機能はありませんが、<code>express-ejs-layouts</code> パッケージで実現可能:</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-javascript">const expressLayouts = require(&apos;express-ejs-layouts&apos;);
app.use(expressLayouts);
app.set(&apos;layout&apos;, &apos;layouts/main&apos;); // views/layouts/main.ejs</code></pre><pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><!-- views/layouts/main.ejs -->
<!DOCTYPE html>
<html>
<head><title><%= title %></title></head>
<body>
  <%- body %>  <!-- 子ビューがここに展開される -->
</body>
</html></code></pre>
<h2>クライアントサイドでの利用</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><script src="https://cdn.jsdelivr.net/npm/ejs@3.1.10/ejs.min.js"></script>
<script>
  const template = &apos;<h1>Hello, <%= name %>!</h1>&apos;;
  const html = ejs.render(template, { name: &apos;World&apos; });
  document.body.innerHTML = html;
</script></code></pre>
<h2>他テンプレートエンジンとの比較</h2>

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>エンジン</th><th>記法</th><th>特徴</th></tr></thead>
<tbody>
<tr><td><strong>EJS</strong></td><td>HTML + <code><% %></code></td><td>素 JS が書ける。学習コスト最小</td></tr>
<tr><td>Pug (Jade)</td><td>インデント DSL</td><td>HTML タグ不要。簡潔だが独自構文</td></tr>
<tr><td>Handlebars</td><td><code>{{ var }}</code></td><td>logic-less。helper 関数で拡張</td></tr>
<tr><td>Mustache</td><td><code>{{ var }}</code></td><td>多言語対応。Handlebars の親</td></tr>
<tr><td>Nunjucks</td><td>Jinja2 風</td><td>Python 経験者になじむ</td></tr>
<tr><td>Liquid</td><td>Shopify 由来</td><td>EC サイト系で多用</td></tr>
</tbody>
</table>

<h2>セキュリティ注意点</h2>

<ul>
<li><code><%- userInput %></code> は <strong>XSS の温床</strong>。ユーザー入力は必ず <code><%= %></code></li>
<li>HTML サニタイズが必要なら <code>DOMPurify</code> や <code>sanitize-html</code> を併用</li>
<li><code>ejs.render(req.body.template, ...)</code> 等、ユーザー入力をテンプレート文字列にすると<strong>任意コード実行</strong>になる</li>
</ul>

<h2>FAQ</h2>

<p><strong>Q: <code><%= %></code> と <code><%- %></code> の使い分けは?</strong><br />
A: ユーザー入力 / DB 値は <code><%= %></code> (エスケープ)。WYSIWYG エディタで書いた既知の安全な HTML は <code><%- %></code>。</p>

<p><strong>Q: EJS は今でも現役?</strong><br />
A: Express のサンプルでは現役。ただし SSR は Next.js / Remix、SPA は React / Vue の時代なので、新規 Web アプリで EJS 一択というケースは減っています。</p>

<p><strong>Q: HTML の syntax highlight が効かない</strong><br />
A: VSCode なら <code>EJS language support</code> 拡張、または <code>files.associations</code> で <code>"*.ejs": "html"</code> を設定。</p>