53
65

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

EJS+gulpで静的サイトのHTML生成

Posted at

静的なHTMLをそこそこ制作する案件があったので
EJSを試しに使ってみました。
複数ページの情報をJSONで管理し、
テンプレートエンジン“EJS”でHTMLを書き出してみます。

こちらのページを参考にさせていただきました。
Gulp+EJS+JSONからHTMLファイルを生成する

▼環境

 "node"   : "v4.1.1",
 "npm"    : "2.14.4",

##カンタンなEJS機能紹介

▼インクルード

<% include hoge %>

hogeファイルをインクルードで読み込む。

▼<% %>内でJavaScriptを記述できます。(公式より)

<% if (user) { %>
  <h2><%= user.name %></h2>
<% } %>

こちらの記事も参考になりました。

##準備編

npmでgulp-ejsをインストールします。

npm install --save-dev gulp-ejs

cf.EJS,npm gulp-ejs

gulpの設定はこちらです。
補足ですがconfigファイルでpathの情報などは別ファイルで保存しています。

後述のtemplate.ejsに
pages.jsonのデータを流しこんでいきます。
"pages"の数だけHTMLを生成する設定です。

gulp/ejs.js
'use strict';
const gulp     = require( 'gulp' );
const fs       = require( 'fs' );
const plumber  = require( 'gulp-plumber' );
const rename   = require( 'gulp-rename' );
const ejs      = require( 'gulp-ejs' );
const config   = require( '../config' );
const jsonData = 'path/to/pages.json';
const template = 'path/to//template.ejs';
const json     = JSON.parse(fs.readFileSync( jsonData ));
const pages    = json.pages;

gulp.task( 'ejs', () => {

  for (let i = 0; i < pages.length; i++) {
    const id = pages[i].id;

    gulp.src( template )
      .pipe( plumber() )
      .pipe(ejs({
          jsonData: pages[i]
      }))
      .pipe( rename(id + ".html") )
      .pipe(gulp.dest( config.ejs.dest ));
  }
});

##テンプレート編

template.ejs
<!DOCTYPE html>
<html lang="ja">
<% include common/_head %>
<body>
  <section id="all">
    <% include common/_header %>
    <% include common/_contents %>
  </section>
  <script src="script.js"></script>
</body>
</html>

template.ejsと同階層にcommonフォルダを設置し、
includeファイルを置いています。

どうもWordPressのテンプレートのような形式
(ex. header.phpに分けた時にタグが途中できれる)
がしっくりこないので、ブロックごとにincludeしていきました。

▼データ元となるpages.jsonはこちらです(html:1ファイル分)

pages.json
{
  "pages": [
    {
      "id": "page000",
      "title": "タイトル",
      "contents": [
        {
          "id": "child000",
          "h2": "タイトルその1",
          "tag": [
            "タグ1",
            "タグ2",
            "タグ3",
            "タグ4"
          ],
          "summary": "サマリーサマリーサマリーサマリーサマリーサマリー",
          "reference": {
            "text": "リファレンス",
            "url" : "http://qiita.com/"
          },
          "exercises": "テキスト"
        },
        {
          "id": "child001",
          "h2": "タイトルその2",
          "tag": [
            "タグ1",
            "タグ2",
            "タグ3",
            "タグ4"
          ],
          "summary": "サマリーサマリーサマリーサマリーサマリーサマリー",
          "reference": {
            "text": "リファレンス",
            "url" : "http://qiita.com/"
          },
          "exercises": "テキスト"
        }
      ]
    }
  ]
}

▼各includeファイルはこんな感じです。

_head.ejs
<% var data = jsonData; %>
<head>
<meta charset="UTF-8">
<meta name="description" content="">
<meta name="keywords" content="">
<title><%= data.title %></title>
<link rel="stylesheet" href="files/css/style.css">
</head>

↑gulp/ejs.jsでtemplate.ejsに渡した
jsonのvalueをtitleタグに設定しています。

_header.ejs
<%
var data  = jsonData;
var Class = '';
%>
<header id="header">
  <nav class="wrap">
    <ul id="navi">
	  <% ( data.id == "page000" ) ? Class = 'current' : Class = '' -%>
      <li>
        <a href="page000.html" class="<%= Class -%>" >menu000</a>
      </li>
      <% ( data.id == "page001" ) ? Class = 'current' : Class = '' -%>
      <li>
        <a href="page001.html" class="<%= Class -%>" >menu001</a>
      </li>
      <% ( data.id == "page002" ) ? Class = 'current' : Class = '' -%>
      <li>
        <a href="page002" class="<%= Class -%>" >menu002</a>
      <li>
    </ul>
  </nav>
