はじめに
この記事では、JavaScript 用のテンプレートエンジン Jarty を紹介します。
Jarty (じゃーてぃー) とは、PHP の有名なテンプレートエンジンである Smarty を JavaScript に移植したものです。ただし、完全に再現しているわけではなく、いくつかの機能は制限されています。
Jarty には以下のような機能があります。書式の多くは Smarty 互換です。
- 変数の置換 {$foo} => "abc"
- {if} {else} {/if} などの条件分岐
- {foreach} {/foreach} などのループ
- {$foo|upper|escape} などのフィルタ (パイプ)
- etc.
ソースコードは The MIT License として公開しています。
GitHub 上のリポジトリ: http://github.com/kotas/jarty
また、弊社ウェブサービスであるニコニコ動画の一部ページでも利用しています。
背景
Smarty は主にサーバーサイドで使うものですが、Jarty はクライアントサイドで利用する事を想定しています。
ウェブサービスによって JSONP 形式で公開されている API を JavaScript から利用する場合、結果を JavaScript 内のオブジェクトとして受け取る事が出来ますが、その表示をどうするか困る場合があります。
例えば、以下のような方法で表示できます。
- HTML 文を組み立て、innerHTML にまるごと入れる
- class や id などに基づいて動的に DOM を書き換える
1 の方法では、JavaScript を書く人と HTML を書く人が違う場合に困ります。また、JavaScript のコード中に HTML が混じるため、読みづらくなる欠点があります。
2 の方法では、JavaScript 中に HTML が混じる事はありませんが、最終的な DOM がどうなるのか JavaScript コードを追わないとわからない、DOM 構造を変えたら JavaScript 側の修正も必要、などの欠点があります。
Jarty を使うと、テンプレートの記述を分離でき、かつ比較的自由度の高いデザインが可能になります。また、テンプレートは HTML ベースなので、JavaScript が分からない人でも読み書きできます。
使い方
jarty.js をページ上に読み込みます。
<script src="jarty.js" type="text/javascript" charset="utf-8"></script>
簡単な使い方は以下のようになります。
var template = "Hello, {$foo}!";
var dictionary = { foo: "world" };
Jarty.eval(template, dictionary);
// => "Hello, world!"
もっと複雑な例は、以下のページから確認できます。
内部の処理について
Jarty は、受け取ったテンプレート文字列を内部的に JavaScript の関数オブジェクト (Function) にコンパイルしています。
例として、以下のようなテンプレートは
Hello, {$foo}!
以下のような JavaScript 関数にコンパイルされます。(実際にはもうちょっと複雑です)
function (d) {
var s = "";
s += "Hello, ";
s += d["foo"];
s += "!";
return s;
}
Jarty.compile() 関数で、テンプレートをコンパイルして関数オブジェクトを取得できます。
var compiled = Jarty.compile(template);
compiled({ foo: "world" });
// => "Hello, world!"
compiled({ foo: "Jarty" });
// => "Hello, Jarty!"
同じテンプレートを何度も利用する場合は、コンパイルされた関数オブジェクトを 使い回す事で速度を得る事ができます。
ベンチマーク
ベンチマーク結果は JavaScript エンジンの性能によって大きく左右されるため、Windows マシン上 (Intel Core2 1.86GHz + 2GB RAM) でいくつかのブラウザで確認してみました。
いくつかの変数置換、{foreach}、{if} を含むテンプレート文字列を 1000 回評価すると、以下のようになりました。
Each-time Compile
Mozilla Firefox
1224 ms (817 回/秒)
Internet Explorer 6
3828 ms (261 回/秒)
Internet Explorer 7
3984 ms (251 回/秒)
Internet Explorer 8
2500 ms (400 回/秒)
Google Chrome
381 ms (2625 回/秒)
Opera
1343 ms (745 回/秒)
Safari
703 ms (1422 回/秒)
Google Chrome の早さが目立ちますね。一番遅い IE6〜7 でも 250 回/秒ほど回りました。
また、コンパイル済みの関数オブジェクトを使い回して 1000 回評価すると、以下のようになります。
Precompile
Mozilla Firefox
65 ms (15385 回/秒)
Internet Explorer 6
265 ms (3774 回/秒)
Internet Explorer 7
281 ms (3559 回/秒)
Internet Explorer 8
156 ms (6410 回/秒)
Google Chrome
7 ms (142857 回/秒)
Opera
31 ms (32258 回/秒)
Safari
14 ms (71429 回/秒)
毎回コンパイルするのに比べて、コンパイル済み関数オブジェクトを使い回すと、圧倒的に速度が勝っているのを確認できます。
おわりに
JavaScript 用のテンプレートエンジン Jarty を紹介しました。
なお、Jarty のソースコード、及びこの記事中に含まれるコードは全て The MIT License です。
Jarty のソースコードは GitHub 上のリポジトリ を参照してください。
Enjoy!
