今回はJavaScriptとWebページの表示・操作の体感速度について考えてみます。というのは,JavaScriptのせいでWebページの表示や操作などの速度が遅くなっている,と感じることがあるからです。

 現在のWebサイトでは,JavaScriptを使って使い勝手を向上することは,ごく当たり前に行われています。例えば,動的にページを書き換えたり,ページ遷移を行わずにサーバーと通信を行ってデータを取得したりと,JavaScriptを使うことで,Webサイトをより便利に,より使いやすくすることができます。

 Ajaxという言葉がはやってから,もう2年以上がたつんですよね。何年か前,JavaScriptはじゃまで,セキュリティを低下させる不要なものだと見なされていた頃がありました。しかしそれから一変して,「JavaScriptをがんがん使ってもいい」という空気になったことで,Webサイトを作成する我々は,使い勝手を向上させるための,大きな力を得たわけです。そしてそれから,様々なテクニック,様々なインタフェースが考案されて,Webページをどんどんリッチに,より使いやすくする方法が,模索され,日々進化を遂げています。

 しかしその一方で,JavaScriptを使うことで,ページの表示や読み込みが遅くなってしまうなど,逆に使い勝手が低下する部分もあるなあ,とも思うのです。JavaScriptを使うことによる使い勝手の低下,というと「不必要に多くのJavaScriptを使ってしまった」とか,「JavaScriptを使ったものの使いづらいインタフェースを作ってしまった」といった直接的なものがまず頭に浮かびます。それから,ちょっと古いですが「右クリック禁止」に代表されるある種の「間違った」使い方もありますよね。

 しかし,JavaScriptを適材適所に使い,ユーザビリティを高めていたとしても,ページの読み込み(表示)完了までに時間がかかってしまったり,ページ内での,リンクをクリックするなどの動作が「引っかかる」感じがする,といったことが起こってしまっていたら,せっかくの使い勝手が台無しになってしまうかもしれません。せっかく様々な工夫をしても,かえってJavaScriptを使わないほうがよかった,なんて言われてしまうことにもなりかねません。

 CNET Japanで翻訳が公開されているRead/WriteWebでも,以下のような記事が出ていました。

JavaScriptがWebを遅くする--今できる緩和策を考える

 ここで触れられているのは,主にウィジェット,つまりはブログパーツのことです。ブログパーツはJavaScriptを読み込むケースが非常に多いので,たくさんのブログパーツを読み込むと,どうしても読み込むデータの量も多くなりますし,実行にも時間がかかってしまいます。しかもブログパーツは,様々な場所で利用される可能性があるので,JavaScriptの使われ方にも気を遣わねばならない部分は多くなります。

 ですから,ブログパーツの話も重要なのですが,それについて考える前に,まずはWebページ一般において,JavaScriptをどう扱ったら,使い勝手を低下させずにすむのか,ということを考えてみたいと思います。インタフェース自体の設計上の「使いにくさ」を除き,ページの読み込み(表示)完了までに時間がかかってしまう,ページ内での動作が「引っかかる」感じがする,といったことに注目した場合,とにかくJavaScriptを「軽く」動作させるために何をすればいいのか,という話になります。

 その方法としては,いろいろなアプローチが考えられてきており,Web上にも様々な情報が公開されています。それを大まかに分類すると,以下のような感じになると思います。

  • JavaScriptファイルの読み込み時間を短縮する
  • 実行のタイミングなどを工夫して体感速度を上げる
  • JavaScript自体の処理速度を上げる工夫をする

 今回は,これらのテクニックをいくつか紹介しながら,その方法論などについて考えてみることにしました。

JavaScriptファイルの読み込み時間を短縮する

 まず,JavaScriptファイルの読み込み速度を向上する方法について考えていくことにしましょう。

 よく知られているのは,JavaScriptはHTMLに含めず,別ファイルとして用意することです。そうすることでJavaScriptのファイルがHTMLとは別にキャッシュされ,キャッシュの効率が上がることが期待できるからです。しかも,同じファイルを複数のページで読み込んでいれば,よりキャッシュの効率は上がります。

 しかし,第11回でも紹介したYahoo! USER INTERFACE BLOGの「Performance Research, Part 2: Browser Cache Usage - Exposed!」によれば,Yahoo!のユーザーのうち40-60%の人はキャッシュが空っぽの状態でアクセスしてくる,とされています。したがって,キャッシュされていない状態でも,より読み込み速度を上げるための工夫が求められているわけです。

 ファイルの読み込み速度を減らす最も単純な方法は,ファイルのサイズを小さくすることです。プログラムの内容を精査して,処理をシンプルに,コードを短くすることは非常に大切で効果的な方法ですが,それ以外にも,ファイルサイズを小さくする方法はあります。

 JavaScriptのファイルから,コメントや空白を取り除いたりする「圧縮」加工をして,ファイルサイズを小さくする方法を,最近よく見かけるようになってきました。例えば,以下のような感じにするわけです(図1)。

図1:JavaScriptファイルの「圧縮」

