レベル: 初級 Roland Barcia (barcia@us.ibm.com), Senior Technical Staff Member, IBM
2008年 2月 27日 Ajax アプリケーションはいったんロードされると、それ以降はページ全体を再レンダリングするというオーバーヘッドを避け、データとコンテンツの小フラグメントを取得することで、パフォーマンスを向上させます。しかし大抵はそうすることによって、アプリケーションの初期ダウンロード時間が長くなってしまいます。この記事では、Dojo アプリケーションの初期ダウンロード時間を短縮すると同時に、素晴らしいパフォーマンスを実現するための方法を検討します。
IBM WebSphere 開発者向け技術ジャーナルより。
必要最小限に抑えること
Ajax (Asynchronous JavaScript and XML) アプリケーションは Web アプリケーションのパフォーマンスを向上させることが可能です。Ajax アプリケーションはいったんロードされると、それ以降はページ全体を再レンダリングするオーバーヘッドが生じないようにするために、データとコンテンツの小フラグメントを取得するという方法を採るからです。ただしその代償として、大抵の場合、アプリケーションの初期ダウンロード時間が長くなってしまいます。
私はこれまで数年間、Dojo アプリケーションに取り組んできました。今では IBM® WebSphere® Application Server Feature Pack for Web 2.0 と Project Zero の両方に、拡張機能で付加価値を付ける Dojo Toolkit の IBM 配布が含まれるようになっています。しかし Dojo Toolkit が持つモジュール性という特質により、Dojo Toolkit の初期ロードには相当な時間がかかることがあります。場合によっては、使用するモジュールごとにいくつかの JavaScript™、HTML および CSS ファイルをダウンロードしなければならないためです。このことが、各モジュールのサイズだけにはとどまらない大量のネットワーク IO を生じさせているのです。
一般に、プログラマーがデバッグとコーディングを容易にするためにはモジュール性が必要となりますが、アプリケーションがいったん作成されてしまえば、モジュールであることは重要でも必要でもなくなります。この点を利用して、Dojo アプリケーションの初期ダウンロード時間を短縮する方法がいくつかあります。
Dojo のビルドおよびパッケージ・システムを使用すること
Dojo Toolkit に備わっているパッケージ化圧縮技術は、アプリケーションで使用するコードを 1 つのファイルにパッケージ化し、さらにそのファイルを Dojo ShrinkSafe という圧縮技術によって圧縮して最小のサイズにします。この技術は、特にアプリケーションの初期ダウンロードのパフォーマンスを大幅に向上させるため、大抵の Dojo アプリケーションのデプロイメントには、この技術を使用してください。それにはまず、アプリケーションのプロファイルを作成し、アプリケーションで使用している Dojo コンポーネントをそのプロファイルの中で指定します。リスト 1 はプロファイルの一例です。
リスト 1. サンプル・プロファイル
dependencies ={
layers: [
{
name: "example.js",
dependencies: [
"dojo.*",
"dojo.parser",
"dijit.dijit",
"dijit.Declaration",
"dijit.layout.LayoutContainer",
"dojox.layout.ContentPane",
"dijit.Toolbar",
"dijit.layout.AccordionContainer",
"my.widget.Super"
]
}
],
prefixes: [
[ "dijit", "../dijit" ],
[ "my", "/myWidgets"],
[ "dojox", "../dojox" ]
]
}; |
プロファイルを作成した上でコマンドライン・ビルド・ツールを実行し、各種のオプションを指定したプロファイルを渡します。すると、Dojo ビルドはアプリケーションに必要なすべてのコード (JavaScript、HTML、CSS を含む) を 1 つのファイルに配置して、そのファイルを圧縮します。この方法を使った結果、例えばアプリケーションの初期ダウンロード・サイズでの IO 呼び出しが 200 回だったのが、たった 2 回から 3 回に減りました。また、全体のサイズは約 60% に縮小されました。Dojo のビルドおよびパッケージ・システムの使用方法についての developerWorks のチュートリアルがまもなく公開される予定ですが、それまでは Dojo の Web サイトでパッケージ・システムとカスタム・ビルドについての詳細を調べてください。
Dojo コンテンツを遅延ロードでキャッシュに入れること
初期ダウンロード・サイズを大幅に減らすことができる別のプラクティスは、ページのコンテンツ部分を遅延ロードし、ダウンロードの完了時にキャッシュに入れることです。アプリケーションに最初にアクセスしたときにすべてをロードするよりも、最初はアプリケーションの一部のみをロードしたほうがよいこともあります。サイトにアクセスしたユーザーが Web アプリケーションの特定の部分には一度も触れないことは大いに有り得ます。その場合、結局手を付けずに終わったセクションをダウンロードするために費やされた時間は無駄になります。したがって、アプリケーションで使用されないと考えられる部分をダウンロードする必要はありません。その上、第一印象は非常に重要です。最初にアクセスしたときにホームページがすぐに表示されなければ、ユーザーは早々に立ち去ってしまうということです。
通常は、初期メニューを表示するレイアウトをロードした後に、ホーム・コンテンツを取得する必要があります。一般的な Dojo アプリケーションは通常、複数のレイアウト要素で構成されています。リスト 2 を見てください。
リスト 2. レイアウト
<body class="tundra">
<div dojoType="dijit.layout.LayoutContainer"
layoutChildPriority="top-bottom"
id="main"
class="layout" >
<div dojoType="dijit.layout.ContentPane"
layoutAlign="top" class="banner">
<h2>Electronic and Movie Depot !!</h2>
</div>
<div dojoType="dijit.layout.ContentPane"
layoutAlign="top" class="menu">
<div dojoType="dijit.Toolbar" id="mainMenuBar">
<div dojoType="dijit.form.Button"
id="productListMenu"
onclick="showItem('productList',
'product/product.html');">
Shopping
</div>
<div dojoType="dijit.form.Button"
id="orderListMenu" onclick="showItem('orderPage',
'cart/cart.html');">
Shopping Cart
</div>
</div>
</div>
<div dojoType="dijit.layout.ContentPane"
class="mainArea"
id="center" layoutAlign="client">
<div dojoType="dojox.layout.ContentPane"
executeScripts="true" id="productList"
style="display:none">
</div>
<div dojoType="dojox.layout.ContentPane"
executeScripts="true"
id="orderPage"
style="display:none">
</div>
</div>
</div>
</body> |
リスト 2 を見ると、いくつかの点がわかります。私はまず、HTML フラグメントを特定のコンテンツにロードする単純なメソッドを作成しました。また、dijit のデフォルト・コンテンツ・ペインではなく dojox.layout.ContentPane を使用することにします。拡張コンテンツ・ペインでは、この領域をロードするときに JavaScript を実行することができます。このようにすれば、HTML コンテンツの遅延ロードだけでなく、関連するロジックの遅延ロードも可能になります。私が作成したユーティリティー・メソッドの実装は、リスト 3 のとおりです。
リスト 3. 遅延ロード
var loaded = new dojox.collections.Dictionary();
function hideAll()
{
console.debug("Hiding other content");
var ids = loaded.getKeyList();
console.debug("Getting ID -> " + ids);
console.debug("List is Array");
for (var id in ids) {
console.debug("Getting section -> " + ids[id]);
var section = dijit.byId(ids[id]);
console.debug("Got Section -> " + section);
if (section) {
console.debug("setting DOM");
section.domNode.style.display = "none";
}
}
console.debug("Content is hid");
}
function showItem(key,template)
{
hideAll();
console.debug("Show Item -> " + key);
var item = dijit.byId(key);
console.debug(item);
if (item)
{
if(!loaded.contains(key))
{
item.setHref(template);
item.refresh();
loaded.add(key,template);
}
item.domNode.style.display ="block";
}
}
/**
* Load Default page
*/
dojo.addOnLoad(function loadDefault()
{
console.debug("Loading initial state");
showItem('productList','product/product.html');
}); |
リスト 3 では、showItem が呼び出されると、本文に表示されるすべてのコンテンツが非表示になります。次に HTML がロード済みであるかどうかをチェックし、まだロードされていない場合はテンプレートをダウンロードして、Dojo ディクショナリー内のキャッシュに入れます。次回、このページを要求すると、ページにはこの領域しか表示されないことになります。また、dojo.addOnLoad メソッドを使ってデフォルト・ページもロードしています。
何もかもを dijit にしないこと
主なアプリケーション・コンポーネントから dijit (Dojo ウィジェット) を作り出すという考えは、とても魅力的なものです。一例として、リスト 4 に Dojo の dijit を作成したサンプル・アプリケーションを示します。
リスト 4. ダウンロード時間を短縮可能な dijit としてのアプリケーション・コンポーネント
<div dojoAttachPoint = "registerId"
dojoType="registration:RegistrationWidget"
style="display:none"
>
</div>
<div dojoAttachPoint = "datacenterId"
dojoType="datacenters:DataCentersWidget"
inputTopic="no.show.datacenter"
style="display:none">
</div> |
リスト 4 では、アプリケーション・コンポーネントのそれぞれが dijit の中にラップされ、すべての dijit はサブ dijit で構成されています。そこで、以下のようにアプリケーション全体をスーパー dijit としてロードするという考えにまで至るはずです。
<div id = "layout" dojoType="layout:EEFLayoutWidget" class="layoutDef"></div>
しかしこの場合の問題は、すべてのウィジェットをビルドの一部として組み込む場合は特に、コンテンツの遅延ロードが無意味になる (あるいは極めて複雑になる) という点です。私が最善だと思う方法は、UI コンポーネント (データ・グリッド、特殊 ComboBox、特殊テキスト域) に対して dijit を作成し、それからこれらの dijit を使用する簡潔な HTML テンプレートをロードする方法です。
このように、優れたガイドラインとプラクティスに従えば、アプリケーションのダウンロードにかかる時間を短縮しながらも、Dojo がもたらすパフォーマンス上の利点を生かすことができます。
参考文献 学ぶために
製品や技術を入手するために
議論するために
著者について
記事の評価
|