gulpでテンプレートエンジン「EJS」を使って静的なwebページ生成を試してみました。

近年の制作案件の多くはWordPressを利用していたのですが、久しぶりに静的なHTMLでサイト構築する仕事に携わりました。

写真ギャラリーのwebページを40以上。WordPressならばカスタムフィールドを使うところですが、静的サイトだとスタティックサイトジェネレーターやテンプレートエンジンを利用することになります。

知ってはいたものの、使ったことが無かったので調べて試してみました。納期間近の引き継ぎ案件だったこともあり実戦投入には間に合いませんでしたが、今後使用する可能性が非常に高いので記録して紹介します。

やりたかったこと

  • ヘッダーやフッターなどをインクルード。
  • 同一のテンプレートからページを大量生成。
  • gulpのプラグインとして動作させる。
  • なるべく学習コストを低く。

上記要件に合うものとして、テンプレートエンジン「EJS」がよさそうでした。有名なjekyllMiddlemanは高性能そう且つ実績がありますが、学習/導入コストが高そう。

ひとまず上記に挙げた機能があり、できればgulpで動作するものがよかったので、サンプルコードを見たかんじ簡単そうなEJSを選びました。

gulp-ejsをインストール

npmでプラグインが配布されています。

gulp-ejs

インストールは以下のコマンド。ページ生成のためにgulp-renameというプラグインも併用します。

npm install gulp-ejs
npm install gulp-rename

JSON形式でページデータを制作する

htmlを生成する際のページの内容は、JSONで記述してテンプレートに渡します。

data.json

{
  "pages": [
    {
      "id": "page1",
      "title": "ページ1",
      "photos": [
        {"photo":"1.jpg"},
        {"photo":"2.jpg"},
        {"photo":"3.jpg"}
      ]
    },
    {
      "id": "page2",
      "title": "ページ2",
      "photos": [
        {"photo":"4.jpg"},
        {"photo":"5.jpg"},
        {"photo":"6.jpg"}
      ]
    },
    {
      "id": "page3",
      "title": "ページ3",
      "photos": [
        {"photo":"7.jpg"},
        {"photo":"8.jpg"},
        {"photo":"9.jpg"}
      ]
    }
  ]
}

gulpfile.jsにタスクを記述

gulpfile.js

var fs           = require('fs');//JSONファイルをパースするのにnode.jsのfsモジュールが必要
var gulp         = require('gulp');
var ejs          = require("gulp-ejs");
var rename       = require('gulp-rename');


//ejsのサンプル jsonからファイル生成
gulp.task('ejs', function() {

	var jsonFile = '_src/_data/pages.json',
		tempFile = '_src/_ejs/_template.ejs',
		json     = JSON.parse(fs.readFileSync(jsonFile, 'utf8')),
		pages    = json.pages,
		id;
  
	for (var i = 0; i < pages.length; i++) {
	id = pages[i].id;
	gulp.src(tempFile)
		.pipe(ejs({
			jsonData: pages[i]
		}))
		.pipe(rename(id + '.html'))
		.pipe(gulp.dest('dist'));
	}

});

JSONをパース→テンプレートに渡してhtmlを生成→ファイル名をリネーム
という流れをfor文で回してページ生成します。

テンプレートを作成

_header.ejs

<% var data = jsonData; %><!DOCTYPE html>
<html lang="ja">

<head>
	<meta charset="UTF-8">
	<title><%= data.title %> | EJS DEMO PAGE</title>
</head>
<body>

<header class="header">
	<h1><%= data.title %></h1>
</header>

一行目の<% var data = jsonData; %>で、gulpfile.jsの処理でパースしたJSONデータのオブジェクトからデータを取得できますので、<%= data.title %>のようにするとタイトルが表示できます。

_template.ejs

<% include _header %>
    <% var data = jsonData; %>
    <div class="main">
        <% data.photos.forEach(function(p){ %>
	    <div><img src="images/<%= p.photo %> alt="" /></div>
        <% }) %>
    </div>
<% include _footer %>

<% include _header %><% include _footer %>でヘッダー、フッターをインクルードしています。

そしてforEachメソッドでページデータを取り出しています。最初はfor文を使ったのですが、条件式に.lengthを使うとdefinedエラーが出て実行できませんでした。forEachを使うのが良いようです。

※_footer.ejsは割愛します。

テンプレートを作成したら、タスクを実行

以下のコマンドでタスクを実行すると、JSONで設定したidをファイル名にしたhtmlが生成されます。今回はやってませんが、watchで監視して動的に生成することも可能です。

gulp ejs

まとめ

ひとまず簡単にEJSを利用する方法をまとめてみました。まだまだ使ってない機能があると思いますが、今回試したコードだけでも実案件に貢献できそうです。

また、

<h1><%= data.title %></h1>

のような記述はなんとなくPHPと似ていて親しみやすさを感じました。反面、rubyやpythonを使う人からすると可読性がよくないと感じる方もいらっしゃるようで、その場合はインデントの記法が使えるjade(今はpugになったらしい?)が良さげ。

ページネーションやアーカイブ、RSSなどを備えたブログを生成するとなるとjelyllとプラグインを組み合わせて使う方法があるようです。

StaticGenを見てみると本当にたくさんのスタティックサイトジェネレーターがあります。実行環境や使える機能が様々異なるようで奥が深いですね。

さて、ここまで紹介してきたサンプルコードはgithubにてひとまとめに公開しています。

kouichi-hoshi/project_ejs_sample

間違いのご指摘やご意見ございましたらコメント欄等でいただけると幸いです。よろしくお願いたします!

参考サイト

この記事を執筆するにあたって以下の記事を参考にさせていただきました。ありがとうございました!

自社サイト用の静的サイトジェネレータ選定と導入の記録 - Casual Startup - MBA/プログラマの起業日記
Gulp+EJS+JSONからHTMLファイルを生成する - kinalog
テンプレートエンジン「EJS」とタスクランナー「Gulp.js」で爆速HTMLコーディング | 株式会社LIG
テンプレートエンジンEJSで使える便利な構文まとめ - Qiita
Node.jsで静的にサイトを生成する時の現時点でのおすすめ - Qiita