aircolor memolog

Web制作・テクノロジー、たまに旅行記

Gulp.js+EJS+JSONを使った複数ページの生成方法

人気のタスクランナーツール「Gulp.js」とテンプレートエンジン「EJS」を下地に、
JSONデータから複数ページを生成できる仕組みを備忘録を兼ねて紹介します。

きっかけ

現在進めている案件で、HTMLを静的かつそこそこ大量に作る事案が発生。
しかし1ページづつ作成・修正するのはとにかくめんどくさいと思われたので、JSONで情報を一括で編集でき、生成も簡単に出来るやり方を確立したかった。

前提・やりたいこと

  • サーバはありものを使用。権限的な問題で新たにパッケージのインストールすることは不可。
  • PHPが使えないサーバだったため、複製は静的HTMLで行う必要がある。
  • 似たページを1つづつ作成、後で修正をするのはとにかくめんどくさいので、機械的に行いたい。
  • ページ複製用データは全てJSONファイルにまとめたい。

仕様

  • 書き出しツールとしてGulp.jsを使用。
  • テンプレートエンジンはEJS。採用基準はJadeやSlimと比べて学習コストが少なそうだったので。
  • gulp用のパッケージは以下が必要。
  • テンプレート用のHTMLのコーディングは先に済ませておく。その上で必要な値をJSONに設定する。
  • ページ毎に大きな違いはない。ただし、細かい違いがある場合は、値をチェックしてif文で出し分ける。
  • 管理を簡単にしたいので、テンプレートファイルは1ファイル(template.ejs)で行う。
  • 変更するたびに書き出す必要はないため、ファイルを監視するwatchタスクは使わない。

ディレクトリ構成

src
  └─ ejs(テンプレートファイル格納)
  └─ data(ページ生成用JSON格納)
app(生成ファイル用ディレクトリ)
gulpfile.js
// ※package.json,node_modulesなどのディレクトリ・ファイルは割愛

メインファイル構成

gulpfile.js

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

// ページ生成用JSONファイルの読み込み
var jsonData = require('./src/data/pages.json');  

// ページ生成用タスクを格納する配列
var taskSet= [];  

// ページ振り分け用のID
var taskNumber = 0;  

//タスクをページ毎に設定、まとめて定義
for (var key in jsonData){ 
  (function(key) {  
  gulp.task(jsonData[key].id, function(){  
    gulp.src("./src/ejs/template.ejs")  
    .pipe(ejs({  
      jsonData: jsonData,//JSONデータをテンプレートファイルに渡す
      flag:taskNumber  
    }))  
    .pipe(rename(jsonData[key].id+".html")) //出力ファイル名を指定
    .pipe(gulp.dest("./app/")); //ファイル出力先を設定  
    taskNumber++;
    });
    })(key);
  taskSet.push(jsonData[key].id)  
}

pages.json

ページ生成用の元ファイル。

{
  "pages": [
    {
      "id": "hoge1",
      "name": "ページ名",
      "content": [
        {
          "title": "ポラーノの広場1",
          "text": "あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。 "
        }
      ]
    },
    {
      "id": "hoge2",
      "name": "ページ名",
      "content": [
        {
          "title": "ポラーノの広場2",
          "text": "あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。 "
        }
      ]
    },
    {
      "id": "hoge3",
      "name": "ページ名",
      "content": [
        {
          "title": "ポラーノの広場3",
          "text": "あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。 "
        }
      ]
    }
  ]
}

template.ejs

ページのテンプレートファイル。

<% 
var pageID = flag;//pageIDを定義
-%>
  
<%= pageID %>
<!DOCTYPE HTML>
<html lang="ja">
<head>
<title><%= jsonData.pages[pageID].name %></title>
<meta charset="utf-8">
</head>
<body>
  <h1><%= jsonData.pages[pageID].name %></h1>
  <% for(var i=0; i < jsonData.pages[pageID].content.length; i++) {%>
    <div style="padding:5px 20px;">
      <h2><%= jsonData.pages[pageID].content[j].title %></h2>
      <div><%= jsonData.pages[pageID].content[i].text %></div>
    </div>
  <% } -%>
</body>
</html>

出力

セットしたタスクを実行する

$ gulp

実行すると、JSONで設定されたid名でファイルがappディレクトリ内に生成されます。
※サンプルのJSONから書きだしたファイル名は「hoge1.html」「hoge2.html」「hoge3.html」となる。

おわりに

この方法は一度確立すれば応用次第で如何様にもできそうなので、似た案件・条件があれば積極的に導入していきたいです。

また、Node.jsを本格的に使うのは今回初めてでしたが、JSONのパース方法がとにかく楽でびっくりしました。これを期にサーバへの直接導入を含めて、もう少し調べてみたい。

参考サイト

gulp+ejs:条件分岐で内容の違う2つのHTMLを生成してみる