ちょっと話題の記事

[ Middleman で超速プロトタイピング ] #00 Haml 再入門

2013.07.16

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Web アプリケーション開発の初期段階においては、そのアプリのモックアップをよく作ったりします。いわゆるプロトタイピングというヤツですね。本実装となるともちろんサーバーサイドは Java や PHP などで実装し、それに伴ってフロントエンドもそれらのプログラミング言語によるテンプレートエンジンをベースに HTML で作り上げる訳です。しかしプロトタイピングの段階ではそういったプログラミング言語に頼ることなく、HTML だけで一通りの静的な Web ページを作ることになります。

実はこのモックアップ作成という名のプロトタイピング、HTML だけで作るという理由からかなりの重労働だったりします。画面数の少ない小規模な Web アプリケーションであればどうってことないですが、業務系の Web アプリケーションとなると10画面、20画面は当たり前。時には40画面以上にも及ぶことも少なくありません。流石にそこまでの規模となると全ての画面を静的な HTML だけで作るというのに無理が生じてきます。膨大な工数が発生してプロジェクトのスケジュールを圧迫しかねません。早く家に帰るにはどうにかしてこのプロトタイピングを効率化させる必要がある訳です。

Middleman を使って超速プロトタイピング

Middleman logo

以前、弊社の清田が当ブログにて Middleman という静的サイトジェネレータを紹介していました。その後しばらくして僕が実際の受託案件に取り入れてみた訳ですが、色々と使い込んでいくうちにすっかりその利便性に魅了されましたので、あらためてその機能やノウハウを紹介していきます。

このシリーズを読むのにふさわしい方は?

以下の質問のどれか一つにでも当てはまる方

  • HTML コーダーだけど、タスクが多すぎて大変!早く仕事を片付けて帰りたい
  • Web デザイナーだけど、HTML も CSS も多少は書けるし、もっと手軽に静的な Web サイトを作り上げられるようになりたい
  • フロントエンドエンジニアだけど、プロトタイピング超大変!五月雨式に降ってくる修正要求にも素早く対応出来るようになって早く帰りたい
  • とにかく早く仕事を終わらせて帰りたい

このシリーズで学習する上で必要な事前知識

  • HTML と CSS の読み書きが普通に出来る必要があります。※JavaScript に関してはこのシリーズでは特に触れる予定はありません
  • 後述しますが Middleman、Haml 共に Ruby がベースとなっているため、最低でも Hello, World が出せる程度の基礎知識があると習得がスムーズになります。
  • Ruby が絡んでくる以上、コマンドプロンプトやターミナルといった所謂 黒い画面 をどうしても使う場面が出てきます。ディレクトリ移動や作成といった基本操作だけでも習得しておいてください。

以上がこのシリーズにおける前書きになります。ではいきなり Middleman の習得に入る前に、そこでメインに使用する Haml という言語について学んでいくとします。

2013年7月現在、真に遺憾ながら Middleman は Windows7 上で動作しません。詳しい説明は省略しますが、Middleman の動作に必要な wdmという gem をインストールすることがどうしても出来ず、僕の知識では Windows 上に Middleman の動作環境を作ることができませんでした。従って Windows ユーザーの方は、VMwareVirtualBox といったツールで Linux の仮想環境を構築し、そこに Middleman をインストールすることになります。

僕は自宅では Mac を使用していますが、会社では Windows マシンしか支給されていないので、VirtualBox に Ubuntu Server を立てて利用しています。

Haml 再入門 - ていうか Haml ってなに?

Haml logo

いわゆる HTML に対する拡張メタ言語という位置づけの言語です。HTML によって記述されたソースコードと同じ意味(機能)を持ちながら、より簡略化された表現で記述できるようにしたものという訳です。Haml のソースコードをコンパイラに通すことで HTML ファイルを生成することができます。

こういった拡張メタ言語は他にもいろいろありますが、代表的なところだと以下のようなものが挙げられます。

拡張メタ言語 コンパイル後
Haml HTML
Slim
SCSS(Sass) CSS
Less
CoffeeScript JavaScript
TypeScript
Hexe

Haml のコンパイラは Ruby で実装されており、主に Ruby on Rails の開発者の間では当たり前のように利用されています。SCSS(Sass) や CoffeeScript もコンパイラが Ruby で実装されており、こちら2つの言語に関しては Rails に標準で実装されています。

Middleman では主にこれら Haml、SCSS(Sass)、CoffeeScript を駆使して静的な Web サイトを作っていきます。超速でプロトタイピングするためにもいきなり Middleman に手を出す前に Haml の基本的な作法から学んでいくとしましょう。

