「Node.jsでBladeみたいにHTML書きたいんだけど」
LaravelでBlade(.blade.php)を使っていた人がNode.jsに来ると、「HTMLにサーバー側の変数を埋め込むやつ、Node.jsだと何使うの?」と迷いますよね。
答えの一つがEJS(Embedded JavaScript)です。やっていることはBladeとほぼ同じで、HTMLの中にJavaScriptを埋め込んで、サーバー側でレンダリングするテンプレートエンジンです。Bladeを知っていれば、EJSの理解は30秒で終わります。
EJSとは? ― Node.js版の「Blade」
EJS(公式サイト)は、Node.js向けのテンプレートエンジンです。HTMLファイルの中に<% %>タグでJavaScriptを埋め込み、サーバーサイドでHTMLを生成します。Expressと組み合わせて使うのが定番です。
Bladeとの対応関係はこうなります。
| 概念 | Blade(Laravel) | EJS(Node.js) |
|---|---|---|
| ファイル拡張子 | .blade.php |
.ejs |
| 変数展開 | {{ $name }} |
<%= name %> |
| エスケープなし出力 | {!! $html !!} |
<%- html %> |
| 条件分岐 | @if / @else / @endif |
<% if () { %> / <% } %> |
| ループ | @foreach / @endforeach |
<% for / forEach %> |
| パーシャル(部品読み込み) | @include('header') |
<%- include('header') %> |
| レイアウト | @extends / @section / @yield |
標準にはない(ejs-mateで対応) |
BladeとEJSの書き方比較
同じページをBladeとEJSで書いてみます。
Blade
{{-- resources/views/users.blade.php --}}
ユーザー一覧
@if(count($users) > 0)
@foreach($users as $user)
- {{ $user->name }}({{ $user->email }})
@endforeach
@else
ユーザーがいません
@endifEJS
<%# views/users.ejs %>
ユーザー一覧
<% if (users.length > 0) { %>
<% users.forEach(user => { %>
- <%= user.name %>(<%= user.email %>)
<% }) %>
<% } else { %>
ユーザーがいません
<% } %>構造はほぼ同じ。違いはBladeが@ディレクティブで書くのに対し、EJSは<% %>の中に素のJavaScriptを書くという点。Bladeの方が専用構文でスッキリしていますが、EJSは「JavaScriptがそのまま使える」ので学習コストが低いのが利点です。
Express + EJSの最小セットアップ
# プロジェクト作成
mkdir ejs-demo && cd ejs-demo
npm init -y
npm install express ejs// app.js
const express = require('express');
const app = express();
// EJSをテンプレートエンジンに設定
app.set('view engine', 'ejs');
app.set('views', './views');
app.get('/', (req, res) => {
const users = [
{ name: '田中太郎', email: 'tanaka@example.com' },
{ name: '佐藤花子', email: 'sato@example.com' },
];
// Bladeの return view('users', compact('users')) に相当
res.render('users', { users });
});
app.listen(3000, () => console.log('http://localhost:3000'));# 起動
node app.jshttp://localhost:3000にアクセスすると、先ほどのviews/users.ejsがレンダリングされて表示されます。LaravelのRoute::get→view()の流れとほぼ同じ感覚です。
基本構文まとめ
| タグ | 用途 | 例 |
|---|---|---|
<%= %> |
変数展開(HTMLエスケープあり) | <%= user.name %> |
<%- %> |
変数展開(エスケープなし、HTML出力) | <%- htmlContent %> |
<% %> |
JS実行(出力なし、制御構文用) | <% if (flag) { %> |
<%# %> |
コメント(出力されない) | <%# これはコメント %> |
<%- include() %> |
パーシャル読み込み | <%- include('header') %> |
覚えるのは=(エスケープ出力)、-(生出力)、何もなし(実行のみ)の3パターンだけ。Bladeの{{ }}と{!! !!}の使い分けと同じ考え方です。
今からEJSを選ぶべきか?
正直に言うと、2026年にEJSを新規プロジェクトで採用するケースは減っています。ReactやNext.jsのようなコンポーネントベースのフレームワークが主流になり、サーバーサイドレンダリングもNext.jsのApp Routerで実現できるようになったからです。
ただし、以下の場面では今でもEJSが有効です。
- メール本文のHTMLテンプレート:Reactを入れるほどではない、シンプルなHTML生成
- 管理画面や社内ツール:SPAにする必要がない軽量なページ
- 既存のExpressプロジェクト:すでにEJSで動いているものを無理に移行する必要はない
- 学習用:テンプレートエンジンの概念を理解するのにEJSはシンプルで最適
テンプレートエンジンの理解を深める関連記事
- コマンドラインの基本と活用方法【初心者エンジニア向け】 – ExpressアプリのセットアップやNode.js実行に必要なCLI操作
- Claude Codeとは?AI搭載のコーディングアシスタントを徹底解説 – EJSテンプレートの生成やBladeからの変換をAIに任せる活用法
- 「全部POSTでよくない?」がモヤる人へ|HTTPメソッド使い分けの正論と現場のリアル – Expressのルーティング設計とテンプレートレンダリングの関係
- リリース前に必ず確認!バイブコーディング&非エンジニア向けWebアプリ安全チェックリスト – EJSの
<%- %>(エスケープなし出力)によるXSSリスクの確認に
まとめ:EJSは「Node.js版のBlade」
- EJSとは、HTMLにJavaScriptを埋め込んでサーバーサイドでレンダリングするNode.js向けテンプレートエンジン
- Bladeとの対応:
{{ }}→<%= %>、@if→<% if %>、@include→<%- include() %> - Express + EJSのセットアップは数行。
app.set('view engine', 'ejs')で完了 - 新規プロジェクトではReact/Next.jsが主流だが、メールテンプレートや軽量な社内ツールでは今も有効
Bladeを使ったことがある人なら、EJSは「構文が違うだけで同じことをやっている」と気づくはず。テンプレートエンジンの考え方自体は言語を超えて共通なので、一つ理解すれば他のエンジン(Pug、Handlebars、Twigなど)もすぐに読めるようになります。
