初期の頃の Web では、Web ページのパフォーマンスを最大にするということは、不要な HTML マークアップを使用しない、JavaScript コードの量を最小限にする、そして画像のファイル・サイズを大幅に減らすことを意味するのが一般でした。そうすれば、ページがロードされるまで、典型的なネット・サーファーが席を立ってコーヒーを淹れに行くことがなくなります。
Web のさまざまな側面が進歩した今、開発者の目の前には、まったく新しいパフォーマンス上の考慮事項が出現しています。DSL とブロードバンドは、高速インターネット・アクセスを多くの人々にとって身近な存在にしましたが、その一方で、ロード時間と応答性に対する人々の期待を高くしたのも事実です。現在私たちは、ページでアクションを起こすと同時に結果が返ってくることを期待するまでになっています。Ajax (Asynchronous JavaScript and XML) の登場により、イベントに応答する前にページ全体をロードする必要がなくなり、開発者は Web アプリケーションでデスクトップのようなエクスペリエンスを実現できるようになりました。これは明らかなメリットですが、このおかげで平均的な Web ユーザーが、このような応答性をあらゆる Web アプリケーションに求めるようになりました。さらに、最近のモバイル Web の急増により、前衛的な Web ユーザーの要求に応えるという新たな課題もあります。しかもこの課題には、画面が小さく、処理能力にしても、接続速度にしても制約のある機器で動作するようにしなければなりません。
この記事の焦点は、読者の皆さんに JavaScript および Ajax Web アプリケーションのパフォーマンスを最大にするために考慮すべき点を知ってもらうことです。記事では、新しいアプリケーションと既存のアプリケーションのどちらに組み込むかに関わらず、新しく作成するコードに取り組むための最善の方法について一連のガイドラインを提供します。また、アプリケーションのパフォーマンスを測定するために利用できる各種のツールと手法について説明し、最後に、既存のコードを変更することなく、パフォーマンスを改善するさまざまな方法を紹介します。
JavaScript および Ajax 開発のベスト・プラクティス
JavaScript 開発に伴う問題の 1 つは、JavaScript コードを作成する開発者と Web 設計者の大半は、実際に JavaScript 自体について基礎から学んだ経験がないことです。一般にそのような開発者、設計者の JavaScript 言語に関する知識は、Web で見つけた特定の機能を実行するスニペットをアプリケーションに追加するという作業を繰り返すなかで蓄積されたものです。変数を宣言する方法、条件文を作成する方法、計算を実行する方法は理解していても、JavaScript 言語を全般にわたって解説した書籍を手にして一から学んだことはありません。開発者たちが開発作業を楽にするために、jQuery や YUI などのライブラリーやフレームワークに飛びつくなか、この問題は今でも続いています。
JavaScript ライブラリーを利用するのは何も間違ったことではありませんが (実際、私も JavaScript ライブラリーの熱烈なファンです)、最近の開発者たちの間では、JavaScript そのものではなく、特定の JavaScript フレームワークのエキスパートになっていく傾向があります。このことが問題となるのは、そのような JavaScript フレームワークのエキスパートは極めて非効率的なコーディング方法を使用することが多いからです。場合によっては通常の JavaScript を使ったほうが遥かに高速に実行できるような処理にさえも、フレームワークの機能を使用しています。
このセクションでは、JavaScript 開発者でないと見落としがちな分野を重点に、JavaScript および Ajax 開発のベスト・プラクティスについて説明します。
JavaScript アプリケーションのパフォーマンスを最大にするための黄金律は、可能な場合には常に、JavaScript コードを HTML ファイルに直接組み込むのではなく、外部 JavaScript ファイルを使用することです。外部 JavaScript ファイルを使用すれば、JavaScript コードを複数のページで何度も複製する必要がなくなるだけでなく、JavaScript コードが Web ブラウザーでキャッシュされることになるため、以降のページ・ロードのたびに繰り返しコードをロードする必要がなくなります。外部ファイルにした場合、追加の HTTP リクエストをサーバーに送信しなければならないため、最初のページ・ロードにはかなり時間がかかります。けれども大多数のアプリケーションでは、最初のページ・ロードに伴うパフォーマンス・ヒットは、その後のページ・ロードで負荷を節約できることで十分過ぎるほど補われます。
このルールの例外は、Web にアクセスする訪問者のほとんどが 1 つのページしか表示しない場合です。そのような場合、つまり最初のページ・ロードをその後のページ・ロードと同じ速さ、あるいはそれよりも速くしなければならない場合には、インライン JavaScript を使用したほうが適切です。Steve Sounders は著書『High Performance Web Sites』(「参考文献」のリンクを参照) のなかで、「Post-Onload Download」という方法を提案しています。この方法は、最初のページでは JavaScript コードを HTML ファイル自体にインライン化し、最初のページが完全にロードされた後、以降のページに必要な外部 JavaScript ファイルを動的にロードするという方法です。けれどもほとんどの場合は、単に外部 JavaScript ファイルを使用する方法で十分でしょう。
JavaScript フレームワークおよびライブラリーを使用するのが適している場合
私は JavaScript フレームワークおよびライブラリーの使用を全面的に支持しています。JavaScript フレームワークおよびライブラリーは、ブラウザー間の互換性に関する多くの問題を解決するのに役立つだけでなく、適切に使用すれば、Web アプリケーションの開発時間を大幅に短縮することができます。そうは言っても、これらのツールを使用するときには十分注意しなければなりません。大多数のツールはかなりサイズが大きいため、アプリケーションのパフォーマンスを低下させる可能性があるからです。
真っ先に自らに問いかける必要があるのは、「どうしてもフレームワークを使用しなければならないのか?」という質問です。私が初めて JavaScript フレームワークを使ったのは数年前で、当時開発していた Web アプリケーションで Ajax を使用する必要が出てきたときのことです。作業を楽にするために、私は自分で XMLHttpRequest 関数を作成する代わりに、Prototype フレームワークを利用することに決めました。アプリケーションでは Ajax リクエストを実行してサーバーからのレスポンスを処理する以外、このフレームワークは何の役にも立ちませんでしたが、それでもフレームワークの使用を止めることはしませんでした。幸い、私が開発していたアプリケーションは比較的小さな社内用アプリケーションだったため、パフォーマンスはそれほど重要ではありませんでしたが、今となってみれば、Ajax 機能だけを提供する軽量のソリューションを使えば良かったと思います。
Prototype フレームワークの最新バージョンは、縮小化も圧縮もされていない状態で 141KB の大きさです。そのなかで私のアプリケーションに関連するコードのサイズは、おそらく 2KB にもならないでしょう。つまり、アプリケーションでは 139KB の JavaScript コードがまったく使われていないということです。これはファイルのサイズという点でアプリケーションのロード時間を長くしているだけではありません。JavaScript コードはブラウザーで実行されることから、実行時間も長くしています。
要点をまとめると、Prototype や jQuery、Dojo、MooTools、YUI、ExtJS などの最近の JavaScript フレームワークとライブラリーにはすべて、過剰なほどの機能が含まれていて、そのうち使用する機能もあれば、使用しない機能もあるということです。最小限の機能一式を使用するだけであれば、それよりも軽量のソリューションを調べる価値はあります。例えば YUI ライブラリーでは、デフォルトで必要最小限のフレームワークをロードした上で、必要なライブラリーを選択してロードできるようになっています。
HTML に関する書籍では、すべての <script> タグをページの <head> 要素の中に配置するようにアドバイスしていることがよくあります。<script> タグの配置についてこのように理解しているとしたら、今すぐその考えを頭から消し去ってください! <script> タグを HTML ページの先頭近くに配置すると、JavaScript コードが完全にロードされて実行されるまで、ページのレンダリングがブロックされます。<head> タグの中に <script> タグを配置した場合は、スクリプトがロードされて実行されるまでページ本体のどの部分もレンダリングされないため、ページのロードが遅いという印象をユーザーに与えることになります。
ページのパフォーマンスを最大にするには、可能な限り、JavaScript コードをページの終わり近くにある </body> タグの直前に配置してください。このようにすれば、Web ページの残りの部分 (HTML、CSS 画像、Flash のコンテンツなど) がすべてダウンロードされてレンダリングされた後に、スクリプトがロードされて実行されるため、ユーザーはロードが速いという印象を持ちます。
Web ページまたはアプリケーションに大量の JavaScript が必要な場合、そのコードをまとめて 1 つのファイルに統合すると、そのファイルがダウンロードされて、実行されるまでの待機時間が長くなる可能性があります。そのような場合には、JavaScript コードを複数のファイルに分割し、ページのロードが完了した時点で必要に応じて各ファイルを動的にロードするという方法が理にかなっています。スクリプトを動的にロードすることを目的とする LazyLoad JavaScript ライブラリーは、スクリプトの実行順序を維持するという点でのブラウザー間の違いに対処します。LazyLoad ライブラリーについての詳細は、「参考文献」を参照してください。
Ajax リクエストは従来の Web アプリケーションのルック・アンド・フィールに大改革をもたらし、JavaScript 開発者は、ユーザーがデスクトップ・アプリケーションに期待するような極めて動的かつ対話性と応答性に優れたアプリケーションを作成できるようになりました。このことから、最近の Web アプリケーションでは至るところで Ajax リクエストが使用されるようになっています。ただし、忘れがちなことですが、ユーザーは新しいページがロードされていることに気付かないにせよ、Ajax リクエストが実行しているのは通常のページ・ロードに対して行うリクエストに相当する完全な HTTP リクエストです。したがって、使用する Ajax リクエストの数を最小限にするように細心の注意を払う必要があります。
一例として、検索結果のページネーションを考えてみてください。Ajax リクエストを使用して検索結果のレコード自体を JSON 配列で取得し、2 番目のリクエストでデータベース内にある結果の総数が返されるようにして、その総数をページネーション・ロジックに使用するというアプリケーションを目にすることがよくあります。リスト 1 とリスト 2 に、この 2 つのリクエストの基本的な例を記載します (ここでは、Prototype フレームワークを使用しています)。
リスト 1. 最初のリクエスト: テーブル・レコードの取得
var url = "get_data.php";
var options = {
method: "post",
parameters: {"page":1,"rows":5},
onSuccess: firstCallbackFunction,
onFailure: firstCallbackFunction
}
new Ajax.Request(url, options);
|
リスト 2 は、総レコード数を取得する、2 番目のリクエストです。
リスト 2. 2 番目のリクエスト: 総レコード数の取得
var url = "get_count.php";
var options = {
method: "post",
parameters: {},
onSuccess: secondCallbackFunction,
onFailure: secondCallbackFunction
}
new Ajax.Request(url, options);
|
リスト 3 とリスト 4 に、上記のそれぞれのリクエストに対応する JSON フォーマットの HTTP レスポンスを記載します。
リスト 3. 最初のレスポンス: レコードの配列
{
"records": [
{"id":1,"name":"John","email":"john@example.com"},
{"id":2,"name":"Mary","email":"mary@example.com"},
{"id":3,"name":"Tony","email":"tony@example.com"},
{"id":4,"name":"Emma","email":"emma@example.com"},
{"id":5,"name":"Alan","email":"alan@example.com"}
]
}
|
リスト 4 は、2 番目のリクエストに対して総レコード数をレポートするレスポンスです。
リスト 4. 2 番目のレスポンス: レコードの総数
{"total_records": 95}
|
簡単に 1 つのリクエストにできるはずの Ajax リクエストを 2 つに分けるのは、リソースの無駄です。この 2 つのリクエストを 1 つのリクエストに結合すると、リスト 5 のレスポンスが生成されます。
リスト 5. 効率的なレスポンス: 総レコード数とレコードの配列
{
"total_records": 95,
"records": [
{"id":1,"name":"John","email":"john@example.com"},
{"id":2,"name":"Mary","email":"mary@example.com"},
{"id":3,"name":"Tony","email":"tony@example.com"},
{"id":4,"name":"Emma","email":"emma@example.com"},
{"id":5,"name":"Alan","email":"alan@example.com"}
]
}
|
このようにすれば、必要な HTTP リクエストとレスポンスがそれぞれ 1 つ減るだけでなく、Ajax リクエストに対するレスポンスを提供するためのサーバー・サイドのスクリプトも 1 つ作成する必要がなくなります。
この例は至って単純なものですが、アプリケーションが複雑になればなるほど、使用する Ajax リクエストの数を減らせるかどうかを検討することが、ますます重要になってきます。
作成するコードの行数を最小限にしようと努力するなか、開発者の多くは変数を使用することを見逃しがちです。多くの場合、変数を使用することによって特定のコードの実行時間を大幅に短縮することができます。例えば、各種のスタイルを要素に適用する以下のコードを見てください。
リスト 6. スタイルを (非効率的に) 要素に適用するコード
document.getElementById("myField").style.backgroundColor = "#CCC";
document.getElementById("myField").style.color = "#FF0000";
document.getElementById("myField").style.fontWeight = "bold";
|
上記の場合、ブラウザーはそれぞれの行で、myField という ID を持つ要素を DOM で検索しなければなりません。3 回も検索を行わなくてもよいように、document.getElementById("myField") の結果を変数に割り当て、それを各行で使用すれば、この処理の効率性を改善することができます (リスト 7 を参照)。
リスト 7. スタイルを (効率的に) 要素に適用するコード
var myField = document.getElementById("myField");
myField.style.backgroundColor = "#CCC";
myField.style.color = "#FF0000";
myField.style.fontWeight = "bold";
|
変数を使用するべきなのに、あまり使用されていない例としては、配列を繰り返し処理する for ループも挙げられます。リスト 8 の例を見てください。
リスト 8.
for による (非効率的な) 配列のループ処理
for(var i=0; i < myArray.length; i++) {
//do something
}
|
上記のコードは、ループを繰り返し処理するごとに myArray という配列の長さを計算しなければなりません。それでは極めて非効率的です。この非効率的なループの影響は小さな配列ではそれほど目立たないかもしれませんが、配列が大きくなればなるほど、かなり顕著になってきます。このループのパフォーマンスは極めて簡単に改善することができます。しかも、コードに行を追加する必要さえありません (リスト 9 を参照)。
リスト 9.
for による (効率的な) 配列のループ処理
for(var i=0, arrayLength=myArray.length; i < arrayLength; i++) {
//do something
}
|
リスト 9 では、myArray.length の参照を for 文の初期化セクションに移し、この参照に変数を割り当てました。こうすることにより、配列の長さはループの最初の繰り返しでのみ計算され、以降の繰り返し処理では貴重な実行時間を節約できるというわけです。
一般に DOM のトラバースと操作は、Web アプリケーションのパフォーマンスに大きな負担をかけます。問題は、応答性に優れたリッチなインターフェースをアプリケーションに提供するためには、DOM を扱うことが絶対に不可欠であることです。DOM の操作に伴う具体的な問題としては、DOM の操作によって影響を受けた画面上の要素の再フローおよび再ペイント (基本的には再レンダリング) をブラウザーが行わなければならないことが挙げられます。そのため、コードが原因となって発生する再フローと再ペイントの回数を最小限に減らすことが重要となります。
リスト 7 の例をもう一度見てください。このコードでは、myField という ID を持つ要素を取得して、3 つの異なるスタイル・プロパティーを要素に適用しています。これにより、3 回の再フローおよび再ペイントが行われることになりますが、コードにそれほど大きな変更が加えられていないことを考えると非効率的です。さらに、このアクションのすべてを 1 つの操作に組み合わせられることを考えれば、なおさら非効率的なコードということになります。リスト 10 に、効率性を改善したコードの例を記載します。
リスト 10. 変更を組み合わせることによって改善される DOM 操作のパフォーマンス
var myField = document.getElementById("myField");
myField.style.cssText = "background-color: #CCC; color: #FF0000; font-weight: bold";
|
スタイルの変更を組み合わせることにより、再フローと再ペイントが行われるのは 1 回だけとなるため、このアプリケーションの応答性とパフォーマンスが改善されます。
このセクションでは、アプリケーションのパフォーマンスを最適なものにする上で役立つ JavaScript および Ajax 開発のベスト・プラクティスの数々を取り上げましたが、決してすべてのベスト・プラクティスを網羅したというわけではありません。ハイパフォーマンス JavaScript を実現するためのベスト・プラクティスに焦点を絞った優れた記事、チュートリアル、書籍へのリンクについては、「参考文献」を参照してください。
Web アプリケーションのパフォーマンスの測定に関しては、アプリケーションの速度とロード時間を Web ブラウザー自体から分析するために使用できる一連のツールが揃っています。通常、これらのツールは JavaScript コードのプロファイルを作成するための機能を提供し、基本的には JavaScript コードの実行時間を計算します。さらに、ページをロードするのに伴って生じたネットワーク・トラフィックを、実行した HTTP リクエストの数、ロードされた静的リソースのサイズ (画像、外部スタイル・シート、および JavaScript ファイル) という点から分析できるツールもあります。
このセクションでは、JavaScript アプリケーションのネットワーク・アクティビティーのプロファイルを作成して分析するために使用できる、さまざまなツールについて説明します。
Firebug は、Web 開発者に役立つ豊富な機能を提供する Mozilla® Firefox® のブラウザー拡張機能です。Firebug には、JavaScript コンソール、DOM の操作と選択、スクリプトのデバッグ、DOM ソースのブラウズ、プロファイリング、ネットワーク分析など、広範な機能が用意されています。
Firebug で JavaScript のプロファイリングを行うには、「Console (コンソール)」タブにナビゲートして、「Profile (プロファイル)」ボタンをクリックします。この時点から、ページ上で JavaScript/Ajax 対応の各種機能の操作をすると、Firebug が実行時間を測定します。Firebug にはプロファイラーと対話するためのコンソール API も用意されています。図 1 に、Firebug プロファイラーによって生成されたレポートのスクリーン・ショットを示します。
図 1. Firebug のプロファイラーによるレポートの例
Firebug のネットワーク分析ツールを使用するには、「Net (接続)」タブをクリックするだけです。すると、実行した HTTP リクエスト、受信したレスポンス・コードとメッセージおよび取得元のドメイン、ファイル・サイズ、ページ・ロード時間のグラフが表示されます。さらに、各リクエストの詳細を表示して、送信した HTTP ヘッダー、受信したレスポンス、該当するファイルに関連するキャッシュ情報を調べることもできます。図 2 に、ネットワーク・トラフィックに関する Firebug の出力例を示します。
図 2. Firebug の「Net (接続)」パネルに表示されるレポートの例
Safari Web インスペクタと Chrome Developer Tools
Safari® Web インスペクタおよび Chrome® Developer Tools が提供する機能は Firebug と同様ですが、外観はそれよりも一段と優れています。Safari のツールバーで「Develop (開発)」メニューに進み (Safari の設定でこのメニューを有効に設定する必要があります)、「Show Web Inspector (Web インスペクタを表示)」を選択してください。Web インスペクタのウィンドウ最上部にある「Profiles (プロファイル)」タブをクリックし、左下隅に表示される記録用の丸いアイコンをクリックしてプロファイリングを開始します。同じアイコンをもう一度クリックするとプロファイリングが停止し、レポートが生成されます。図 3 に、このレポートの一例を示します。
図 3. Safari Webインスペクタのプロファイラーによるレポートの例
ロード時間とアプリケーションが行った HTTP リクエストを分析するには、Web インスペクタのウィンドウ最上部にある「Resources (リソース)」ボタンをクリックします。ネットワーク・リソースのグラフは、時間を基準に表示することも、サイズを基準に表示することもできます。図 4 に、この美しい出力の例を示します。
図 4. Safari Web インスペクタによるリソースに関するレポートの例
Google Chrome Developer Tools も Safari のツールと同様ですが (両方とも WebKit ベースのブラウザーです)、「Developer (開発者)」メニューの中に「Developer Tools (開発者向けツール)」として表示されます。
Internet Explorer® 8 には開発者ツールのセットが付属しています。F12 キーを押すと、「Developer Tools (開発者ツール)」ウィンドウが起動します。この Internet Explorer のツールが提供する機能は、Firebug の機能の多さには及びませんが、JavaScript 関数のパフォーマンスを測定する優れたプロファイラーが組み込まれています。この Internet Explorer の開発者ツールで「Profiler (プロファイラー)」タブをクリックし、「Start Profiling (プロファイリングの開始)」ボタンをクリックすると、アプリケーションのプロファイリングが開始されます。アプリケーションを使用してテスト対象の機能を実行した後、「Stop Profiling (プロファイリングの停止)」をクリックすると、レポートが生成されます。図 5 は、レポートの一例です。
図 5. Internet Explorer 開発者ツールのプロファイラーによるレポートの例
残念ながら、ネットワーク・アナライザーは Internet Explorer 開発者ツールに組み込まれていません。Internet Explorer を使ってアプリケーションのネットワーク・トラフィックを分析したい場合には、Fiddler ツールを使用してください。このツールは、Internet Explorer を始めとする、HTTP リクエストを行うどのアプリケーションでも見事に機能します。Fiddler についての詳細は、「参考文献」を参照してください。
YUI Profiler は、JavaScript で作成されたコード・プロファイラー・ツールです。Web ブラウザーに組み込まれているプロファイラー・ツール (または Firebug のようなブラウザー拡張機能) とは異なり、YUI Profiler はビジュアル・ツールではなく、Web ページに組み込む必要があります。このツールを使用するメリットは、アプリケーションのなかで、プロファイリングを行う範囲をターゲットとして具体的に指定できることです。しかも、実行される任意の関数をただ単に測定するのではなく、YUI Profiler では測定対象とする関数、クラス・コンストラクター、オブジェクトを登録することができます。このプロファイラーが出力を生成した後、オプションでフィルター関数を指定して出力のレポートを作成すれば、測定を行うターゲットの範囲をさらに絞り込むこともできます。プロファイル・レポートは JSON フォーマットで生成されるため、あらゆる類の表形式およびグラフ形式でデータを表示するアプリケーションを独自に作成し、そのアプリケーションにレポート結果をエクスポートするのも簡単です。
YUI Profiler を使用する主なメリットの 1 つは、特定のブラウザーに縛られていないことです。さらに、WebKit ベースのブラウザーを使用する Apple® iPhone®、Android® 機器、Nokia® N95 など、YUI が規定する A-grade のブラウザーを備えたモバイル機器でも動作します。
YUI Profiler についての詳細は、「参考文献」を参照してください。
Firefox の拡張機能である YSlow は、同じく Firefox の拡張機能である Firebug に対するプラグインとして、Web ページのロードおよび実行に関する採点をします。総合的なグレードを評価するだけでなく、JavaScript および Web ページのパフォーマンス全般におけるさまざまな側面を詳細に分析します。私が行ったテストで、91 の HTTP リクエストを行うページで YSlow を実行したところ、YSlow はページのグレードを C レベルと評価し、有益な情報を提供してくれました。それは、このページには 10 の外部 JavaScript スクリプトがあるため、これらのスクリプトをなるべく 1 つに結合することを勧めるアドバイスです。
その他、このツールがグレードを評価する観点には、Expires ヘッダーを追加しているか、gzip を使用しているか、ページの最後に JavaScript を配置しているか、JavaScript と CSS を縮小化しているか、重複する JavaScript および CSS コードが取り除かれているか、その他多数があります。図 6 に、YSlow によって生成された出力の例を示します。
図 6. YSlow によるレポートの例
アプリケーションのパフォーマンスを測定して、そのアプリケーションのパフォーマンスを向上させる必要があると判断したとします。皆さんはその場合、アプリケーションのソース・コードを詳しく調べて変更しなければならないと考えることでしょう。もちろん、ある点ではその作業が必要になる可能性は大いにありますが、アプリケーションのコードを一切変更することなく、JavaScript と Ajax のパフォーマンスを改善するいくつかの方法があります。
大規模な JavaScript アプリケーションでは、さまざまな機能を提供するために、多数の外部 JavaScript ソース・ファイルをページにロードすることがよくあります。おそらくこの場合、jQuery のようなフレームワークを使用しているのに加え、jQuery をベースに作成された数多くのプラグインを使用してさまざまな機能を追加しているはずです。さらに、アプリケーションで使われている独自の JavaScript コードが複数のファイルに分割された形で存在する可能性もあります。
JavaScript を複数の個別のファイルに分割することにメリットはありますが、パフォーマンスには重大な影響を与えます。Web アプリケーションにロードする外部 JavaScript ファイルごとに HTTP リクエストが実行されるため、スクリプトの負荷と実行時間が劇的に増加するからです。リクエストの数を減らすために、可能な場合には JavaScript ソース・ファイルをマージすることを是非ともお勧めします。特定のプラグインが 1 つのページでしか必要ないのであれば、当然、そのコードは 1 つのソース・ファイルに含めるべきではありません。実際、他のページで使用されないコードは、インライン・スクリプトとして組み込むべきなのではないかという議論もあります。何がなんでもすべてのコードを 1 つのファイルにマージするのはおそらく無理な話ですが、アプリケーションが行う HTTP リクエストの数が少なければ少ないほど、アプリケーションのロードにかかる時間は短くなります。
優れたプログラミング・プラクティスのガイドラインには、アプリケーションのコードを作成するときには、特定のスタイルに忠実に従うべきであると書かれています。このことは他の言語と同様、JavaScript にも当てはまりますが、問題は、コードに追加するホワイト・スペース、改行、コメントのすべてがスクリプトのファイル・サイズの増大につながり、アプリケーションのロード時間を長くするという点です。
JavaScript ファイルのサイズを小さくするために是非ともお勧めするのは、ファイルを本番環境に移す前に縮小化することです。縮小化には基本的に、ソース・コードから余計な部分を削除して、簡潔でサイズの小さなファイルにするという作業が伴います。縮小化によりファイル・サイズが小さくなる例として、この記事を執筆している時点での最新バージョンの jQuery のサイズは 155KB ありますが、縮小化するだけで 70.6KB まで小さくなります。これは約 55% もの縮小率です。
もちろん、ソース・コードの縮小化は有効な提案ですが、実際に縮小化するとなったら、どのような方法を採りますか?正気の人なら、手作業でコードを縮小化しようとは思わないはずです。有難いことに、自動で縮小化を行ってくれる一連の開発者向けツールがあります。なかでもよく使われているツールとしては、Douglas Crockford の JSMIN、Dean Edwards の Packer、そして Dojo ツールキットに組み込まれたコンプレッサーが挙げられます。個人的に私が気に入っているのは、Yahoo!® Inc が提供している YUI Compressor です。これらのツールに付いての詳細は、「参考文献」を参照してください。
gzip で JavaScript ソース・ファイルを圧縮する
前のセクションでは、JavaScript ソース・ファイルを縮小化することによって、そのサイズを劇的に小さくすることができると説明しました。実のところ、gzip を使ってファイルを圧縮することで、ファイルのサイズをさらに小さくすることができます。この場合の最善の方法は、Web サーバーに対し、JavaScript ファイルをクライアントに送信する前に gzip で圧縮するように指定することです。mod_deflate モジュールをインストールした Apache 2 を使用していて、JavaScript ファイルが同じ 1 つのディレクトリーに保存されている場合、gzip 圧縮を設定する .htaccess ファイルは、JavaScript ファイルと同じディレクトリーに作成することができます。.htaccess ファイルには、単に SetOutputFilter DEFLATE と指定します。
このようにして JavaScript ファイルを圧縮すると、サイズはかなり小さくなります。前のセクションで、jQuery ソース・コードを縮小化するとファイル・サイズが 155KB から 70.6KB (55% の縮小) になると説明しましたが、この縮小化されたファイルを gzip で圧縮すると、ファイル・サイズはわずか 24KB にまで減ります。縮小化と圧縮によって、ファイルは約 85% のサイズにまで小さくなります。縮小率はコードによって異なりますが、ファイル・サイズを極めて小さくできることは確かです。
Web ブラウザーによってコンテンツが必ずキャッシュに適切に入れられるようにすることは、重要なことです。例えば、Apache (mod_expires モジュールを適用) を使用していて、クライアントのキャッシュに JavaScript ファイルが 2 日間保持されるようにするには、JavaScript ファイルが保存されているディレクトリーに置かれた .htaccess ファイルに、リスト 11 のディレクティブを追加します (JavaScript ファイル専用のディレクトリーがあることが前提です。専用ディレクトリーがない場合には、ディレクティブを Apache 構成ファイルに追加することになります)。
リスト 11. JavaScript ファイルを 2 日間キャッシュに入れておくためのディレクティブ
ExpiresActive on ExpiresDefault "access plus 2 days" |
言うまでもなく、JavaScript ファイルをキャッシュに入れる設定にしたときの問題は、ファイルに変更を加えた場合です。クライアントがキャッシュの有効期限内にファイルにアクセスすると、ファイルが更新されていたとしても、更新されたバージョンではなく、キャッシュに入れられたバージョンのスクリプトを使用することになります。幸いこの問題は、スクリプトをロードするための <script> タグに記述したバージョン番号をクエリー・ストリングに指定して、クライアントに最新バージョンのスクリプトを強制的に取得させることで、回避することができます。このクエリー・ストリングは JavaScript コードにはまったく影響を及ぼしませんが、ブラウザーにとってクエリー・ストリングが指定されたファイルは、キャッシュに入れられたファイルとは完全に別のファイルであるため、最新バージョンのファイルをダウンロードします。もちろん、ファイルに変更を加えるたびにバージョン番号を増やすことが不可欠です。大規模なアプリケーションでは、このプロセスをビルド・スクリプトで自動化して、問題が起こらないようにする必要があります。
この記事では、最近の Web サイトおよびアプリケーションにおける JavaScript および Ajax のパフォーマンスの重要性について説明しました。最初に説明したように、効果的な JavaScript プログラミング手法によって、アプリケーションの応答性とロード時間に大きな差が出てきます。記事ではベスト・プラクティスの説明に続いて、既存のアプケーションのパフォーマンスをプロファイリング・ツールとネットワーク・アナライザー・ツールを使って測定する方法を紹介しました。そして最後に、単純ながらも効果的な手法でファイルのサイズを小さくし、アプリケーションが行う HTTP リクエストの数を減らすことによって、アプリケーションのソース・コードを変更しなくても、既存のアプリケーションのパフォーマンスを改善できることを説明しました。
学ぶために
- 「Ajax をマスターする、第 2 回: JavaScript と Ajax を使用して行う非同期要求」(Brett McLaughlin 著、developerWorks、2006年1月): Ajax と XMLHttpRequest オブジェクトを使用して、ユーザーにサーバーからのレスポンスを待たせることのないリクエスト/レスポンス・モデルを作成する方法を学んでください。
- 「モバイル Web 用の Ajax アプリケーションを作成する」(Michael Galpin 著、developerWorks、2010年3月): Ajaxを使用して特定のブラウザーに依存しないスマートフォン用 Web アプリケーションを構築する方法を学んでください。
- 「Where and when to use Ajax in your applications」(Jesse Skinner 著、developerWorks、2008年2月): Ajax を利用して、Web サイトを改善すると同時に不快なユーザー・エクスペリエンスを防ぐ方法を学んでください。
- 「Web 2.0 アプリケーションのパフォーマンスを改善する」(Jian Qiao Sun、Hua Pin Shen 共著、developerWorks、2009年12月): この記事では、さまざまなブラウザーのキャッシュ・メカニズムを探っています。
- 「Ajax パフォーマンスの分析」(Kristopher William Zyp 著、developerWorks、2008年4月): この記事では、Ajax で強化されたアプリケーションに潜むパフォーマンス問題を見つけ出して修正するツール・セットについて検討しています。
- 「JavaScript フレームワークの比較」(Joe Lennon 著、developerWorks、2010年2月): JavaScript 開発を大幅に強化するフレームワークの概要を説明しています。
- 『ハイパフォーマンスWebサイト――高速サイトを実現する14のルール』(Steve Souders 著、オライリー・ジャパン、2007年7月): Web サイトのパフォーマンス改善に役立つ 14 のツールを紹介しています。
- 『High Performance JavaScript』(Nicholas Zakas 著、O'Reilly Media、2010年3月): 開発中にパフォーマンスのボトルネックを排除するために役立つ手法と戦略を学んでください。
- Best Practices for Speeding Up Your Web Site: Yahoo! Developer Network のこの記事に、Web ページの高速化に役立つ 35 のベスト・プラクティスが挙げられています。
- Mozilla Developer Network にアクセスしてください。Web、モバイル、アドオン、アプリケーション、ラボを分野とするさまざまな開発者コミュニティーからなるネットワークです。
- この「JSON の紹介」記事で、JSON の構文を学んでください。
- developerWorks Web development ゾーンでは、多種多様な Web ベースのソリューションを話題にした記事を揃えています。
- developerWorks podcasts ではソフトウェア開発者のための興味深いインタビューや議論を聞くことができます。
製品や技術を入手するために
- LazyLoad ライブラリーは小さな (わずか 1,541 バイトに最小化)、依存関係のない JavaScript ライブラリーです。このライブラリーによって簡単に、外部 JavaScript および CSS ファイルをオンデマンドでロードできます。
- Firebug Web 開発ツールを入手してください。
- YUI Profiler は JavaScript を対象とした単純な非ビジュアル・コード・プロファイラーです。
- YSlow は、ハイパフォーマンス Web ページのための一連のルールに基づいて Web ページを分析し、パフォーマンスの改善方法を提案します。
- Fiddler は、コンピューターとインターネットとの間のすべての HTTP トラフィックをログに記録するWeb デバッグ・プロキシーです。
- YUI Compressor を使って JavaScript コードを縮小化してください。
- IBM ソフトウェアの試用版を使用して、次の開発プロジェクトを革新してください。ダウンロード、あるいは DVD で入手できます。
議論するために
- 今すぐ My developerWorks で自分のプロフィールを作って、JavaScript または Ajax に関するウォッチ・リストをセットアップしてください。My developerWorks とずっとつながっていられます。
- Web 開発に興味を持つ他の developerWorks メンバーを見つけてください。
- Web のトピックを専門とする developerWorks グループに参加して、知識を共有してください。
- Roland Barcia が彼のブログで Web 2.0 とミドルウェアについて語っています。
- developerWorks のメンバーが共有する Web 関連のブックマークをフォローしてください。
- Web 2.0 Apps フォーラムで、素早く回答を得てください。
- Ajax フォーラムで、素早く回答を得てください。
Joe Lennon は、アイルランド・コーク出身の 25 歳のモバイル・アプリケーション開発者兼 Web アプリケーション開発者です。勤務先の Core International では、Core のモバイル HR セルフサービス・ソリューションの開発リーダーを務めています。彼は技術に関する執筆活動にも熱心で、これまで DB2 pureXML、Flex、JavaScript、Adobe AIR、.NET、PHP、Python などを話題にした数多くの IBM developerWorks 記事を書いています。2009年の後半には彼の最初の著書、『Beginning CouchDB』が Apress から出版されました。余暇は、趣味の旅行、読書、ビデオ・ゲームを楽しんでいます。