Nodeで動作する静的サイトジェネレータ「metalsmith」を使ってみた

このエントリーをはてなブックマークに追加

現在の自分の制作の多くが、静的HTMLファイルの納品もしくはCMSに組み込むためのHTMLの納品です。静的ではありますが、共通部はincludeファイルなどで分けて納品してもOKというような状況がほとんどです。

そのため、これまでは共通部をSSIやPHPのincludeなどを使ってコーディングをしていたのですが、 jekyll や middleman などをちらほら聞くようになった2年ほど前から、静的サイトジェネレータを利用するようになりました。

今回は、最近利用してみた静的サイトジェネレータの 「metalsmith」 を利用してみたので、メモとしてエントリーしておきます。

Metalsmith

metalsmith

最初は jekyll を grunt のタスクに組み込んで使っていたのですが、ページ数が増えたりしてくると、書き出しに時間がかかるようになってきたりして、なんとか改善できないかなと考えていました。

grunt や gulp が Node で動いているので、 同じ Node で動作するものがいいなーと探してみたところ、今ってものすごくたくさんあるのですね。

Static Site Generators

で、いろいろ調べたところ、 HTML ファイルをそのままの形でも使いまわせそうなのが、 Metalsmith だってことで使ってみました。

導入

metalsmith 本体はいろいろなプラグインと合わせることで、好みの形式にできるようなので、私は jekyll 形式を利用することにしてみました。

GitHub : segmentio/metalsmith

静的ページを用意したいだけなので、以下のように最小限で。

package.json

{
  "devDependencies": {
    "metalsmith": "~1.0.1",
    "metalsmith-templates": "~0.6.0",
    "swig": "~1.4.2"
  },
  "private": true
}

上記ファイルを用意して

$ npm install

もしくは package.json に入れる用として

$ npm install --save-dev metalsmith metalsmith-templates swig

swig というテンプレートを使うことで、 jekyll ライクなテンプレート構成が出来る様子。

Swig - A Node.js and Browser JavaScript Template Engine

ファイル構成

テンプレートを利用するためのファイル構成は以下のようにしてみました。

  • _layouts
    • default.html
  • _source
    • index.html
  • metalsmith.json
  • package.json

テンプレートのファイルは _layputs のフォルダに、実際のソースは _source フォルダに。

設定ファイル:metalsmith.json

設定は metalsmith.json にまとめておくと楽のようなので以下のように用意。

metalsmith.json

{
  "source": "_source",
  "destination": "html",
  "plugins": {
    "metalsmith-templates": {
      "engine": "swig",
      "directory": "_layouts"
    }
  }
}

テンプレート:default.html

テンプレートは、ひとまずシンプルに

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>{{ title }}</title>
</head>
<body>

{{ contents | safe }}

</body>
</html>

テンプレートを利用するファイル

---
template: default.html
title: テスト
---
本文テスト

書き出し用コマンド

以下のコマンドを叩いて書き出し

$ node node_modules/.bin/metalsmith

metalsmith を -g つきのグローバルでインストールしていたら、上記のコマンドも

$ metalsmith

だけでOK。

書き出し後

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>テスト</title>
</head>
<body>

本文テスト

</body>
</html>

ひとまずこれで導入は問題なさそう

共通部( header や footer )を include する場合

include する方法がいまいちわからなかったのですが、以下のようにすることで include させることができました。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>{{ title }}</title>
</head>
<body>

{% include &apos;header.html&apos; %}

{{ contents | safe }}

{% include &apos;footer.html&apos; %}

</body>
</html>

※追記(2015/01/20 22:00)

{{ contents }} で読み込むだけでは、htmlの要素がエスケープされて出力されてしまいます。エスケープしないでHTML要素として出力するために {{ contents | safe }} とする必要があるのですが記載がぬけてしまっていたため、追記しました。