</header>

_header.ejsでは

_header.ejs
<% ( data.id == "index000" ) ? Class = 'current' : Class = '' -%>

HTMLのファイル名と"id"が同じ時に
currentクラスを付加しています。

_contents.ejs
<% var data = jsonData; %>
<section id="main">
  <div class="wrap">
    <h1><%= data.title %></h1>
  
  //▼contentsをループで生成
  <% for( var i = 0; i < data.contents.length; i++ ) { -%>
    <section id="<%= data.contents[i].id %>" class="content">
      <h2><%= data.contents[i].h2 %></h2>
      <div class="content-ttl">
        <ul class="tag">
        
        //▼tagリストをループ生成
    	<% for( var j = 0; j < data.contents[i].tag.length; j++ ) { -%>
    	  <li><%= data.contents[i].tag[j] %></li>
    	<% } %>
    	
        </ul>
      </div>
      <div class="content-box">
        <p class="summary"><%= data.contents[i].summary %></p>
        <p class="reference">
          <a href="<%= data.contents[i].reference.url -%>">
          	<%= data.contents[i].reference.text %>
          </a>
        </p>
      </div>
      <div class="btn"><a href="#"><%= data.contents[i].exercises %></a></div>
    </section>
  <% } %>
  </div>
</section>

以上で準備が整いましたので
gulpでbuildしてみましょう!

console.log
gulp ejs

こちらのようなHTMLが生成されるとおもいます。

page000.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="description" content="">
<meta name="keywords" content="">
<meta name="viewport" content="width=device-width">
<title>タイトル</title>
<link rel="stylesheet" href="files/css/style.css">
</head>
<body>
  <section id="all">
    <header id="header">
      <nav class="wrap">
        <ul id="navi">
          <li>
            <a href="page000.html" class="current" >menu000</a>
          </li>
          <li>
            <a href="page001.html" class="" >menu001</a>
          </li>
          <li>
            <a href="page002" class="" >menu002</a>
          <li>
        </ul>
      </nav>
    </header>    
    <section id="main">
      <div class="wrap">
        <h1>タイトル</h1>
        <section id="child000" class="content">
          <h2>タイトルその1</h2>
          <div class="content-ttl">
            <ul class="tag">
              <li>タグ1</li>
              <li>タグ2</li>
              <li>タグ3</li>
              <li>タグ4</li>
            </ul>
          </div>
          <div class="content-box">
            <p class="summary">サマリーサマリーサマリーサマリーサマリーサマリー</p>
            <p class="reference">
              <a href="http://qiita.com/">リファレンス</a>
            </p>
          </div>
          <div class="btn"><a href="#">テキスト</a></div>
        </section>
        <section id="child001" class="content">
          <h2>タイトルその2</h2>
          <div class="content-ttl">
            <ul class="tag">
              <li>タグ1</li>
              <li>タグ2</li>
              <li>タグ3</li>
              <li>タグ4</li>
            </ul>
          </div>
          <div class="content-box">
            <p class="summary">サマリーサマリーサマリーサマリーサマリーサマリー</p>
            <p class="reference">
              <a href="http://qiita.com/">リファレンス</a>
            </p>
          </div>
          <div class="btn"><a href="#">テキスト</a></div>
        </section>
      </div>
    </section>
  </section>
  <script src="script.js"></script>
</body>
</html>

※現状ですとincludeした箇所のインデントが少しずれてしまうので調整が必要です。
(掲載HTMLコードは多少整えてあります)


また、include接頭辞にアンダーバーを付けているのは
LIGさんの記事に倣っているためです。

ただejs.jsの記述の通り
pages.jsonに記載されているページのみ生成されますので
本コードには必須ではありません。

##まとめ
一度に複数のHTMLを生成できるのは
効率的で気持ちいいですね!

実際の運用にはまだ最適化が必要そうですが
静的サイトのテンプレート展開などに使えるのではないでしょうか。

##参考リンク
Gulp+EJS+JSONからHTMLファイルを生成する
EJSの使い方を訳してみた(中途半端でごめんなさい)
テンプレートエンジン「EJS」とタスクランナー「Gulp.js」で爆速HTMLコーディング

53
65
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
53
65

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?