自社サイト用の静的サイトジェネレータ選定と導入の記録

最近、Jekyllをはじめとする静的サイトジェネレータ(Static Site Generator)が流行していますが、自社サイトに導入しようとすると、類似ソフトウェアの数がとても多く、選定に苦労します。いわゆる「エンジニア社長」で同じような悩みを持つ方もいると思うので、小規模な自社サイトに導入した経過を公開しておきます。
長くなるので要点をまとめると以下のようになります。

  • ジェネレータの実行環境を決める(Node.jsにした)。
  • テンプレート記述言語の好みで、テンプレートエンジンを決める(Handlebarsにした)。
  • ジェネレータを決める(Metalsmithにした)。
  • ジェネレータ導入は意外とカスタマイズが必要で時間がかかった。

自社サイトへの導入を考えた背景

更新頻度が月に1回程度の小規模な企業サイトは、アクセスを受けたときのサーバ負荷が小さく、どんなレンタルサーバにも置ける静的HTMLが向いていると考えているため、当社の自社サイトは、いわゆる静的配信です。
最初にWeb制作会社に作ってもらったHTMLを、自分で手で編集して更新しています。ヘッダやフッタなどの共通部品も、テキストエディタで全ファイル対象にまとめて置換などの原始的な手段で更新していました。しかし、メニュー項目を追加するのをきっかけに、静的サイトジェネレータを導入することにしました。
主な要件は以下の点です。

  • 共通ヘッダ・フッタ(特にナビゲーション・バー。下図赤枠部分)を自動生成できること
  • 既存のHTMLファイルを最小限の変更で取り込めること

選択肢がとても多くて一時断念

静的サイトジェネレータとして一番有名なのはJekyllだと思いますが、これはコンテンツをMarkdown書式で書くことが前提となっており、ゼロからサイトを構築する際にはいいかもしれませんが、今回のように既存コンテンツがHTMLで存在している場合には今ひとつという印象を受けました(既存コンテンツをMarkdownで書き換えるつもりはないため)。
そこで"static site generator"というキーワードで検索してみると、今度は膨大な数が出てきます。しかも、自分がやろうとしていることはHTMLプリプロセッサでも実現可能です。HTMLのコンパイルととらえることもできるので、もしかしたらGruntやGulpのようなビルドツールのプラグインでも実現できるかもしれません。
このあたりまで考えるとあまりにも選択肢が多くて、それぞれについて自分の要件を満たすかどうかを確認するのが難しくなってきたので、いっそ自分で専用のPerlスクリプトでも書こうかと思いました。しかし、それはそれで中途半端な静的サイトジェネレータに育ちそうな怖れを感じたため、やはり選定しようと思ったものの、選定の軸が定めきれず、一旦静的サイトジェネレータ導入を保留にしました。

まずジェネレータの実行環境を決める

数ヶ月ほど経過して、ふと、選定をやり直そうと思い立ち、まずは比較サイトを調べ始めました。静的サイトジェネレータの比較サイトを2つ挙げておきます。

色々見ても、肝心のナビゲーション・バーを自動生成できるかどうかは分からないので、まずはジェネレータの実行環境を何にするか決めてしまおうと考えました。
自分の場合、自社サイトのHTMLを編集する環境は、主にWindowsです。しかし、日本語の割合が少ない他のサイトでは、Ubuntuを使っていることもあります。また、ノートPCはMacOSなので、将来的にMacOSを使うこともあるかもしれません。
ジェネレータの実行環境も、これら3つのOSにあまり意識せずに対応できるものがいいと考えました。ちょっと調べてみると、Node.jsは公式サイトでこれら3つのOS用のバイナリを同時に配布しているため、ジェネレータの実行環境はNode.jsと決めました。
3つのOSに対応している環境は他にもありますが、最近見かけるツールにGruntやYeomanなどNode.js環境を使うものが多いため、一度使ってみようと思ったというのもNode.jsを選んだ理由のひとつです。

テンプレートエンジンを好みで選ぶ

