ビルド関連のパフォーマンス・チューニング
「ビルドでパフォーマンス・チューニング(1)」ではビルドの意味やビルド・システムの基本的な使い方について解説しました。ビルドによってリリース版として適したモジュールを生成するだけでもコード・サイズやサーバーへのリクエスト回数の改善でパフォーマンスが劇的に向上します。しかし、ビルドに関係することだけでもまだまだパフォーマンス向上のためにできることがあります。そこで、ここではより高度なビルド関連のパフォーマンス・チューニングのテクニックを紹介します。
コードの遅延読み込み
ビルドをしたにもかかわらず依然としてコード・サイズが大きく、起動時のパフォーマンスが問題になることがあります。そのようなとき、アプリケーションによってはコードの遅延読み込みが効果的な場合があります。
コードの遅延読み込みとは
コードをそれが必要になった時点ではじめて動的にロードすることを遅延読み込み、あるいは遅延ロード(lazy load)と呼びます。それにより、特に起動時にロードするコード量を減らし、起動時間を短縮するといったパフォーマンス改善を図ることができます。
例えば、前述のプロファイルの例では、myCalendarとmyDatePickerを別レイヤーに分けました。もちろん、myCalendarレイヤーにmyDatePickerも依存モジュールとして含めてしまってもよかったのですが、カレンダー・ウィジェット(myCalendar)を使う場合でも、そこから開くことのできる日付選択ウィジェット(myDatePicker)は必ず使うとは限りません。従って、ユーザーの操作次第では使われないかもしれないコードを毎回ロードするのは無駄なので、要求があったときのみ動的にロードしようというのが発想です。
dojoによる遅延読み込み
dojoでモジュールの動的な読み込みを行う方法はいたってシンプルで、通常各モジュールのファイルの先頭に記述するdojo.require文を、実行時に実行されるコードとして書くだけです。例えば、カレンダー・ウィジェットで日付選択ボタンを押したときに呼ばれる関数をshowDatePicker()とすると、次のように記述できます。
showDatePicker: function(){ dojo.require("acme.widget.myDatePicker"); var picker = new acme.widget.myDatePicker(); .... };
はじめてshowDatePicker()が呼び出されると、dojo.require文によってmyDatePicker.jsがロードされ、その次の行で直ちにmyDatePickerクラスを使用することができます(※1)。2回目以降の呼び出しではmyDatePickerはすでにロード済みであるため、dojo.requireは何もせずにリターンします。
dojoのデフォルト・ローダーを使う限り、dojo.requireは同期(sync)モードのXHR(XMLHttpRequest)呼び出しによりモジュールをロードするため、dojo.require呼び出しから戻ってきた直後にはそのモジュールのロードと評価は完了しており、安全に使用することができます。
一方、dojoには非同期(async)ロードを行うXDローダーと呼ばれるローダーも提供されており、ビルド時のオプションにより利用することができます。ただし、XDローダーを使用した場合は、dojo.require呼び出しから戻っても、非同期で行われるモジュールのロードが完了している保証はないため、リスト1のコードは動作しません。
ビルド時の問題点
リスト1のコードには一つ問題があります。ソース・コードのまま実行している限りでは意図した通りに動作します。しかし、ビルドをすると、機能的には動作しますが、肝心の遅延読み込みが行われません。理由は、ビルド時にビルド・ツールが依存関係を解析する過程でshowDatePicker()内のdojo.require文も見つけてしまうため、カレンダー・ウィジェットのレイヤーにmyDatePickerモジュールも自動的に取り込まれてしまうためです。これを防ぐには、dojo.require文を次のようにして記述します。これにより、ビルド・ツールはmyDatePickerを依存モジュールとして認識しなくなります(※2)。
showDatePicker: function(){ dojo["require"]("acme.widget.myDatePicker"); var picker = new acme.widget.myDatePicker(); .... };
一見、奇妙な書き方ですが、JavaScriptではオブジェクトのアクセス方法に関してa.bとa["b"]は等価であるため、コードとしては元の書き方と等価です。しかし、ビルド・ツールはソース・コードを文字列としてスキャンし、パターン・マッチングでdojo.require文を探しているため、ビルド・ツールに解析をスキップさせる効果があります。