6.

JavaScriptテンプレートエンジン完全比較(EJS/Handlebars/Pug/JSX/SSR)

編集
この記事の要点
  • テンプレートエンジン = HTML 等の雛形に変数や制御構文を埋め込んでレンダリングする仕組み
  • JS 主要エンジン: EJS / Handlebars / Pug / Mustache / Nunjucks / Liquid
  • モダン UI: React の JSX / Vue・Svelte のテンプレート構文もテンプレートエンジンの一種
  • シンプル用途はテンプレートリテラル `Hello ${name}` で十分(ただしエスケープ自前)
  • 選定基準: ロジック許容度 / エスケープ自動化 / SSR 対応 / コミュニティ規模 / 既存スタック互換
  • XSS 対策: HTML エスケープを自動化するエンジンが安全。生 HTML 埋め込みは要慎重
  • SSR フレームワーク(Next.js / Nuxt / SvelteKit)は内部で JSX / template compiler を持ち、ハイブリッドレンダリングを実現

テンプレートエンジンとは

テンプレートエンジンは、HTML(あるいはメール本文、JSON、ファイル名)の雛形に変数制御構文を埋め込んで、動的にレンダリングするライブラリです。サーバサイドの SSR、メール送信、コード生成、CMS、CLI スカフォルドなど用途は多岐に渡ります。

主要 JavaScript テンプレートエンジン比較

エンジン構文タイプロジックエスケープ主用途
EJS<% %> 埋め込み JSフルJS可自動 (<%= %>)Express SSR
Handlebars{{ }} ロジックレスヘルパー経由のみ自動メール / 静的サイト
Pug (旧 Jade)インデント記法制限付き自動SSR / モックアップ
Mustacheロジックレス {{ }}条件・ループのみ自動多言語移植性重視
NunjucksJinja2 風 {% %}フィルタ/マクロ自動静的サイト (11ty)
LiquidShopify 由来制限付き自動Shopify / Jekyll
JSX (React)HTML in JSフルJS自動SPA / SSR
Vue TemplateHTML + ディレクティブ制限付き表現自動SPA / SSR
SvelteHTML + JS ブロックフルJS自動SPA / SSR

EJS(最も Express 的)

<h1><%= title %></h1>
<ul>
  <% items.forEach((it) => { %>
    <li><%= it.name %></li>
  <% }) %>
</ul>

Handlebars(ロジックレス)

