Gulp+EJS+JSONからHTMLファイルを生成する
似たようなファイルをたくさん作る機会があったんだけど、面倒だし後から更新するのも大変。
そこで、GulpとEJSを使って、JSONファイルの設定を読み込んで、その設定の分だけHTMLファイルを生成する方法はないかと探してみたところ、やっぱりありました。
ただ個人的に、いっぱいタスク作るのってどうなんだろう...と思ったので、1個のタスクにまとめてみることに。
各ファイルの設定
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ファイルを指定できたら汎用性高まるかなと思ったんだけど、方法がわからず断念...まあ他の設定項目もどうせ案件ごとに変えるから、このままでもいいかな。