高速な CSS セレクタエンジン「Sizzle」「Peppy」を試す
最近のほとんどの JavaScript フレームワークには、 CSS セレクタによる DOM エレメントの取得機能が実装されています。複数の要素を柔軟な条件で取得できるので、 DOM ツリーの操作がシンプルに記述でき、とても便利です。しかし、単に CSS セレクタを使いたいだけなのに、フル機能のフレームワークを読み込むのはちょっと抵抗がありますよね。
そんな悩みを解決してくれるのが、本日ご紹介する Sizzle, Peppy という 2 つのライブラリです。これらは他のフレームワークに依存しない独立した CSS セレクタエンジンで、しかも jQuery 等の既存のエンジンより数倍高速に動作します。 unobtrusive な Web ウィジェットの開発や、独自フレームワークの開発に最適ですね。その他にも広範な用途に使えるでしょう。
以下でこれらのライブラリの使い方や動作速度等の検証結果を掲載していますので、皆さんぜひご活用ください!
Sizzle : 次期 jQuery 向けに開発中のセレクタエンジン
http://github.com/jeresig/sizzle/tree/master
jQuery の開発者である John Resig 氏が、次期 jQuery のために開発しているセレクタエンジンです。 jQuery 同様、 MIT License で配布されています。前述のように単体でセレクタエンジンとして使えるほか、 jQuery のセレクタエンジンをリプレースして高速化することもできます。以前は IE で正しく動作しない部分があったのですが、最新版ではほとんど修正されており、実用的になってきたようです。それでは、さっそく使ってみましょう。
使ってみる
まずはこちらのページの download ボタンで Sizzle の関連ファイルをダウンロードしてください。それを解凍し、トップディレクトリにある sizzle.js を SCRIPT タグで HTML に読み込めば準備完了です。
実際に DOM 要素を取得するには、 Sizzle メソッドを呼び出します。
Sizzle(CSSセレクタ[, ルート要素])
CSS セレクタは取得する条件を CSS セレクタの文法で記述した文字列、ルート要素はセレクタの評価時にルートとして扱う DOM 要素です。ルート要素を省略すると window.document が使われます。返り値は、指定したセレクタにマッチする HTMLElement を格納した配列になります。
例として、 stripe クラスの順序なしリストの背景色をストライプにするサンプルを作ってみました。
特定のクラス名のついた要素を操作するような処理はとても簡単に書けます。
jQuery のセレクタエンジンを差し替える
前述のとおり、 jQuery のセレクタエンジンを Sizzle に差し替えることもできます。そのためには、まず解凍した Sizzle のトップディレクトリ(sizzle.js があるディレクトリ)で make を実行します。すると、 jquery-sizzle.js というファイルができますので、これを jQuery 本体の後に読み込めば OK です。
Windows 環境等で make が無い場合は、 sizzle.js の最後の方にある "// EXPOSE" の辺りに libs/jquery.js の内容をコピー&ペーストし、それを jquery-sizzle.js という名前で保存すれば同じ結果になります。
先ほどの例を jQuery を使って書き換えると以下のようになります。
jQuery の標準セレクタエンジンに対して、とくに複雑なセレクタの処理が顕著に高速化されます。 CSS セレクタをフル活用したいときに、試してみてください。
Peppy : 生まれたての CSS3 準拠セレクタエンジン
http://jamesdonaghue.com/?cat=8
先月(10月)の半ばに公開されたばかりの、新しいセレクタエンジンです。 FreeBSD Lisence で配布されています。ファイルサイズは Sizzle より若干大きいのですが、動作速度は僅かに速いようです(環境によって違います。詳しくは後の速度比較参照)。作者の James Donaghue 氏は次のバージョンでさらなる最適化を施すとアナウンスしているので、これは期待が持てますね。
使ってみる
Peppy についても、基本的な使い方からご紹介しましょう。スクリプトファイルはこちらのページにある「Peppy Min (10K)」のリンクから取得できますので、それを peppy-min.js として保存し、 SCRIPT タグで HTML に読み込んでください。
実際に DOM 要素を取得するには、以下の peppy.query メソッドを呼び出します。
peppy.query(CSSセレクタ[, ルート要素])
実際はもっと引数があるのですが、おそらく内部処理用ですので、実用上は上記のように覚えておけば良いでしょう。それぞれの引数・返り値の仕様は Sizzle とほぼ同様です。
順序なしリストの背景色をストライプにするサンプルは以下のようになります。読み込むスクリプトと呼び出すメソッドが変わっただけです。
ちなみに peppy-min.js はその名のとおり圧縮バージョンで、ファイルサイズは 10k 弱です。最初から圧縮版が用意されているのは便利ですね。
$ でも呼び出せます
Peppy には現在のところ jQuery のセレクタエンジンを置き換えるような機能はありませんが、 peppy-min.js の読み込み時点でグローバル変数 $ が定義されていなければ、 $ が peppy.query メソッドのエイリアスになります。従って、上記のサンプルで DOM 要素を取得している部分は以下のように書き換えられます。
var el = $('.zebra li:nth-child(odd)');
ちょっとだけ jQuery や Prototype.js っぽく使えますね(笑)。
どちらを選ぶか?
以上のように、 Sizzle と Peppy はいずれも使い勝手の良い優れたライブラリに仕上がっています。そうなると、どっちを使ったら良いかが悩みどころになりますよね。そこで、 CSS セレクタエンジンの重要な要素を比較してまとめてみました。選択の際の参考にしていただければと思います。ただ、正直あまり差が出ていないので、最終的には好みで判断するしかないかもしれません。
なお、いずれのライブラリもまだ開発中なので、今後のバージョンアップで条件が大きく変わる可能性が高いです。以下はあくまで記事を書いた時点での情報ということで、ご了承ください。
速度比較
CSS セレクタエンジンの性能で、最も気になるのは動作速度です。そこで、まずは Firefox 3.0 (Mac mini), Safari 3.1 (Mac mini), IE7 (libretto U100) でベンチマークをとってみました。ベンチマークは Peppy のサイトにある slickspeed とほぼ同じものですが、 Sizzle は現時点での最新版に差し替えてあります。
ご覧のとおり互角の戦いですが、総合的には Peppy のほうが僅かに勝っているようです。 querySelectorAll をサポートしている Safari でも差がついているのは、 Sizzle が querySelectorAll の結果を通常の配列にコピーしているのが原因でしょう。逆に言うと、 Peppy を使う場合は結果の配列に対して push などのメソッドを呼ばないように注意する必要があります。このあたりは好みの分かれるところですね。
また、 IE7 でもトータルは Peppy が勝っていますが、使用頻度の高い Combinator 系(子孫セレクタ等)は Sizzle が速いので、実運用では Sizzle に分があるかもしれません。
ファイルサイズ
ページ読み込みのパフォーマンスを考慮すると、スクリプトのファイルサイズも重要です。そこで、 YUI Compressor を使って双方の JavaScript ファイルを圧縮してみました。結果は以下の通り。
圧縮前 | 圧縮後 | |
---|---|---|
Sizzle | 16,487bytes | 8,586bytes |
Peppy | 22,717bytes | 9,776bytes |
圧縮前、圧縮後ともに Sizzle のほうがコンパクトになっています。ウィジェットや iGoogle ガジェットのように読み込み速度が重視されるアプリケーションでは Sizzle が良さそうですね。ただ、圧縮後の差は 1kb 程度ですので、通常の Web アプリケーションにとっては決定的な違いではないと思います。
セレクタのサポート状況
セレクタのサポート状況は、 Sizzle, Peppy ともまったく同じのようです。 CSS3 セレクタのほとんどが使えますが、動的疑似クラスと疑似要素、それに以下の疑似クラスは未サポートです。
- :target
- :lang
- :nth-of-type
- :nth-last-of-type
- :first-of-type
- :last-of-type
- :only-of-type
ただ、 Peppy のソースを覗くと *-of-type 系のセレクタをサポートしようとしている形跡があります。まだ例外を投げたり *-child と同じ動作だったりしますが(笑)、今後のバージョンアップでのサポートが期待されます。
また、 Sizzle, Peppy ともに jQuery の has, contains といったセレクタもサポートしています。ただし、 Safari などの querySelectorAll をサポートしたブラウザでは、処理を querySelectorAll に丸投げするため、非標準セレクタは使えなくなります。引数で querySelectorAll を使うかどうかが指定できるといいのですがね。
以上、本日はフレームワークに依存しない CSS セレクタエンジンの Sizzle, Peppy をご紹介しました。 DOM API の煩雑さは JavaScript アプリケーションを作成する際の頭痛の種ですが、これらのライブラリを利用することで大きく改善されそうです。 Web アプリケーション全体の品質の底上げに繋がる、重要なライブラリだと思います。 2 つのライブラリが競い合うことで、完成度により磨きがかかることが期待されますね。私も今後の開発に存分に活用していこうと思っています。
詳しくはこちらの記事をどうぞ!
この記事にコメントする