Haml と HTML - その書き方

HTML の書き方を簡略化したモノが Haml です。とはいえ HTML がタグベースの記法という性質からか、SCSS(Sass) や LESS に見られるようなそれとは違い随分と大胆な簡略化がなされています。

Haml

!!!
%html
	%head
		%title hello, Haml
	%body
		%h1 hello, Haml!
		%p Lorem ipsum dolor sit amet
		%ul#myList
			- 3.times do |i|
				%li= "item_#{i}"

HTML

<!DOCTYPE html>
<html>
	<head>
		<title>Hello, Haml</title>
	</head>
	<body>
		<h1>Hello, Haml!</h1>
		<p>Lorem ipsum dolor sit amet</p>
		<ul id="myList">
			<li>item_0</li>
			<li>item_1</li>
			<li>item_2</li>
		</ul>
	</body>
</html>

初見だと何が何だかサッパリかも知れません。下の HTML を Haml で表現するとここまで簡略化されるわけです。はじめのうちは中々この凄さが判らないかもしれませんが、一度慣れてしまうと実に見通しの良いコードに思えてきます。

百聞は一見にしかずです。とにかく実際にコードを書いてそれがどんな HTML に変換されるのか試してみましょう。

Haml 導入手順

なにはともあれ Ruby がインストールされていなと事が始まりません。

1| Ruby のインストール

インストールする手段はいくつかありますが、当ブログの過去の記事から判りやすくまとまっているものをピックアップしたので、そちらをご参照ください。

手っ取り早く済ませたい方はこちら

本格志向の方はこちら

これで Ruby がインストールされたことでしょう。きちんとインストール出来たかどうかを確認するには、ターミナル(コマンドプロンプト)上で以下のコマンドを入力して Enter キーを押します(※ディレクトリはどこでも構いません)

% ruby -v

下記のようにインストールされた Ruby のバージョンが表示されれば成功です。

ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-darwin12.3.0]

上記に挙げたリンク先ではどちらも 1.9.x をインストールしていますが、2013年7月現在の Ruby の最新バージョンは 2.0.0-p195 となっています。Mac 環境ではどちらでも問題ないのを確認済みです。

2 | Haml をインストール

無事に Ruby がインストール出来たところで、いよいよ Haml をインストールします。Haml は Ruby のブラグインに相当するわけですが、Ruby の世界ではそういったプラグインやフレームワークをひっくるめて gem と呼んでいます。この Haml もまた数ある gem の一つです。ということでインストール方法も gem のインストール方法に倣って行います。

手っ取り早く済ませたい方はこちら

ターミナル(コマンドプロンプト)を立ち上げます。起動したらすかさず以下のコマンドを入力して Enter キーを押します。

% gem install haml

ズラズラズラーっと文字が出てきますが、これだけでインストールは完了です。無事にインストール出来たかどうかを確認するには、その場で以下のコマンドを入力して Enter キーを押します。

% haml -v

下記のようにバージョンが表示されればインストール成功。

Haml 4.0.3

2013年7月現在の最新バージョンは 4.0.3 です。

あとは Haml をバリバリ書きまくるだけですが、ひとまず作業ディレクトリを用意しておきましょう。場所はどこでも良いのでtry_hamlというディレクトリを作っておきます。

本格志向の方はこちら

上記のお手軽インストールは gem をグローバルレベルでインストールする方法ですが、開発環境(※ディレクトリ)単位でインストールしたいという方はこちらの手順でインストールすることになります。

1) bundler をインストール

gem を何でもかんでもグローバルレベルに突っ込まずに、開発環境ごとに管理出来るようにするための Ruby のプラグインです(※bundler自身もgemです)。bundler のインストール手順については以下の記事に詳しく書かれているので、ここでは割愛します。

2) bundler を使って Haml をインストール

いきなりインストールコマンドを実行せずに、まずは開発環境となる作業ディレクトリに移動します。

% mkdir try_haml
% cd try_haml

次に以下のコマンドを実行して作業ディレクトリを初期化します。

$ bundle init
Writing new Gemfile to /path/to/project/Gemfile

すると Gemfile というテキストファイルが生成されます。これをテキストエディタで開くとなんだか色々と書かれていますが、今回は Haml だけ使えれば良いので、これらをまるごと消して以下のソースコードだけを書きます。

source "https://rubygems.org"
 
gem "haml"

保存したら以下のコマンドを入力して Enter キーを押します。

$ bundle install --path vendor/bundle

ずらずらずらーっと文字が出てきますが、これで Haml が作業ディレクトリに対してインストールされました。これですべての前準備は完了となります。

はじめての Haml