<h1>{{title}}</h1>
{{#if user}}
  <p>Welcome, {{user.name}}</p>
{{else}}
  <p>Please log in</p>
{{/if}}

<ul>
  {{#each items}}
    <li>{{this.name}}</li>
  {{/each}}
</ul>

{{!-- ヘルパー登録 --}}
{{formatDate created_at "YYYY-MM-DD"}}
const Handlebars = require('handlebars');
Handlebars.registerHelper('formatDate', (date, fmt) => {
  return dayjs(date).format(fmt);
});

const tmpl = Handlebars.compile(source);
const html = tmpl({ title: 'My Site', items: [...] });

Pug(インデント記法)

doctype html
html
  head
    title= title
  body
    h1 Welcome, #{user.name}
    ul
      each item in items
        li= item.name
    if user.isAdmin
      a(href="/admin") Admin Panel

Mustache(最小・移植性重視)

<h1>{{title}}</h1>
{{#user}}
  <p>Welcome, {{name}}</p>
{{/user}}
{{^user}}
  <p>Please log in</p>
{{/user}}

<ul>
  {{#items}}
    <li>{{name}}</li>
  {{/items}}
</ul>

Mustache はロジックを意図的に制限しているため、多くの言語に同名実装(Python・Ruby・PHP・Java)があるのが強み。多言語システムでテンプレート共有したいとき強力。

Nunjucks(Jinja2 風)

<h1>{{ title }}</h1>
{% if user %}
  <p>Welcome, {{ user.name | upper }}</p>
{% endif %}

{% for item in items %}
  <li>{{ loop.index }}. {{ item.name }}</li>
{% endfor %}

{% macro card(item) %}
  <div class="card"><h3>{{ item.name }}</h3></div>
{% endmacro %}
{{ card(items[0]) }}

JSX / Vue / Svelte(モダン UI フレームワーク)

// React JSX
function Page({ title, items }) {
  return (
    <main>
      <h1>{title}</h1>
      <ul>
        {items.map(it => <li key={it.id}>{it.name}</li>)}
      </ul>
    </main>
  );
}

// Vue SFC
<template>
  <main>
    <h1>{{ title }}</h1>
    <ul>
      <li v-for="it in items" :key="it.id">{{ it.name }}</li>
    </ul>
  </main>
</template>

// Svelte
<main>
  <h1>{title}</h1>
  <ul>
    {#each items as it (it.id)}
      <li>{it.name}</li>
    {/each}
  </ul>
</main>

テンプレートリテラル(標準 JS)

外部ライブラリ無しで動く最小構成。ちょっとした文字列組み立てには十分です。

const name = 'Alice';
const html = `

Hello, ${name}!

`; // タグ付きテンプレートで自動エスケープも自作可能 function html(strings, ...values) { const escape = s => String(s) .replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); return strings.reduce((acc, str, i) => { return acc + str + (i < values.length ? escape(values[i]) : ''); }, ''); } const safe = html`

${userInput}

`; // 自動エスケープ

選定の指針

要件推奨
Express で SSR、HTML をそのまま書くEJS
メール本文、テンプレートの設計者は非エンジニアHandlebars / Mustache
インデントで省タイプ、モック作成Pug
静的サイトジェネレータNunjucks (11ty) / Liquid (Jekyll)
SPA / インタラクティブ UIReact (JSX) / Vue / Svelte
SSR + SPA ハイブリッドNext.js / Nuxt / SvelteKit
ごく単純な文字列組み立てテンプレートリテラル

XSS と自動エスケープ

ユーザ入力をテンプレートに埋め込むときは自動 HTML エスケープが必須です:

入力: 

自動エスケープあり:
  <script>alert(1)</script>  ← 文字として表示(安全)

自動エスケープなし:
            ← 実行される(XSS)
  • EJS: <%= %> は自動、<%- %> は生
  • Handlebars: {{ }} は自動、{{{ }}} は生
  • JSX: 文字列は自動エスケープ、dangerouslySetInnerHTML は生
  • Vue: {{ }} は自動、v-html は生

SSR との関係

SSR(Server Side Rendering)は本質的にテンプレートレンダリングです:

  • Express + EJS / Pug = 古典的 SSR、静的 HTML を返す
  • Next.js (React SSR) = JSX をサーバで HTML 化 + クライアントで hydrate
  • Nuxt (Vue SSR) = Vue Template を同様に
  • SvelteKit = Svelte Component を同様に

FAQ

Q: テンプレートエンジンと React / Vue の違いは?
A: 用途が違います。テンプレートエンジンは静的 HTML 生成に強く、React/Vue はクライアント側の動的 UIに強い。両方を併用する構成も普通です。

Q: テンプレートエンジンは時代遅れ?
A: いいえ。メール本文 / SSR / 静的サイト / コード生成 / CMS で現役。SPA だけが全てではありません。

Q: ロジックレス(Mustache 等)と高機能(EJS 等)どちらが良い?
A: 大規模・複数人ならロジックレスがメンテしやすい。個人や小規模なら EJS の柔軟さが速い。

編集
Post Share
子ページ
  1. EJS
同階層のページ
  1. 環境構築
  2. 文法
  3. プラットフォーム
  4. ライブラリ
  5. フレームワーク
  6. テンプレートエンジン
  7. ビルトインオブジェクト
  8. エラー一覧
  9. よくある事例

最近更新/作成されたページ