function show_message(message, elm){
  if( elm ) elm.innerHTML = message;
  else alert( message );
}
     ↓
function show_message(A,B){if(B){B.innerHTML=A}else{alert(A)}}

 単に空白やコメントを削るだけではなく,ローカル変数名など,他に影響を与えないと思われる変数については,短い名前に置換してしまっていることがわかります。これは,手作業でやると大変な処理ですが,それを自動でやってくれるツールがいくつも公開されています。

 例えば,Packerや,YUI Compressorなどです。YUI Compressorは,Yahoo! USER INTERFACE BLOGを公開するYahoo!によって公開されているツールで,最も気合いが入ったツールになっています。

 ちなみに,HTTPには転送時にgzip圧縮を行って転送量を減らす「HTTP 圧縮(HTTP compression)」という仕組みがあります。JavaScriptはテキストファイルなので,これを行うだけでかなりの圧縮が見込めるのですが,それでもさらにYUI Compressorなどのツールを利用することで,サイズの減少が見込めます。

 例えばPrototype.js(バージョン1.6)のファイルをYUI Compressorで圧縮してみると,以下のようになり,gzipで圧縮したあとも,約25%小さいファイルになることがわかります(図2)。

図2:YUI Compressorによる圧縮結果

 ファイルサイズ(gzip圧縮前)ファイルサイズ(gzip圧縮後)
オリジナル121KB28KB
YUI Compressor使用71KB21KB

 これはなかなか優秀なのですが,問題となるのは,一度圧縮処理をしてしまったJavaScriptファイルは,メンテナンスをするのが困難になってしまうことです。困難,というよりももう不可能,と言ってもいいと思います。

 ですから,開発やテストは圧縮前のファイルで行い,実際に本番の環境にリリースする際に,圧縮をかけるようにする必要があります。例えば,デプロイ(deploy)ツールに工夫をして,本番環境にリリースする際に,自動的に圧縮を行う,といった処理を追加するのが良さそうです。

 JavaScriptの中身を圧縮するほかに,もう一つ速度向上に効果のある方法は,JavaScriptのファイルを一つにまとめる,というものです。

 JavaScriptのファイルを,目的別にファイルを分けてしまうと,1ページで読み込むJavaScriptファイルの数がどんどんと増えてしまいます。しかし,JavaScriptのプログラムは,複数のファイルに分散されて記述されていても,一つのファイルにすべてが記述されていても,基本的には全く同じように動作します。HTTPでのやり取りは,1回ごとにオーバーヘッドがありますから,JavaScriptの場合は,複数のファイルに分割されているよりも,一つのファイルにまとまっていたほうが,全体的な速度は速くなります。

 とは言っても,開発の際には用途や目的ごとに異なるファイルとして管理したほうが便利です。したがって,開発時は複数のファイルに分割された状態にして,リリースされたアプリケーションでは一つのファイルになっているのが理想的です。

 そのための方法としては,あらかじめまとめたファイルを静的に作っておく方法と,ページへのアクセスの際に,動的にファイルをまとめる方法があります(図3)。

図3:JavaScriptファイルの統合

 静的にファイルを生成する場合は,前述の圧縮の場合と同様に,本番の環境への反映の際に一つのファイルにまとめるような仕組みを導入すべきなんだと思います。動的にファイルを統合する仕組みとしては,以下にPHPを利用した実装例があります。

Supercharged Javascript

 これは,jsファイルへのアクセスをPHPに送り,指定されているファイルを結合して送り返すものです。

 2007年4月に行われたYAPC::Asia 2007において,Six ApartのBen Trott氏のセッション「How we build Vox」の中で,Voxでは20以上のJavaScriptファイルがあるため,Parlbalを利用してJavaScript,CSSを結合している,ということが言及されていました。

 実際に,Voxのページのソースコードを見てみると,以下のようにファイルの結合を行っていると思われる記述が見て取れます。

<script type="text/javascript" src="http://p-static.vox.com/.shared:v40.5
:vox:ja/js/Core.jsc?/js/DOM.jsc,/js/Cookie.jsc,/js/JSON.jsc,/js/Timer.jsc,
/js/Observable.jsc,/js/Cache.jsc,/js/Client.jsc,/js/Template.jsc,/js/Auto
layout.jsc,/js/Component.jsc,/js/Dialog.jsc,/js/App.jsc,/js/List.jsc,/js/
ArcheType.jsc,/js/ArcheType/Client.jsc,/js/ArcheType/Controller.jsc,/js/
ArcheType/Autocomplete.jsc"></script>

 なお,読み込むファイルの数を極限まで減らそうとして,CSSとJavaScriptを一つのファイルにまとめようとしている人もいます。

Combine CSS with JS and make it into a single download!

 ここではJavaScriptとCSSのコメントの記述方法の違いを利用して,CSSとして読み込まれた場合はCSSとして,JavaScriptとして読み込まれた場合はJavaScriptとして扱われるファイルの作り方を紹介しています。

 さすがにこれはやり過ぎですし,いわば「ネタ」ではあるのですが,こんなこともできる,ということで紹介してみました。