では実際に Haml を書いて HTML ファイルを書きだしてみます。先ほど作ったtry_hamlディレクトリ内にindex.hamlというファイルを新規に作成します。作成出来たらテキストエディタで以下のコードを入力します。

!!!
%html
	%head
		%title hello, Haml
	%body
		%h1 hello, Haml!
		%p Lorem ipsum dolor sit amet
		%ul#myList
			- 3.times do |i|
				%li= "item_#{i}"

入力できたら保存し、コマンドを実行して HTML ファイルを書きだしてみます。ターミナル(コマンドプロンプト)を開き、try_hamlディレクトリに移動します。

$ cd try_haml

移動したら以下のコマンドを入力して Enter キーを押します。

haml index.haml index.html

bundler を使って haml をインストールした場合は、以下のコマンドを入力します。

bundle exec haml index.haml index.html

特に何かメッセージが返ってくることはありませんが、問題なくコンパイルされtry_hamlディレクトリに HTML が書きだされました。

ではこれより Haml の記法について一つずつ解説していきます。

% 記号の後ろにタグ名を書くとタグが生成される

Haml

%h1
%div
%p
%img

HTML

<h1></h1>
<div></div>
<p></p>
<img />

%記号の後ろにタグ名を書くと、その要素の HTML タグが生成されます。Haml では終了タグといったものを明示的に記述することはなく、HTML 生成時にそれぞれ必要に応じて補完されます。

要素内のテキストはタグ名の後ろに半角スペース空けて記述する

Haml

%h1 Hello, Haml!
%div hogehoge
%p Lorem ipsum

HTML

<h1>Hello, Haml!</h1>
<div>hogehoe</div>
<p>Lorem ipsum</p>

イメージとして、要素を宣言してその引数として入れ子にしたいテキストを渡すといった感じです。入れ子というキーワードが出て来ましたが、要素を入れ子構造にするやり方は次に紹介します。

要素の入れ子は改行してインデントをつける

Haml

%header
	%h1 Hello, Haml!
%div
	%p Lorem ipsum
	%img

HTML

<header>
	<h1>Hello, Haml!</h1>
</header>
<div>
	<p>Lorem ipsum</p>
	<img />
</div>

明示的な閉じタグが存在しない Haml において改行とインデントは非常に重要な意味を持っています。親要素から改行してインデントを一つ付けられた要素は、入れ子された状態で HTML に書き出されます。

ここで気をつけなくてはならないのは、インデントのサイズと数です。インデントは Tab でも半角スペースでも問題ありませんが、それらを混在させることはできません。Haml コンパイラはソースコードを上から順にチェックして、一番最初にあるインデントを基準とみなします。基準と異なるサイズのインデントを見つけるとコンパイルエラーが発生します。また、入れ子が一段階の場合はインデントの数もひとつにしなくてはなりません。誤ってインデントを2つ続けて入力してしまうとコンパイルエラーが発生します。

NG

-# インデントサイズは半角スペース4つ
%header
    %h1 Hello, Haml!
%div
        %p Lorem ipsum
      %img

入れ子になった要素の改行を制御する

以下の様な Haml コードがあるとします。

Haml

%p
	Hello,
	%strong Haml!

HTML

<p>
	Hello,
	<strong>Haml!</strong>
</p>

HTML の文法上は何も問題ありませんが、この程度のコードなら一行で書きだしたいところです。要素名の後ろに<をつけると、その要素の内側にある改行や空白を全て取り除いた状態で書き出すことが出来ます。>をつけると、その要素の外側にある改行や空白を全て取り除きます。

Haml

%p<
	Hello,
	%strong> Haml!

HTML

<p>Hello,<strong>Haml!</strong></p>

全て一行に纏められました。

id と class は Emmet(Zen Coding)風に記述する

Haml

%h1#pageTitle Hello, Haml!
%div.container hogehoge
%p#message.text-info.lead Lorem ipsum

.container foo

HTML

<h1 id="pageTitle">Hello, Haml!</h1>
<div class="container">hogehoe</div>
<p id="message" class="text-info lead">Lorem ipsum</p>

<div class="container">foo</div>

#記号の後ろに id 名、.記号の後ろに class 名を書きます。class は上記のように書くことで複数同時に指定することができます。要素名を省略して id や class だけを指定すると、div要素とみなされて書き出されます。

Emmet (Zen Coding) について詳しく知りたいという方は、こちらをご参照ください。

属性の付け方

srchrefnametargetといった属性を指定する方法です。これに関しては以下のように二通りの記法があります。

Haml

