タイトル: テンプレートエンジン
SEOタイトル: テンプレートエンジン完全ガイド
| この記事の要点 |
|
テンプレートエンジンとは
テンプレートエンジン (Template Engine) は、HTML のひな形 (テンプレート) に動的なデータを差し込み、最終的な HTML を生成するソフトウェアです。例えば「ユーザー名」だけが違う 1000 通りのページを、1 個のテンプレートと 1000 件のデータから生成できます。
こんにちは、{{ $user->name }}さん
あなたの注文は {{ $orders->count() }} 件です。
@foreach ($orders as $order)
{{ $order->title }} - {{ $order->price }}円
@endforeach
テンプレートエンジンを使わずに「素の PHP」で書くと name; ?> のように冗長になり、XSS 脆弱性を生みやすくなります。
テンプレートエンジンの利点
- HTML エスケープの自動化:
{{ }}で出力すると自動でエスケープされ XSS を防ぐ - ロジックとビューの分離: コントローラはデータ取得、テンプレートは表示に集中
- レイアウト継承: 共通レイアウト (ヘッダ / フッタ) を 1 箇所で管理
- コンパイル キャッシュ: テンプレートを最適化された PHP/Python/Java コードに事前変換
- カスタムタグ / フィルタ: 日付フォーマット、通貨表示などを再利用可能に
- セキュリティ: 自動エスケープ + サンドボックスで安全
PHP のテンプレートエンジン
Blade (Laravel 標準)
{{-- layouts/app.blade.php --}}
@yield('title')
@yield('content')
{{-- pages/article.blade.php --}}
@extends('layouts.app')
@section('title', $article->title)
@section('content')
{{ $article->title }}
{{-- 自動エスケープ --}}
{!! $article->html_content !!} {{-- 生 HTML --}}
@if ($user)
ようこそ {{ $user->name }} さん
@else
ログイン
@endif
@foreach ($comments as $comment)
{{ $comment->body }}
@endforeach
@endsection
Twig (Symfony / 多言語)
{# layout.html.twig #}
{% block title %}{% endblock %}
{% block content %}{% endblock %}
{# article.html.twig #}
{% extends "layout.html.twig" %}
{% block title %}{{ article.title }}{% endblock %}
{% block content %}
{{ article.title }}
{{ article.body|raw }} {# 生 HTML #}
{{ now|date('Y-m-d') }} {# フィルタ #}
{% if user %}
{{ user.name }}
{% endif %}
{% for comment in comments %}
{{ comment.body }}
{% endfor %}
{% endblock %}
Smarty (老舗 PHP)
2001 年から続く老舗。EC サイト (EC-CUBE 等) で今も使われています。
Python のテンプレートエンジン
Jinja2 (Flask 標準、Ansible でも使われる)
{# base.html #}
{% block content %}{% endblock %}
{# article.html #}
{% extends "base.html" %}
{% block content %}
{{ article.title }}
{{ article.body | safe }} {# raw HTML #}
{% if user %}
{{ user.name | upper }}
{% endif %}
{% for c in comments %}
- {{ c.body }}
{% else %}
- コメント無し
{% endfor %}
{% endblock %}
Django Templates
Django 標準。Jinja2 とほぼ同じ記法 (実は Jinja2 が Django Templates にインスパイアされた)。
Java のテンプレートエンジン
Thymeleaf (Spring Boot 標準)
HTML 属性として記述するので、テンプレート単体でブラウザで開いても表示が崩れないのが特徴。
記事タイトル
詳細
FreeMarker
Apache 系。柔軟性が高く、メール本文生成などにも使われます。
Node.js のテンプレートエンジン
| エンジン | 特徴 | 例 |
|---|---|---|
| EJS | HTML に近い、PHP に似た記法 | <%= title %> |
| Pug (旧 Jade) | インデントベース、簡潔 | h1= title |
| Handlebars | ロジックレス指向、Mustache 拡張 | {{title}} |
| Mustache | 言語非依存、ロジックレス | {{title}} |
| Nunjucks | Mozilla 製、Jinja2 ライク | {{ title }} |
// EJS の例
const ejs = require('ejs');
const html = ejs.render(`
<%= article.title %>
<% if (user) { %>
<%= user.name %>
<% } %>
`, { article, user });
// Handlebars の例
const Handlebars = require('handlebars');
const template = Handlebars.compile(`
{{ article.title }}
{{#if user}}
{{ user.name }}
{{/if}}
{{#each comments}}
{{ this.body }}
{{/each}}
`);
const html2 = template({ article, user, comments });
クライアントサイド (Vue / React / Svelte)
SPA (Single Page Application) ではフロント側にもテンプレート機構があります。
{{ article.title }}
ようこそ {{ user.name }}
- {{ c.body }}
// React JSX
function Article({ article, user, comments }) {
return (
<>
{article.title}
{user && ようこそ {user.name}
}
{comments.map(c => - {c.body}
)}
>
);
}
静的サイトジェネレータ (SSG)
| ツール | 言語 | テンプレート | 用途 |
|---|---|---|---|
| Hugo | Go | Go templates | 高速ブログ、ドキュメント |
| Eleventy (11ty) | Node.js | Nunjucks/Liquid/EJS/Markdown | 軽量ブログ |
| Jekyll | Ruby | Liquid | GitHub Pages |
| Gatsby | React | JSX + GraphQL | React 派生 |
| Next.js (SSG モード) | React | JSX | React + ISR |
| Astro | 多言語 | 独自 + Vue/React/Svelte 混在 | パフォーマンス重視ブログ |
| VitePress / Docusaurus | Vue / React | 各々 | ドキュメント |
Plain PHP vs テンプレートエンジン
= htmlspecialchars($title) ?>
こんにちは = htmlspecialchars($user->name) ?>
- = htmlspecialchars($item) ?>
{{ $title }}
@if ($user)
こんにちは {{ $user->name }}
@endif
@foreach ($items as $item)
- {{ $item }}
@endforeach
コンパイル キャッシュの仕組み
多くのテンプレートエンジンは、テンプレートを1 度だけパースして最適化された PHP/Java/JS コードに変換し、ファイルとしてキャッシュします。2 度目以降はキャッシュを読むだけなので高速です。
Laravel Blade のキャッシュ場所:
storage/framework/views/*.php
Twig のキャッシュ:
var/cache/dev/twig/
Thymeleaf:
メモリ上にコンパイル済テンプレート保持
# 開発時はキャッシュ無効化、本番では有効化
# Laravel: APP_DEBUG=false で自動キャッシュ
選定ガイド
| 状況 | 推奨 |
|---|---|
| Laravel プロジェクト | Blade (標準で十分強力) |
| Symfony / 純 PHP | Twig |
| Spring Boot | Thymeleaf (公式チュートリアル基準) |
| Django | Django Templates (標準) |
| Flask | Jinja2 (標準) |
| Express.js | EJS / Pug、両方人気 |
| 静的サイト (高速重視) | Hugo |
| 静的サイト (柔軟性重視) | Astro / Eleventy |
| SPA | React JSX / Vue Template / Svelte |
FAQ
Q: テンプレートエンジンを使わず素の PHP/Node でも書けるが、なぜ使う?
A: 自動エスケープ、レイアウト継承、可読性、保守性、IDE 補完、コンパイルキャッシュ、開発者間の共通認識。長期保守を考えれば導入する価値があります。
Q: ロジックをテンプレート側に書いてもよい?
A: 表示に関する分岐 (if/for) は OK。ビジネスロジック (DB 操作、計算) はコントローラやサービス層に置くべき。「テンプレートは表示専用」を意識します。
Q: パフォーマンスはどれが速い?
A: コンパイルキャッシュが効けば差は僅かです。Hugo (Go) はビルド速度が非常に速いことで有名。サーバ側は 適切なキャッシュ設定が最重要で、エンジン選定の差は通常無視できます。