次に考えたのがテンプレートエンジンです。どんなジェネレータを使うにしても、既存のHTMLファイルがある以上、その一部を変数にしたり、includeにするなど、テンプレート化する作業が発生します。その際にテンプレート記述言語を使う必要がありますが、調べてみると結構バラつきがあるので、自分の好みで選びました。
参考にしたサイトはこちらです。
http://www.bearfruit.org/2014/01/20/node-js-template-showdown-5-options-compared/
一連の記事から、各記述言語のサンプルを紹介します(サンプルコードはCC-0で公開されています)。

Jadeの例

extends layout

block content

  if data
    div.container
      h1= title
      ul
        each person in data
          li= person.name

EJSの例

<%- include head.ejs %>

  <% if(data) { %>
    <div class="container">
      <h1> <%= title %> </h1>
      <ul>
        <% data.forEach(function(person){ %>
            <li title="job: <%= person.job %> status: <%= person.status %>">
           <%= person.name %>
          </li>
        <% }); %>
      </ul>
    </div>
  <% } %>

<%- include foot.ejs %>

Handlebarsの例

{{#if data}}
    <div class="container">
      <h1> {{title}} </h1>
      <ul>
       {{#data}}
            <li title="job: {{job}} status: {{status}}">
           {{name}}
          </li>
          {{/data}}
      </ul>
    </div>
{{/if}}

Jade形式はパッと見はHTMLとまったく違ってとっつきにくいものの、Pythonっぽく閉じタグが不要なのが良さそうです。ただ、今回はもともと持っているHTMLファイルをすべてJade形式に書き換えるのがムダな作業に感じられたため、導入しませんでした。新規開発の機会があったら試したいと思っています。
EJSはHTMLに変数を埋め込むような形で、PHPに馴染んでいる自分としては親近感がわいたのですが、上記サイトの「PHPの悪いところを引き継いでしまっている」という指摘に説得力を感じたので止めました。
最終的に、比較的単純なHandlebarsを使うことにしました。

ジェネレータの必要性を再考しつつ、Metalsmithに決める

このあたりで、以下の理由で「ジェネレータなしで、テンプレートエンジンを直接使うだけで十分なのでは」と考えました。

  • やろうとしていることが共通ヘッダやフッタの差込程度で単純
  • ブログでよくある、目次やサマリ付き記事一覧(「続きを読む」リンクなど)の自動生成などは不要
  • Markdownなどの簡易書式は不要(本文はHTMLで直接書く)

いったんこの方向でHandlebarsの実行方法などを調べ始めたのですが、もともとNode.jsよりもブラウザ内での実行を前提としており、ディレクトリ構成などをゼロから考える必要があることに気付いたため、やはりジェネレータを導入することにしました。比較サイトから、今まで決めたNode.jsとHandlebarsという組み合わせのものを探し、その中から自分が考える目的に近くてシンプルなMetalsmithを導入することにしました。

Metalsmithを実際に使ってみた感想

実際にMetalsmithを使ってみると、実はテンプレートエンジンは自由に選択することができました(consolidate.jsというラッパーを使っている)。
Handlebarsのif文には条件式が書けないので(ナビゲーション・バーで当該ページのリンクだけクラスを変えるのに必要)、他のエンジンにしようかと思ったこともありますが、書式を途中で勉強し直すのが面倒で、結局独自のヘルパーを作成して解決しました。
Metalsmith自身はとても小さいツールで、ジェネレータというより「ビルドスクリプト作成用フレームワーク」という印象です。結局、ナビゲーション・バーを自動生成するためだけでも、Handlebarsの独自ヘルパーと、Metalsmithの独自プラグインを作る必要がありました。そのために、Metalsmithやプラグインのソースも多少読みました(小規模なので読むのは楽ですが)。
現在公開している自社サイト( http://www.ontarget.co.jp/ )は、Metalsmithで生成したものになっていますが、問合せページだけPHPを導入していたり、サイトマップだけindex.htmlというファイル名でないなど、小規模な割に意外と不規則な部分があって苦労しました。
ディレクトリ構成から自分で考えるよりは効率良かったと思いますし、その後のメニュー追加が楽に実施できて満足しているのですが、そもそも10ページ程度のサイトで学習コストをかけて導入する価値があるかどうかは正直なところ疑問です。
ちょっと変わったたとえですが、「ちょくちょくMakefileを直接編集してコンパイルオプションを変更していることに疑問を感じるけど、だからといってautoconfを導入するのはちょっと面倒」と似た感じを覚えました。