読者です 読者をやめる 読者になる 読者になる

kinalog

自称フロントエンドエンジニアが何か喚いています。

Gulp+EJS+JSONからHTMLファイルを生成する

似たようなファイルをたくさん作る機会があったんだけど、面倒だし後から更新するのも大変。
そこで、GulpとEJSを使って、JSONファイルの設定を読み込んで、その設定の分だけHTMLファイルを生成する方法はないかと探してみたところ、やっぱりありました。

aircolor.hatenablog.com

ただ個人的に、いっぱいタスク作るのってどうなんだろう...と思ったので、1個のタスクにまとめてみることに。

用意するもの

gulpは入れてある前提。インストールは割愛。

下記は新しく作ります。

  • pages.json(各ページの設定用ファイル)
  • template.ejs(テンプレートEJSファイル)

各ファイルの設定

pages.json

それぞれのページの設定を記述。

{
    "pages": [
        {
            "id": "page1",
            "title": "ページ1のタイトル"
        },
        {
            "id": "page2",
            "title": "ページ2のタイトル"
        },
        {
            "id": "page3",
            "title": "ページ3のタイトル"
        },
        {
            "id": "page4",
            "title": "ページ4のタイトル"
        }
    ]
}

ここのidの項目がそのままファイル名になる。

template.ejs

生成するページのテンプレート。

<% 
var data = jsonData;
%><!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title><%= data.title %></title>
</head>
<body>
<%= data.title %>ページだよ。
</body>
</html>

最初の「var data = jsonData;」でJSONの設定を読み込んでるので、
あとはタイトルが欲しければdata.titleとか自分で設定した設定値が読み込める。

gulpfile.js

var fs = require('fs');
var gulp = require('gulp');
var ejs = require('gulp-ejs');
var rename = require('gulp-rename');

gulp.task('json-html', function() {
    var json_file = "path/to/pages.json"; // 設定用JSONファイル
    var tmp_file = "path/to/template.ejs"; // テンプレート用EJSファイル

    var json = JSON.parse(fs.readFileSync(json_file)); // JSONの読み込み
    var pages = json.pages;

    for (var i = 0; i < pages.length; i++) { // ページの数だけループ
        var id = pages[i].id;

        gulp.src(tmp_file)
            .pipe(ejs({
                jsonData: pages[i] // JSONのデータをejsに渡す
            }))
            .pipe(rename(id + ".html")) // (id).htmlにファイル名を変更
            .pipe(gulp.dest("path/to/dist")); // 指定したフォルダに出力
    }
});

nodeのファイルシステムのモジュールのfsでJSONを同期的に読み込んで処理。
JavaScriptなので、JSONのパースはJSON.parseでらくちん。

配列として扱えるので、pages.jsonで設定した数だけ勝手にループしてくれます。

こういうまとめて生成系はwatchする必要性をあまり感じないので、コマンドライン上で

$ gulp json-html

と叩いてあげれば「(id).html」っていうファイルを生成してくれる。

watchしてもうまくいくとは思うけど、他とは違って変更したファイルだけ更新ってことができないから、変更の度にコマンド叩いたほうが良いとは思う。


本当はコマンドライン引数でJSONファイルとEJSファイルを指定できたら汎用性高まるかなと思ったんだけど、方法がわからず断念...まあ他の設定項目もどうせ案件ごとに変えるから、このままでもいいかな。