ScottyからHamletを使う

HaskellでWebアプリ作るときにrubysinatraライクなScottyというシンプルなフレームワークが便利です。

ScottyはTemplate Engineについてagnosticなので好きなの使えます。

HaskellのTemplate Engineはblaze-htmlという高速に動作する共通基盤のようなものがあって、Hamletはその上に構築されているそうです。Scottyからblaze-htmlを生で使う方法は ここのページ が参考になりますが、Yesodで使われてるHamletをScottyでも使ってみたいところ。

ヒアドキュメント的にHamletを書くサンプルはググるといっぱい出てくるのですが、外部ファイルから読み込んでScottyで使う方法が以下。

サンプルのソース

{-# LANGUAGE QuasiQuotes, TemplateHaskell, OverloadedStrings #-}

import Web.Scotty

import Data.ByteString.UTF8 as BU
import Data.Text.Lazy.Encoding
import Data.Text

import Text.Hamlet (hamletFile)
import Text.Blaze.Html.Renderer.Text (renderHtml)

import Data.Monoid (mconcat)

main = scotty 3000 $ do

  get "/" $ do
    let title = pack "hoge"
    html $ renderHtml $ $(hamletFile "views/index.hamlet") undefined

views/index.hamletファイルの中身は

$doctype 5
<html>
  <head>
    <title>#{title}
  <body>
    hello!

ハマりポイントは

  • hamletFileするところで$()で囲む(TemplateHaskellの処理のためかな)
  • URLレンダラ―を使わない場合に後ろにつけるのはundefined
  • テンプレートに食わせる変数はhamletFile関数から見えるスコープにあればOK
  • 食わせる前に変数をpackする
  • UTF8文字列使うときはData.ByteString.UTF8をimportする
  • ファイル冒頭のプラグマを忘れないこと

ちなみにHaskellで書くWebアプリのパフォーマンスですが、HaskellはHTTPサーバミドルウェアWarpというのがあってScottyはそれを使っててnode.jsより数倍速いそうです。node.js自体がP系スクリプト言語より相当早いのでHaskellでWebアプリはかなりのパフォーマンスが期待できます。