-# Ruby 風の記法
%a{ href: 'https://dev.classmethod.jp', target: '_blank', title: 'クラスメソッド開発ブログ' } Developers.IO

-# HTML 風の記法
%a( href="https://dev.classmethod.jp" target="_blank" title="クラスメソッド開発ブログ" ) Developers.IO

HTML

<a href="https://dev.classmethod.jp" target="_blank" title="クラスメソッド開発ブログ" rel="noopener noreferrer">Developers.IO</a>
<a href="https://dev.classmethod.jp" target="_blank" title="クラスメソッド開発ブログ" rel="noopener noreferrer">Developers.IO</a>

書き出される結果はどちらも同じです。また id と class もこの記法で書くことができます。

コメントアウト

Haml

/
	この部分は
	ブロックコメントです
	
/ 一行コメント
%p Lorem ipsum

HTML

<!-- 
	この部分は
  	ブロックコメントです
  -->
<!-- 一行コメント -->
<p>Lorem ipsum</p>

コメントアウト箇所も HTML 要素と同様に入れ子とインデントを意識する必要があります。

上記の例は HTML にも出力される記法ですが、以下の記法は Haml コードでのみ有効となるタイプです。

Haml

-#
	この部分は
	ブロックコメントです
	
-# 一行コメント
%p Lorem ipsum

HTML

<p>Lorem ipsum</p>

HTMLには書き出されません。

DOCTYPE 宣言

Haml

!!!

HTML

<!DOCTYPE html>

どういう理屈なのかは置いておいて、!!!と書くと DOCTYPE 宣言部分が書き出されます。

Haml4.0.0 以前は!!!と書くと XHTML 用の DOCTYPE が書き出されましたが、4.0.0 より HTML5 用のがデフォルトで書き出されるようになりました。

pre 要素、textarea 要素の記述

pre 要素や textarea 要素では改行や空白文字をそのまま保持しておく必要があります。

Haml

%textarea
    :preserve
        hoge hoge
        <!-- <div> --> 
        yamada naoki
        <div />

HTML

<textarea>hoge hoge
  <!-- <div> --> 
  yamada naoki
  <div /></textarea>

:preserveフィルターを呼び出し、そこ以下に書かれた文字列は改行や空白文字が(※必要に応じてエスケープされたりして、)そのまま保持されます。

簡単な Ruby プログラミングを取り入れる - 変数、条件式、ループ処理など

ここまでに紹介してきたテクニックだけでも十分に効率化は図れていますが、所詮は個々の HTML タグの記法を省略しただけで、まだまだ超速と呼ぶには物足りません。Haml は Ruby 上でコンパイルされる手前、Ruby のプログラミング手法を使うことができます。この機能を上手く利用すればとっさの文言修正やレイアウト変更にも難なく対応することができるなど、超速への階段をまた一つ駆け上がることが出来るでしょう。

変数を使う

変数の定義は一行目にあるように先頭に-をつけ、その後ろに変数名を記述して値を代入します。変数の内容を出力するにはいくつか方法があり、主に以下の様な記法にて出力します。

Haml

- name = 'yamada'

%p= name
%p
    さようなら、#{name} さん
%p= "こんにちは、#{name} さん"

HTML

<p>yamada</p>
<p>
  さようなら、yamada さん
<p>こんにちは、yamada さん</p>
</p>

HTML タグと同じ行内で出力するにはタグ名の直後に=をつけ、その後に変数名を記述します。タグの後に改行して通常の文字列と合わせて表示させるには変数を#{}で囲みます。改行せずタグの直後に文字列を記述したい場合は =の後に書くわけですが、文字列全体をダブルクォーテーションで囲う必要があります。(シングルクォーテーションでは変数名がそのまま表示されてしまいます。)

例えばユーザー名など画面のいろんな箇所に同じ文言が表示されるといった場合、それぞれの箇所にベタ書きしてしまうと文言変更が発生した際に全箇所修正しなくてはなりません。変数で定義しておけば修正はその一箇所だけで済むので、ケアレスミスを犯すことなく瞬時に修正することができます。

条件式 - if else

JavaScript等と同様にifelseが使用出来ます。ちなみにelse ifに関しては Ruby に於いてはelsifと記述します。

Haml

- editable = true

- if editable
  %input{type: 'text', value: 'yamada'}
- else
  %p yamada

HTML

<!-- true の場合 -->
<input type='text' value='yamada'>

<!-- false の場合 -->
<p>yamada</p>

スイッチ - case when

同一の条件式に対して2つ以上の候補がある場合は、ifelsifを繰り返すよりもcasewhenを繰り返すほうが整然としたコードにすることができます。

Haml

- timezone = 'evening'

