unoh.github.com

jQueryのパフォーマンス最適化に関するTips

Tue Nov 13 07:57:55 -0800 2007

こんにちは、山下です。
今回は、jQueryのパフォーマンス最適化について説明したいと思います。

軽量と言われているjQueryですが、いろいろな機能を実現しようとして複数のプラグインを導入すると、だんだんと動作が重くなってきます。サーバ側をいくらチューニングしたところで、ブラウザ側での処理に時間がかかっていたら、せっかく訪問してくれたユーザに重いサイトとして認識されてしまいます。以下に、ウノウで運営している「映画生活」で実際に行っている方法を紹介します。

1. Packed版ではなくMinified版を使う

jQuery1.1まではPacked版のみだったのですが、jQuery1.2からMinified版もダウンロードできるようになりました。Packed版よりもMinified版を使うことをお勧めします。どう違うのかというと、Packed版はファイルサイズを極限まで削減するために静的辞書+可読文字符号化という方法を使っているのですが、ページが読み込まれる度に展開処理が必要になり、無駄な処理が発生します。

これに対してMinified版は、コメントや無駄な空白などを取り除くだけですので圧縮率は低いのですが、無駄な展開処理が必要ありません。最新のPCを使っている場合は気にならないかもしれませんが、古いPCを使っている場合にこの差は顕著になります。静的辞書法については、JavaScriptの圧縮 - daily dayflowerに詳しく書かれていますので参考にしてください。

以上のような理由からjQuery1.2からMinified版が提供されるようになったのですが、まだ1.1.4を使っている場合には、自分でMinified版を作成しましょう。私はJSMinのPython版を使っています。jsmin.pyをダウンロードして次のように実行します。

$ python jsmin.py <some.src.js >some.js

2. 代わりにmod_deflateなどを使う

上で説明したように、Minified版はPacked版より圧縮率の点で劣るのですが、Webサーバの機能を使って通信時にgzip圧縮することで圧縮率を高めることができます。WebサーバにApache2を使っている場合は、mod_deflateが利用可能です。

設定例:

LoadModule deflate_module modules/mod_deflate.so
<FilesMatch "\.(html|css|js)$">
SetOutputFilter DEFLATE
</FilesMatch>

3. プラグインを一つのファイルにまとめる

すべてのページで読み込まれるプラグインなどは、jquery.jsと一緒にまとめてしまいましょう。ブラウザがWebサーバと同時に接続できるコネクション数は限られています。また、通信のオーバーヘッドをできるだけ減らすことで、レスポンスの向上が期待できます。
プラグインのjsファイルは圧縮されていないことが多いので、前述のJSMinなどを使って忘れずにMinified処理をしておきます。

4. 自動で実行される処理を止める

ThickBoxはよく使われるjQueryプラグインで、aタグにclass="thickbox"を追加するだけで画像のエフェクト表示を行うことができます。これは、JavaScriptが分からない人でも手軽に使えて便利なのですが、jQuery(document).ready()関数で毎回イベントの割り当が行われるので非常に効率が悪いです。

$(document).ready(function(){   
  tb_init('a.thickbox, area.thickbox, input.thickbox'); ← 削除
  imgLoader = new Image();// preload image
  imgLoader.src = tb_pathToImage;
});

<a class="thickbox">の代わりに、次のようにHTML内の記述を変更します。

<a href="javascript:tb_show('タイトル',
                             '/hoge/?height=300&width=300')">

ThickBoxに限らず、利用するプラグインのソースには目を通して、無駄な処理が実行されていないか確認しましょう。

5. Expiresをできるだけ長く設定する

ブラウザにキャッシュを使ってもらうようにExprireの期限をできるだけ未来に設定します。Apacheの場合は次のように設定します。

Expires On
ExpiresByType text/javascript "access plus 30 day"
ExpiresByType application/x-javascript "access plus 30 day"

6. class指定ではなくid指定にする

以前のエントリで紹介したように、jQueryでは $('div.hoge') などとclass指定でノードを選択することが簡単にできるのですが、class指定での選択はid指定よりも遅いので可能な限り、$('#hoge')のようにidを指定するようにします。HTMLの構造上できない場合もあるかもしれませんが、速度が変わってくることは覚えておいたほうが良いと思います。

 

2007/11/14 17:20追記

コメント欄で質問されたので、下記のようなコードで軽くベンチマークを取ってみました(MacBook+Firefox)。#hogeだと速いのですが、div#hogeだと逆に遅くなってしまうようです。ですので、初掲時のdiv#hogeを#hogeに修正させていただきました。

var txt = '';

var date = new Dae;
for (var i = 0; i < 10000; i++) txt = $('#hoge').html();
alert(new Date - date); // 582

date = new Date;
for (var i = 0; i < 10000; i++) txt = $('div#hoge').html();
alert(new Date - date); // 4771

date = new Date;
for (var i = 0; i < 10000; i++) txt = $('div.hoge').html();
alert(new Date - date);  // 4595

 

以上、jQueryのパフォーマンス最適化について説明してきましたが、これによって向上できる時間は数十〜数百ミリ秒かもしれません。しかし、新しい機能を追加するよりもパフォーマンス・チューニングを行ったほうがアクセス向上に役立ったというデータもあり、サイトを訪れてくれたユーザに少しでも快適に使ってもらうために有効だと思います。