jade(テンプレートエンジン)をクライアントサイドで動かすの巻

2014/02/24 追記:
jade.compile(jadeText, {client: true})は使えなくなったようです。かわりにjade.compileClient(jadeText)を使えとのこと。
あと、下の文中のanonymousはtemplateに変わってました。

Node.jsのフレームワークExpressの標準テンプレートエンジンである、jade
https://github.com/visionmedia/jade
を、クライアントサイドで動かしたくなったので、色々調べながらなんとかゴリ押しでできるようにした。
公式読んだ限り普通に出来そうな事を書いてあるんだけど、
僕が英語弱すぎてかつ色々初心者すぎて分からなかったので、色々試してやってみました。

まずjadeは、jade->js->htmlという流れでコンパイルされる。
jadeをjsに変換することを、公式に倣い、プリコンパイルということにする。
プリコンパイル時にclient: trueオプションをつけると、次のような感じのjsの関数に変換される。

コンパイル元(jade)

p= hello

コンパイル後(js)

function anonymous (locals) {
  var buf = [];
  var locals_ = (locals || {}),hello = locals_.hello;jade.indent = [];
  buf.push("\n<p>" + (jade.escape(null == (jade.interp = hello) ? "" : jade.interp)) + "</p>");;return buf.join("");
}

例えばNodeで動かすなら、

var jade = require('jade');
var fn = jade.compile('p= hello', {client: true, pretty: true, compileDebug: false});
console.log(fn.toString());

とかすると上のような関数を文字列として書き出せる。

で、htmlを生成するには、この関数の第一引数localsに、テンプレートで埋めたいモノを含んでるオブジェクトを渡せばよいので、

var html = fn({hello: 'Hi'});
console.log(html);

とかすると、

<p>Hi</p>

というhtmlが生成されるという理屈。
プリコンパイルされた状態はただのjsなので、クライアントサイドでも普通に評価できる。

ということで、私が至った結論としては、

  1. 1箇所(例えばclient/views/)にjadeファイルを置く
  2. シェルで全jadeファイルを回し、
  3. jadeファイルを開き、その文字列をjade.compile()の引数に渡す(Nodeならfsモジュールを使う)
  4. できた関数を1ファイルに書き出していく。
  5. public/以下に置き、公開する。
  6. クライアント側で、その関数を呼び出す。

あとは、些細な点ですが、
上のようにプリコンパイルした関数をtoString()するとanonymousという名前の関数になってしまうので、この名前を変えてやる必要があります。
anonymousをjadeのファイル名に変えようと思ったのですが、それだとファイル名にjsで使えない文字が入っていた時困りますので、
書き出す1ファイルを

var pre = {
  'jadeのファイル名': function (locals) {...},
  'jadeのファイル名2': function (locals) {...},
};

というように連想配列にしました。これで、呼ぶときはpre.ファイル名(obj)でOK。