%p= "It is #{timezone} now."
%p<
  - case timezone
  - when 'morning'
    おはようございます。
  - when 'afternoon'
    こんにちは
  - when 'evening'
    こんばんは
[/ruby]

<h4>HTML</h4>


<h3>ループ処理 - times each</h3>
<p>Ruby にも<tt>for</tt>文はありますが、文化の違いなのかあまり使われません。代わりに繰り返し回数を明示的に定義する<tt>times</tt>や配列の長さだけ繰り返す<tt>each</tt>が頻繁に用いられます。これは Haml においても同様です。</p>

<h4>Haml <span class="ash">(※ times)</span></h4>

%ul
  - 3.times do |i|
    %li= "Item No, #{i}"

HTML

<ul>
  <li>Item No, 0</li>
  <li>Item No, 1</li>
  <li>Item No, 2</li>
</ul>

3 回繰り返すという言葉そのままの処理です。サンプルにあるようなリストのアイテムや、テーブルの行をダミーで作りたいときなどに便利です。

Haml (※ each)

- stones = ['Mick', 'Kieth', 'Ronnie', 'Charlie']

%ul
  - stones.each do |name|
    %li= name

HTML

<ul>
  <li>Mick</li>
  <li>Kieth</li>
  <li>Ronnie</li>
  <li>Charlie</li>
</ul>

Stones のメンバー名を配列に定義し、each関数で1つずつ取り出してリストに表示させています。この辺は JavaScript のfor eachとよく似ていますが、より簡潔な書き方になっているのが Ruby ならではです。

ここまでで何となく気がついたかもしれませんが、Haml 内に Ruby の式を書くときは先頭に-もしくは=をつけるのが基本的なルールとなっています。-は Haml での内部的な処理としたい式に対して使用し、=は HTML ファイルに出力したい式(※変数の中身など)に対して使用します。

外部ファイルをインクルード

グローバルヘッダーやページフッターなど、全画面通して同じ要素のモノに関しては外部ファイル化しておくことができれば、万が一修正することになっても1ファイルのみで済むので非常に効率的な上、つまらないデグレの予防にもつながります。

Haml

global_header.haml

%header
  %span here is global header.
  %h1 Hello, Haml!

index.haml

!!!
%html
  %head
    %title Hello, Haml!
  %body
    
    = Haml::Engine.new(File.read("global_header.haml")).render
    
   .content
      %p Lorem ipsum

HTML

<!DOCTYPE html>
<html>
  <head>
    <title>Hello, Haml!</title>
  </head>
  <body>
    <header>
      <span>here is global header.</span>
      <h1>Hello, Haml!</h1>
    </header>
    <div class='content'>
      <p>Lorem ipsum</p>
    </div>
  </body>
</html>

いささか冗長なメソッド呼び出しですが、この辺りは Middleman でかなり使いやすく改善されているので、ここでは参考程度にとどめておけば良いでしょう。

おまけ - ダブルクォーテーションで出力する

どういうわけか Haml は HTML タグの属性値が全てシングルクォーテーションで囲われた状態で出力します。しかし HTML ではダブルクォーテーションで属性値が囲われるというのが一般的です。コンパイル時に以下の様なオプション指定することで、ダブルクォーテーション出力させることが出来ます。

% haml -q index.haml index.html

コンパイルコマンドに-qというオプションをつけます。これで以下のように属性値がダブルクォーテーションで囲われました。

・・・
    <div class="content">
      <p>Lorem ipsum</p>
    </div>
・・・

おわりに

従来の HTML と比べるとかなり記法に違いが感じられて、最初のうちは却ってコーディングスピードが落ちてしまうかもしれません(※ソースは山田)。ですがそれは本当に最初だけで、HTML のルールさえしっかりと身についていれば一日もかからずに使いこなすことが出来るハズです。僕はこれのお陰で一年以上前に書かれた数十ページあるソースコードを機能追加と同時進行でありながら短期間でリファクタリングすることが出来ました。フロントエンドエンジニアは是非とも習得しておきたい技術です。また Web デザイナーの方も自分のアイデアを素早く形に起こすためにも習得しておいて損はありません。プログラマー集団にデカイ顔をされないためにも、こういった技術を身につけておくと彼らからの見る目が違ってくること請け合いです。

次回から Middleman の本格的な使い方について紹介していきます。Middleman を使うことで、Haml ファイル更新の度にいちいちコマンドを打たなくても HTML を生成させることが出来ますし、Haml 自体を書く上でもより便利な関数が予め用意されているなど、誇張ではなく本当に超速でプロトタイピングが出来るようになります。

参考サイト