追記
この記事を書いてから1年以上が経っており、MiddlemanV4もまともに動くようにはなっております。本稿は「V4ダメだからV3でやろうぜ」というスタンスで記述されておりますが、今では必ずしもそうとは限りません。V3の方が全部入りで使いやすいですが、V4の方がナウいです。それを踏まえ、ご自分の状況にあったバージョンを使うようにしましょう。
本稿について
とりあえず社内の人にMiddlemanを使ってもらおうと思って適当に書き殴ってたら長くなったのでQiitaに公開したものです。
また、Grunt/gulpをDisってるけど、単に俺が嫌いなだけなので、まぁ好きな方使ってください。
前置き
ウェブページ実装の問題点
ウェブページを制作する際、多くはHTMLとCSSで記述していく。しかし、これらは強固なまでにスタティックであり、また、記述方法が冗長になっている。多くのHTMLタグには閉じタグが必要だし、CSSはHTMLの階層構造をスペース区切りでいちいち記述していかないといけない。
プリプロセッサの登場
HTMLやCSSの記述を手間に思ったウェブエンジニアたちは、少しでもこの面倒臭さを取り払おうと、特定の記法を用いて記述すると、それをHTMLやCSSに変換してくれる「プリプロセッサ」を作った。Hamlは、HTMLの階層構造をインデントで表現することで閉じタグの記述を、タグの頭に%記号を記述することで<>の記述を不要にした。Scssは、HTML上の階層構造を入れ子で表現可能にすることで、同じidを何度も記述しなくて済むようにした。また、どちらもプリプロセッサでコンパイルするメリットを活かし、変数やループなどの機能が使えるようになった。
関連リンク
- Haml http://haml.info/
- Sass: Syntactically Awesome Style Sheets http://sass-lang.com/
プリプロセッサの問題点
プリプロセッサにより、冗長なコードを書く必要はなくなった。しかし、現状、HamlはHTML用、ScssはCSS用と明確に分かれており、HTMLとCSSをセットで開発するウェブページのコーディングでは、プリプロセッサ自体を複数起動しておかなければならない。プリプロセッサにはJavaScriptに対するものもある(CoffeeScriptやTypeScriptなど)。これらを複数起動しておくということは、それだけ管理も大変になる。
タスクランナーの登場
この問題に対応するため、GruntというNode.js上で動く「タスクランナー」が生まれた。これは、1つのコマンドで、上記のようなプリプロセッサを一元管理し、意識をより一層、実装側に持っていけるというものだ。Haml等の変換処理を「タスク」という単位で管理しており、この処理をあらかじめ設定ファイルに記述しておくことで、前述のプリプロセッサを単体で走らせるよりも細かい処理が可能になっている。
そのうちに、Gruntの設定ファイルの記述法が難しいという意見が生まれ、その代わりに頭角を現してきたのがgulpだ。設定ファイルの書き方がよりJavaScriptのプログラムコードっぽくなっており、各処理がどのように行われていくのかがわかりやすくなっている。
関連リンク
- Grunt: The JavaScript Task Runner http://gruntjs.com/
- gulp.js - the streaming build system http://gulpjs.com/
Middlemanという選択肢
GruntもgulpもNode.js上で動く。そのため主にフロントエンドエンジニアにとって、非常にとっつきやすく、一気に広まった。
しかし、この2つには共通の問題点がある。それは「設定ファイルを自分でいちいち書かないと動かない」という点だ。いくらgulpの設定ファイルは書きやすくなったとはいえ、「買ってきたオモチャを使うのに、まず初期設定を、しかもイチからテキストベースで書いていかないと使えない」なんて狂気の沙汰である。
そんな中、おすすめしたいのはMiddlemanだ。MiddlemanはRuby製の「静的サイトジェネレーター」で、簡単に言ってしまうと「最低限のものは一通り入ってる、買ってきてすぐに遊べるオモチャ」である。Ruby製ということもあり、「設定より規約」の精神を受け継いでおり、実行すればすぐに使えるのだ。もちろん、あえて設定ファイルを書き込んで、自分用にカスタマイズしていくこともできる。
Middlemanは、根幹にSinatraを使っている。つまり、ものとしては「Ruby製のウェブアプリケーションフレームワーク」なのである。ウェブアプリケーションフレームワークと考えれば、コマンドを実行していくモデルのGruntやgulpとの違いがイメージしやすいのではないだろうか(結局は内部的にコマンドを実行しているようではあるが…)。それは、タスクランナーでは出せない大きなメリットが存在する。それは「ヘルパーメソッド」の存在である。特に「テンプレートヘルパー」は、partial や yield などの機能を使うことができ、テンプレートによるページ実装を容易にしている。
本稿では、この超便利なMiddlemanを使って、HamlやScssなどのコンパイルを行いつつ、テンプレート機能や自動ページ更新などの便利機能も簡単に使っていこうぜ!と、紹介するものである。
関連リンク
- Middleman: 作業を効率化するフロントエンド開発ツール https://middlemanapp.com/jp/
本題
流れ
本来なら、Middlemanの仕様を伝えたうえで、具体的な作業フローを説明すべきだと思うのだが、それはそれでわかりづらいと思うので、とりあえず一連の作業フローを先に説明する。その後で、実際に実装を行う際に知っておくべき仕様を説明していこうと思う。
バージョン
Middlemanは現在、Version 4 が開発されている。まだベータ(正確にはRC版ではあるが、まともに動かない機能が多々あるので、ベータ扱いしている)なので、このVersion 4 を使うことはおすすめしない。おとなしく、Version 3を使おう。
インストール
MiddlemanはRuby製であるため、Rubyが実行できることが大前提である。その上で、下記コマンドにてインストールしよう。Middlemanの関連ファイルはBundlerにて管理されているので、Bundlerもインストールしておく。
$ gem install bundler middleman --no-ri --no-rdoc
$ rbenv rehash # Ruby を rbenv経由でインストールしている場合
--no-ri
や--no-rdoc
については、(インストールしたgemのドキュメントなので)別に好きにすればいいけど、やたらインストールに時間がかかるようになるので、~/.gemrc
にgem: --no-ri --no-rdoc
とか書いておけばいいんじゃないかな。
プロジェクトの作成
Middlemanのインストールが終わったら、下記コマンドを叩いてプロジェクトディレクトリを作ろう。このディレクトリ内に必要なファイルがゴソッと入ってくるので、自分なりのワーキングディレクトリに移動してから作業すれば良い。
$ cd your/working/directory
$ middleman init project_name --skip-bundle
Middlemanはmiddleman init
により関連ファイルをコピーしてきた後、そのまま自動的にbundle install
を実行してくれる。便利ではあるのだが、それが終わるまで何もできなくなるので、ここでは--skip-bundle
をオプションとしてつけている。これをつけると、bundle install
を後から自分でやる必要がある。
middlmean init --skip-bundle
は、既にローカルにインストールされているデフォルトのテンプレートを、今いるディレクトリにコピーしてくるだけなので、速攻で終わる。この後に、プロジェクトディレクトリに移動して、設定ファイルを書き換え、bundle install
することになるのだが、今回はMiddlemanの標準仕様のまま使っていこうと思うので、下記のコマンドを打ってしまおう。
$ cd project_name
$ bundle install --path vendor/bundle
さぁ、これでプロジェクトの準備は完了だ。あとはHTML等を実装して、書き出すだけである。
ブラウザで確認する
実装を行う前に、Middlemanでの開発フローを確認していこう。Middlemanでは、「その根幹がSinatraである」といったように「静的ファイルを書き出すこと無く、現状をブラウザで確認できる」という特徴がある。RubyのRackサーバーが組み込まれているのだ(Grunt/gulpでも似たようなことは可能であるが、基本的には静的ファイルを書きだした後に、そのファイルを参照するModelとなっている)。Ruby on Railsなどで、publicディレクトリにファイルを置いておくとその内容が表示されるような感じである。そのRackサーバーを立ち上げるのが下記のコマンドだ。
$ bundle exec middleman server # bundle exec middleman sでもよい
しばらくするとRackサーバーの準備が整い、ブラウザからlocalhost:4567
でアクセスできるようになる。この状態で、Haml等を更新すると、自動でその更新を検知し、ブラウザがリロードされる。更新するごとに自分でブラウザのリロードボタンを押す必要はない。
静的ファイルを書き出す
仮に今、Haml / Scss等を書き換え、ページの実装が終わったとしよう。この時点では、Rackサーバー経由でページを確認しているに過ぎず、まだ静的ファイルにはなっていない。多くの場合、納品は「HTML/CSSファイル」という静的ファイルで行う必要があるので、これを書き出す必要がある。
Middlemanでは、Grunt/gulpと違い、常に静的ファイルを書き出すようにはなっていない。それが必要なときだけ、開発者がコマンドを打つことで生成されるようになっている。そのコマンドが下記だ。
$ bundle exec middleman build # bundle exec middleman b でもよい
しばらくすると、プロジェクトディレクトリの中にbuild/
というディレクトリが生成される。この中には、今作ったサイトのHTML/CSS/JS/IMG等々が一通り格納されているかたちになる。
Middleman仕様
Middlemanは「設定より規約」の原則に基いて設計されているため、自分で自由にディレクトリ構成を考えて開発する、という方法には向かない。むしろ、Middlemanが想定しているディレクトリ構成に合わせて制作を行うことで、開発以外の作業コストを下げようとしてる。
ウェブページ用のファイルは source/ の中
source/ の中には、幾つかのディレクトリと、index.html.erb
というファイルがある。ファイル名などからだいたい予想はつくと思うが、これが最終的に書きだされる静的ファイルのディレクトリ構成である。source/index.html.erb
を書き換えれば、サーバーモードではlocalhost:4567/index.html
でページが確認でき、書きだされたファイルはbuild/index.html
となる。
全ページ共通のテンプレート部分は source/layouts の中
source/index.html.erb
を開いてみよう。その中身を読むと、それがHTMLとしていろいろ不足しているのが分かる。
htmlタグはもちろん、headタグもbodyタグもない。これらは実は「全ページ共通部分」として別のファイルに記述されており、source/
直下に置かれるファイルは基本的には「それ以外の部分」のみを記述する形になる。そのコードが書かれているファイルがsource/layouts/layout.erb
だ。
source/layouts/layout.erb
を開いてみると、先ほど確認したファイルでは不足していたタグがちゃんと書かれている。<meta name='viewport' ...>
などを追記したければここに書けば良い。
bodyタグの中を見てみると、ただ1行<%= yield %>
とだけ書かれている。これは「/index.html
にアクセスしたら、source/index.html.erb
の中身をこの<%= yield %>
部分に埋め込んで返しますよ」という指示である。これをbodyタグの外に移動してページを確認してみよう。書きだされたHTMLは、bodyタグの外にdiv.welcome
が移動したと思う。
このままではHTMLとして間違っているので、ちゃんと元に戻しておくように。
ヘルパーが使える
元がウェブアプリケーションフレームワークなので、ヘルパーが使える。具体的にはerbファイルの中に<%= image_tag 'middleman.png' %>
と書けば自動的にsource/images/
の中を参照してくれて、書き出されるHTMLには<img src='/images/middelman.png'>
と記述される。
他にも便利な機能がいろいろ使えるが、ソレについては下記の関連リンクを参照されたい。
関連リンク
- Middleman: ヘルパーメソッド https://middlemanapp.com/jp/basics/helper_methods/
てかHaml使おうぜ
初期状態では、HTMLのプリプロセッサとしてerb
が使われている。これは「HTMLで変数処理を可能にしたようなもの」sであり、基本的にはHTMLと同じように書ける。しかし、HTML書きたくなくてその終としてMiddlemanを使っているのだから、erbを使う必要は全く無い。全部消そう。
Middlemanは標準でHamlが使えるようになっている。source/
の中にindex.html.haml
を新規作成し、下記のようなコードを記述してみよう。
---
title: Welcome to Middleman
---
%div.welcome
%h1
Middleman is Watching with Haml
%p.doc
= link_to "Read Online Documentation", "http://middlemanapp.com/"
そしてlocalhost:4567/index.html
にブラウザからアクセスすると、先ほどど同じ画面が表示されるはずだ(テキストに'with Haml'を追加しているので、先ほどのerbファイルを参照しているわけではないことがわかると思う)。
ちなみに最初の三行は、"Frontmatter"と呼ばれるもので、source/layouts/layout.erb
へ任意の文字列等を送ることで、本来共通部分に書かれるはずのコードを各ページから指定できるというものである。主に、titleタグの中身を指定する際に使われる。
まとめ
インストール
$ gem install bundler middleman --no-ri --no-rdoc
プロジェクト作る
$ middleman init project_name --skip-bundle
$ cd project_name
$ bundle install --path vendor/bundle
ブラウザで確認するモードとして実行する
$ bundle exec middleman s
ソース書き換える
project_name/source/
以下のファイルを書き換える。
テンプレート部分はproject_name/source/layouts/
。
実装終わったので書き出す
$ bundle exec middleman b
project_name/build/
に書き出される