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

タイトル: テンプレートの共通化(組み込み)
SEOタイトル: EJS テンプレートの共通化 (include) 完全ガイド

この記事の要点
  • EJS で部品共通化は <%- include('partials/header') %> を使用
  • 変数を渡すには <%- include('item', { name: 'foo' }) %>
  • パスは現在のファイルから相対views/ 配下のディレクトリ構造を反映
  • <%- %>(エスケープなし)と <%= %>(エスケープあり)の使い分けに注意
  • レイアウト共通化は express-ejs-layoutslayout.ejs 自動適用

EJS の include 構文

EJS (Embedded JavaScript Templates) は、Node.js / Express で広く使われるテンプレートエンジンです。ヘッダー・フッター・サイドバーなどの共通パーツを別ファイルに切り出すには include 関数を使います。

EJS partials ディレクトリ構造

基本的な共通化

ディレクトリ構成例

views/
├── partials/
│   ├── header.ejs       # ヘッダー
│   ├── footer.ejs       # フッター
│   ├── nav.ejs          # ナビゲーション
│   └── meta.ejs         # メタタグ
├── pages/
│   ├── index.ejs
│   └── about.ejs
└── layout.ejs

views/partials/header.ejs




  
  <%= title %>
  


  

マイサイト

views/partials/footer.ejs

  
  

© 2026 My Company

views/pages/index.ejs

<%- include('../partials/header', { title: 'Top page' }) %>

Welcome

これがトップページです。

<%- include('../partials/footer') %>

<%- %><%= %> の違い

構文動作用途
<%= var %>HTML エスケープしてから出力ユーザー入力等の表示(XSS 防止)
<%- var %>エスケープなしでそのまま出力HTML 断片 / include 結果
<% code %>JS 実行のみ、出力なしif / for / 変数定義
<%# %>コメントテンプレート内コメント

include は必ず <%- %><%= %> で書くと HTML がエスケープされて <div> のように画面に出てしまいます。

include に変数を渡す


<%= name %>

価格: <%= price %>円

<% const items = [ { name: 'りんご', price: 100 }, { name: 'みかん', price: 80 } ]; %> <% items.forEach(item => { %> <%- include('partials/item', { name: item.name, price: item.price }) %> <% }); %>

親テンプレートで定義された変数は子テンプレートでもそのまま参照可能(EJS 3 系のスコープ仕様)。第 2 引数で明示的に渡すと上書きできます。

パス解決のルール

EJS 3 系で include のパスは現在のファイルからの相対パスです(EJS 2 系の views ルート相対と異なる)。

views/pages/index.ejs から
  - '../partials/header'   → views/partials/header.ejs
  - './sub'                → views/pages/sub.ejs

EJS は拡張子を自動で補完:
  - 'header' → 'header.ejs'
  - 'header.html' → そのまま 'header.html'

絶対パス (/ 始まり) は views ルート扱い
  - '/partials/header' → views/partials/header.ejs

Express でのセットアップ

// app.js
const express = require("express");
const path = require("path");

const app = express();

app.set("view engine", "ejs");
app.set("views", path.join(__dirname, "views"));

app.get("/", (req, res) => {
  res.render("pages/index", {
    title: "Top page",
    user: { name: "taro" }
  });
});

app.listen(3000);

レイアウト共通化: express-ejs-layouts

毎回 header / footer を include するのが面倒な場合は express-ejs-layouts でレイアウトを自動適用できます:

npm install express-ejs-layouts
// app.js
const expressLayouts = require("express-ejs-layouts");

app.use(expressLayouts);
app.set("layout", "layout"); // views/layout.ejs を使用
app.set("layout extractScripts", true);
app.set("layout extractStyles", true);




  <%= title %>
  <%- style %>


  <%- include('partials/nav') %>

  
<%- body %>
<%- include('partials/footer') %> <%- script %>

各ページからは render('pages/index') するだけで layout.ejs にラップされます。

他テンプレートエンジンとの比較

エンジン記法共通化特徴
EJS<% %>include素の HTML に近い、JS そのまま使える
Pug (旧 Jade)インデント記法include / extends / block記述量少、独自記法
Handlebars{{ }}partials / helperロジックレス志向
Mustache{{ }}partials最小限、複数言語対応
Nunjucks{% %}extends / block / includeJinja2 互換、強力な継承

パフォーマンス: キャッシュ

// 本番環境ではテンプレートをコンパイル結果でキャッシュ
app.set("view cache", true); // NODE_ENV=production で自動 ON

// EJS の cache オプション直接指定
const ejs = require("ejs");
ejs.cache = require("ejs").cache; // LRU

Next.js / SSR フレームワークとの関係

近年は Next.js / Nuxt / SvelteKit 等のコンポーネントベース SSR が主流で、EJS のような伝統的サーバサイドテンプレートは新規採用が減っています。ただし:

  • 管理画面 / 静的多めのサイトでは今でも EJS / Pug が現役
  • Express で軽量なアプリを作る時に最速
  • 大量のメールテンプレート、PDF 生成テンプレートでも採用例多数

FAQ

Q: include で Cannot find module
A: パスが現在ファイルからの相対です。../ が必要なケース多数。app.set('views') も再確認。

Q: 親で定義した変数が子で undefined
A: EJS 3 では基本見えますが、Express の res.locals 経由で渡すか、include の第 2 引数で明示的に渡すのが安全。

Q: ループ内 include は遅い?
A: 大量ループでは EJS 関数呼び出しコストが効きます。本番では view cache を ON にし、必要なら HTML を予めビルドしてください。