HTML5 アプリのパフォーマンスを改善する

はじめに

HTML5 は、ウェブ アプリケーションの見た目を良くする優れたツールです。これは、アニメーションの領域では特に当てはまります。しかし、この新しい力には新たな課題も伴います。実のところ、こうした課題はそれほど新しいものではありません。親しみやすいデスクの隣の Flash プログラマーに、過去に同じような問題をどう克服したかを尋ねるのが合理的かもしれません。

いずれにせよ、アニメーションの作業では、アニメーションが滑らかであるとユーザーが認識することが非常に重要です。理解する必要があるのは、1 秒あたりのフレーム数を認知のしきい値を超えて増やすだけでは、アニメーションの滑らかさは実際には実現できないということです。残念ながら、私たちの脳はそれよりも賢いのです。これからわかることは、30 フレーム/秒(fps)のアニメーションは、途中で数フレームがドロップされた 60 fps よりもはるかに優れているということです。人はギザギザが好きじゃない。

この記事では、アプリケーションのエクスペリエンスを向上させるためのツールと手法をご紹介します。

戦略

決して、HTML5 を使用して驚くほど視覚に訴える優れたアプリを作成することはおすすめしません。

パフォーマンスをもう少し改善できる可能性があると思ったら、ここに戻って、アプリケーションの要素を改善する方法をお読みください。もちろん、最初のうち正しく行うべきこともあるかもしれませんが、生産性の妨げにならないようにしましょう。

HTML5 によるビジュアル フィデリティ++

ハードウェア アクセラレーション

ハードウェア アクセラレーションは、ブラウザの全体的なレンダリング パフォーマンスにとって重要なマイルストーンです。一般的なスキームでは、メイン CPU によって計算されるはずのタスクを、コンピュータのグラフィック アダプタのグラフィック プロセッシング ユニット(GPU)にオフロードします。これにより、パフォーマンスが大幅に向上し、モバイル デバイスのリソース消費量も削減できます。

ドキュメントのこれらの処理は GPU によって高速化できます。

  • 一般的なレイアウト合成
  • CSS3 の遷移
  • CSS3 3D 変換
  • 描画キャンバス
  • WebGL 3D 描画

キャンバスと WebGL のアクセラレーションは、特定のアプリケーションには当てはまらない特別な用途の機能ですが、最初の 3 つの側面は、ほぼすべてのアプリの動作速度向上に役立ちます。

加速できる対象

GPU アクセラレーションは、明確に定義された特定のタスクを専用ハードウェアにオフロードすることによって機能します。一般的なスキームでは、ドキュメントは複数の「レイヤ」に分割されます。これらのレイヤは、高速化されるページの要素とは不変です。これらのレイヤは、従来のレンダリング パイプラインを使用してレンダリングされます。GPU を使用して 1 ページにレイヤを合成し、その場でアクセラレーションできる「効果」を適用します。結果として、画面上でアニメーション化されるオブジェクトは、アニメーションの実行中にページを一度「再レイアウト」する必要がなくなる可能性があります。

そこで必要なのは、GPU アクセラレーション マジックを適用できるタイミングをレンダリング エンジンが簡単に識別できるようにする必要があることです。 たとえば次のようになります。

これは機能しますが、ブラウザは、人間にはスムーズなアニメーションとして認識されることを想定したものを実行していることを実際に認識していません。代わりに CSS3 の遷移を使用して同じ外観を実現した場合について考えてみましょう。

ブラウザがこのアニメーションを実装する方法は、デベロッパーには完全に表示されません。これは、ブラウザが GPU アクセラレーションなどの手法を適用して、定義された目標を達成できることを意味します。

Chrome には、GPU アクセラレーションのデバッグに役立つ 2 つの便利なコマンドライン フラグがあります。

  1. --show-composited-layer-borders は、GPU レベルで操作されている要素の周囲に赤い枠線を表示します。GPU レイヤ内で操作が行われたことを確認するのに便利です。
  2. --show-paint-rects: GPU 以外の変更がすべてペイントされ、再ペイントされたすべての領域の周囲に薄い枠線がスローされます。ブラウザによるペイント エリアの最適化の動作を確認できます。

Safari には、こちらで説明されているようなランタイム フラグがあります。

CSS3 の遷移

CSS 遷移を使用すると、スタイル アニメーションの作成が簡単になりますが、パフォーマンスの効率化にもつながります。CSS の遷移はブラウザによって管理されるため、アニメーションの忠実度が大幅に向上し、多くの場合、ハードウェアが高速化されます。現在、WebKit(Chrome、Safari、iOS)にはハードウェア アクセラレーションによる CSS 変換が搭載されていますが、他のブラウザやプラットフォームでもすぐに利用できるようになります。

transitionEnd イベントを使用して、スクリプトを効率よく組み合わせることもできますが、現時点では、サポートされているすべての遷移終了イベントをキャプチャするには webkitTransitionEnd transitionend oTransitionEnd を監視する必要があります。

多くのライブラリで、遷移を利用するアニメーション API が導入されました(存在する場合)。scripty2YUI 遷移jQuery のアニメーション強化

CSS3 翻訳

これまでに、ページ全体で要素の x 位置と y 位置をアニメーション化したことと思います。おそらく、インライン スタイルの left プロパティと top プロパティを操作したのでしょう。2D 変換では、translate() 機能を使用してこの動作を再現できます。

これを DOM アニメーションと組み合わせると、

<div style="position:relative; height:120px;" class="hwaccel">

  <div style="padding:5px; width:100px; height:100px; background:papayaWhip;
              position:absolute;" id="box">
  </div>
</div>

<script>
document.querySelector('#box').addEventListener('click', moveIt, false);

function moveIt(evt) {
  var elem = evt.target;

  if (Modernizr.csstransforms && Modernizr.csstransitions) {
    // vendor prefixes omitted here for brevity
    elem.style.transition = 'all 3s ease-out';
    elem.style.transform = 'translateX(600px)';

  } else {
    // if an older browser, fall back to jQuery animate
    jQuery(elem).animate({ 'left': '600px'}, 3000);
  }
}
</script>

Modernizr を使用して CSS 2D 変換と CSS 遷移の機能テストを行います。そうであれば、移動を使用して位置をシフトします。遷移を使用してアニメーション化する場合は、ブラウザがハードウェアでアクセラレーションできる可能性が高いと考えられます。ブラウザを正しい方向にさらに押し進めるために、上記の「CSS マジック ブレット」を使用します。

ブラウザの性能が低い場合は、jQuery にフォールバックして要素を移動します。Louis-Remi Babe による jQuery Transform ポリフィル プラグインを利用すると、これ全体を自動化できます。

window.requestAnimationFrame

requestAnimationFrame は Mozilla によって導入され、WebKit でも反復されています。これは、DOM/CSS ベース、<canvas> または WebGL ベースのいずれであっても、アニメーションを実行するためのネイティブ API を提供することを目的としています。ブラウザは、同時に実行されるアニメーションを 1 つのリフローとリペイント サイクルで最適化できるため、アニメーションの忠実度を高めることができます。たとえば、CSS 遷移や SVG SMIL と同期した JS ベースのアニメーションです。さらに、表示されていないタブでアニメーション ループを実行した場合、ブラウザは実行を継続しません。つまり、CPU、GPU、メモリの使用量が少なくなるため、バッテリー寿命が大幅に長くなります。

requestAnimationFrame の使用方法と使用する理由について詳しくは、Paul Irish の記事 requestAnimationFrame for smart animating をご覧ください。

プロファイリング

アプリケーションの速度を改善できるとわかったら、プロファイリングを掘り下げて、最適化によるメリットが最も大きい場所を見つけます。最適化は多くの場合、ソースコードの保守性に悪影響を及ぼすため、必要な場合にのみ適用してください。プロファイリングにより、コードのどの部分でパフォーマンスが向上した場合に最大のメリットが得られるかを把握できます。

JavaScript のプロファイリング

JavaScript プロファイラを使用すると、個々の関数の実行を開始してから終了するまでにかかる時間を測定することで、JavaScript 関数レベルでのアプリケーションのパフォーマンスの概要を把握できます。

関数の合計実行時間とは、関数を最初から最後まで実行するのに要した時間です。正味実行時間は、合計実行時間から、その関数から呼び出される関数の実行に要した時間を引いたものです。

関数の中には他の関数よりも頻繁に呼び出されるものがあります。プロファイラでは通常、すべての呼び出しの実行にかかった時間と、平均実行時間、最小実行時間、最大実行時間がわかります。

詳しくは、プロファイリングに関する Chrome デベロッパー ツールのドキュメントをご覧ください。

DOM

JavaScript のパフォーマンスは、アプリケーションがどの程度滑らかで応答性が高いかに大きく影響します。JavaScript プロファイラは JavaScript の実行時間を計測する一方で、DOM オペレーションの実行にかかった時間も間接的に計測することを理解しておくことが重要です。このような DOM 操作は、多くの場合、パフォーマンスの問題の根幹にあります。

function drawArray(array) {
  for(var i = 0; i < array.length; i++) {
    document.getElementById('test').innerHTML += array[i]; // No good :(
  }
}

たとえば、上記のコードでは、実際の JavaScript の実行に費やす時間はほとんどありません。drawArray 関数は、無駄な形で DOM とやり取りしているため、依然としてプロファイルに表示される可能性は大いにあります。

ヒントとアドバイス

匿名関数

匿名関数は、本質的にプロファイラに表示される名前がないため、プロファイルしにくい。これを回避するには、2 とおりの方法があります。

$('.stuff').each(function() { ... });

次のように書き換えます。

$('.stuff').each(function workOnStuff() { ... });

JavaScript が関数式の命名をサポートしていることは、あまり知られていません。これにより、プロファイラに完全に表示されるようになります。この解決策には問題が 1 つあります。それは、名前付き式を使用すると、実際には関数名が現在の字句スコープに入れられることです。他の記号を上書きする可能性があるため、ご注意ください。

長時間の関数のプロファイリング

長い関数があり、そのごく一部がパフォーマンスの問題を引き起こしているのではないかと疑うとします。どの部分に問題があるかを特定するには、次の 2 つの方法があります。

  1. 正しい方法: 長い関数が含まれないようにコードをリファクタリングします。
  2. 悪事を実行する方法:名前付き自己呼び出し関数の形式でステートメントをコードに追加します。少し注意すれば、セマンティクスは変更されず、関数の一部がプロファイラで個別の関数として表示されることになります。 js function myLongFunction() { ... (function doAPartOfTheWork() { ... })(); ... } プロファイリングが完了したら、以下の余分な関数を忘れずに削除してください。また、コードをリファクタリングするための出発点として使用することもできます。

DOM プロファイリング

最新の Chrome ウェブ インスペクタ開発ツールには、ブラウザで実行された低レベルのアクションのタイムラインを表示する新しい「タイムライン ビュー」が含まれています。この情報を使用して、DOM オペレーションを最適化できます。コードの実行中にブラウザが実行する必要がある「アクション」の数を減らすことを目標にする必要があります。

タイムライン ビューでは、膨大な量の情報が作成される場合があります。したがって、独立して実行できる最小限のテストケースを作成するようにしてください。

DOM プロファイリング

上の画像は、非常に単純なスクリプトのタイムライン ビューの出力を示しています。左側のペインにはブラウザによって実行されたオペレーションが時系列で表示され、右側のペインのタイムラインには個々のオペレーションにかかった実際の時間が表示されます。

タイムライン ビューの詳細Internet Explorer でプロファイリングを行う別のツールとして、DynaTrace Ajax Edition があります。

プロファイリング戦略

要素を取り出す

アプリケーションをプロファイリングする際は、速度低下を引き起こす可能性がある機能をできるだけ近くで特定してください。次に、アプリケーションのこれらの側面に関連するコードの一部のみを実行するプロファイルの実行を試みます。これにより、実際の問題に関係のないコードパスとプロファイリング データが混在することがなくなるため、プロファイリング データが解釈しやすくなります。アプリケーションの個々の側面の良い例を次に示します。

  1. 起動時間(プロファイラをアクティブにし、アプリケーションを再読み込みし、初期化が完了するまで待ってからプロファイラを停止する)
  2. ボタンのクリックとその後のアニメーション(プロファイラを起動、ボタンをクリック、アニメーションが完了するまで待機、プロファイラを停止する)
GUI プロファイリング

GUI プログラムでは、アプリケーションの適切な部分のみを実行することは、たとえば 3D エンジンのレイ トレーサーを最適化する場合よりも困難です。たとえば、ボタンをクリックしたときに発生する処理をプロファイリングする場合、途中で無関係なマウスオーバー イベントが発生し、結果の結論が下がる可能性があります。なるべく避けてください。

プログラム インターフェース

また、デバッガをアクティブにするプログラム インターフェースもあります。これにより、プロファイリングの開始時間と終了時間を細かく制御できます。

プロファイリングを開始するには、次のコマンドを使用します。

console.profile()

プロファイリングを停止する:

console.profileEnd()

反復性

プロファイリングを行うときは、結果を実際に再現できることを確認してください。そうして初めて、最適化によって実際に状況が改善されたかどうかを判断できます。また、関数レベルのプロファイリングは、コンピュータ全体のコンテキストで行われます。これは厳密な科学ではありません。個々のプロファイルの実行は、コンピュータで行われる他のさまざまな影響の影響を受ける可能性があります。

  1. アプリケーション内の無関係なタイマーで、他のものの測定中に作動します。
  2. 処理を実行するガベージ コレクタ。
  3. ブラウザの別のタブが同じ操作スレッドでハードな処理を行っている。
  4. パソコン上の別のプログラムが CPU を消費し、アプリケーションの動作が遅くなっている。
  5. 地球の重力場の突然の変化。

また、1 回のプロファイリング セッションで同じコードパスを複数回実行することも理にかなっています。そうすることで、上記の要素の影響が軽減され、遅い部分がよりはっきり目立ちます。

測定、改善、測定

プログラムの遅い部分を特定したら、実行の動作を改善する方法を考えてみましょう。コードを変更したら、もう一度プロファイリングを行います。結果に満足したら、次に進みます。改善が見られない場合は、変更をロールバックし、「害を及ぼさない」から放置するほうがよいでしょう。

最適化戦略

DOM インタラクションを最小限に抑える

ウェブ クライアント アプリケーションの速度を向上させる一般的なテーマは、DOM のインタラクションを最小限に抑えることです。JavaScript エンジンの速度は桁違いに向上していますが、DOM へのアクセスはそれほど高速ではありません。これは、決して実現しない非常に実用的な理由でもあります(画面へのレイアウトや描画などには時間がかかります)。

キャッシュ DOM ノード

DOM からノードまたはノードのリストを取得するときは常に、それらを後の計算(または次のループの反復処理だけ)で再利用できるかどうか検討してください。関連する領域で実際にノードを追加または削除しない限り、これがよくあるケースです。

プログラム開始前:

function getElements() {
  return $('.my-class');
}

申し込みの後:

var cachedElements;
function getElements() {
  if (cachedElements) {
    return cachedElements;
  }
  cachedElements = $('.my-class');
  return cachedElements;
}

属性値をキャッシュする

DOM ノードをキャッシュに保存するのと同じ方法で、属性の値もキャッシュに保存できます。ノードのスタイルの属性をアニメーション化するとします。その属性にアクセスできるのがユーザー(コードの該当部分)だけであることがわかっている場合は、反復処理のたびに最後の値をキャッシュに保存することで、その値を繰り返し読み取る必要がなくなります。

プログラム開始前:

setInterval(function() {
  var ele = $('#element');
  var left = parseInt(ele.css('left'), 10);
  ele.css('left', (left + 5) + 'px');
}, 1000 / 30);

変更後: js var ele = $('#element'); var left = parseInt(ele.css('left'), 10); setInterval(function() { left += 5; ele.css('left', left + 'px'); }, 1000 / 30);

DOM 操作をループの外に移動する

ループは、最適化すべきホットポイントになることがよくあります。実際の数値処理を DOM の操作に切り離す方法を考えてみてください。計算を行ってから、すべての結果を一度に適用することは可能です。

プログラム開始前:

document.getElementById('target').innerHTML = '';
for(var i = 0; i < array.length; i++) {
  var val = doSomething(array[i]);
  document.getElementById('target').innerHTML += val;
}

申し込みの後:

var stringBuilder = [];
for(var i = 0; i < array.length; i++) {
  var val = doSomething(array[i]);
  stringBuilder.push(val);
}
document.getElementById('target').innerHTML = stringBuilder.join('');

再描画とリフロー

前述のように、DOM へのアクセスは比較的遅く、コードが DOM 内の関連する何かを最近変更したため、再計算が必要な値を読み取っていると非常に遅くなります。そのため、DOM に対する読み取りと書き込みのアクセスを混在させるのは避ける必要があります。コードを常に次の 2 つのフェーズに分けるのが理想的です。

  • フェーズ 1: コードに必要な DOM 値を読み取る
  • フェーズ 2: DOM を修正する

次のようなパターンはプログラムしないでください。

  • フェーズ 1: DOM 値を読み取る
  • フェーズ 2: DOM を修正する
  • フェーズ 3: さらに読む
  • フェーズ 4: DOM を別の場所で変更する

プログラム開始前:

function paintSlow() {
  var left1 = $('#thing1').css('left');
  $('#otherThing1').css('left', left);
  var left2 = $('#thing2').css('left');
  $('#otherThing2').css('left', left);
}

申し込みの後:

function paintFast() {
  var left1 = $('#thing1').css('left');
  var left2 = $('#thing2').css('left');
  $('#otherThing1').css('left', left);
  $('#otherThing2').css('left', left);
}

このアドバイスは、1 つの JavaScript 実行コンテキスト内で行われるアクションについて検討する必要があります。(イベント ハンドラ内、インターバル ハンドラ内、ajax レスポンスの処理時など)。

上記の関数 paintSlow() を実行すると、次の画像が作成されます。

paintSlow()

より高速な実装に切り替えると、次のような画像になります。

実装の高速化

これらの画像は、コードが DOM にアクセスする方法の順序を変更することで、レンダリング パフォーマンスが大幅に向上することを示しています。この場合、元のコードで同じ結果を得るには、スタイルを再計算して、ページを 2 回レイアウトする必要があります。同様の最適化を基本的にすべての「現実世界」のコードに適用すると、劇的な結果が得られます。

詳細: Rendering: repaint, reflow/relayout, restyle(著者: Stoyan Stefanov)

再描画とイベントループ

ブラウザでの JavaScript の実行は、「イベント ループ」モデルに従います。デフォルトでは、ブラウザは「アイドル」状態です。この状態は、ユーザー操作からのイベントや、JavaScript タイマーや Ajax コールバックなどによって中断される場合があります。そのような割り込みポイントで JavaScript が実行された場合、ブラウザは通常、画面が再描画されるまで終了を待ちます(JavaScript の実行時間が極端に長い場合や、JavaScript の実行を効果的に中断するアラートボックスなどは例外です)。

結果

  1. JavaScript アニメーション サイクルの実行に 1/30 秒以上かかる場合、JavaScript の実行中にブラウザが再描画を行わないため、スムーズなアニメーションを作成できません。ユーザー イベントも処理することが想定される場合は、はるかに高速である必要があります。
  2. JavaScript の処理を少し遅らせると便利な場合があります。例: setTimeout(function() { ... }, 0)。これにより、イベントループが再びアイドル状態になり次第、すぐにコールバックを実行するようにブラウザに効果的に指示できます(一部のブラウザでは実質的に 10 ミリ秒以上待機します)。これにより、時間的に非常に近い 2 つの JavaScript 実行サイクルが作成されることに注意する必要があります。どちらの場合も、画面の再ペイントがトリガーされ、ペイントに費やされる全体の時間が 2 倍になる可能性があります。実際に 2 回のペイントをトリガーするかどうかは、ブラウザのヒューリスティックによって決まります。

通常バージョン:

function paintFast() {
  var height1 = $('#thing1').css('height');
  var height2 = $('#thing2').css('height');
  $('#otherThing1').css('height', '20px');
  $('#otherThing2').css('height', '20px');
}
再描画とイベントループ

遅延を追加しましょう。

function paintALittleLater() {
  var height1 = $('#thing1').css('height');
  var height2 = $('#thing2').css('height');
  $('#otherThing1').css('height', '20px');
  setTimeout(function() {
    $('#otherThing2').css('height', '20px');
  }, 10)
}
Delay

遅延バージョンでは、ページに対する 2 回の変更が 1/100 秒にすぎないにもかかわらず、ブラウザが 2 回ペイントしていることがわかります。

遅延初期化

ユーザーは、読み込みが速く、応答性が高いと感じられるウェブアプリを求めています。ただし、ユーザーが何をしているかによって、遅いと感じるしきい値は異なります。たとえば、アプリはマウスオーバー イベントで大量の計算を実行すべきではありません。ユーザーがマウスを動かし続けている間に、ユーザー エクスペリエンスが低下する可能性があるためです。しかし、ユーザーはボタンをクリックした後、少しの遅延を受け入れることに慣れています。

したがって、初期化コードをできるだけ遅く(たとえば、ユーザーがアプリケーションの特定のコンポーネントをアクティブにするボタンをクリックしたとき)実行されるように移動することが合理的です。

変更前: js var things = $('.ele > .other * div.className'); $('#button').click(function() { things.show() });

変更後: js $('#button').click(function() { $('.ele > .other * div.className').show() });

イベントの委任

イベント ハンドラをページ全体に分散させる作業には比較的長い時間がかかります。また、要素が動的に置換されると新しい要素にイベント ハンドラを再アタッチする必要が生じると、面倒な作業になることがあります。

この場合の解決策は、イベント委任と呼ばれる手法を使用することです。個々のイベント ハンドラを要素にアタッチするのではなく、多くのブラウザ イベントのバブリング特性を利用するために、実際にイベント ハンドラを親ノードにアタッチし、イベントのターゲット ノードをチェックして、そのイベントが対象かどうかを確認します。

jQuery では、これを次のように簡単に表現できます。

$('#parentNode').delegate('.button', 'click', function() { ... });

予定の委任を使用すべきでない場合

逆のケースも考えられます。たとえば、イベントの委任を使用していて、パフォーマンスに問題がある場合です。基本的に、イベントを委任すると、初期化時間を一定にすることができます。ただし、イベントが重要かどうかをチェックする費用は、そのイベントを呼び出すたびに支払う必要があります。特に「マウスオーバー」や「マウスムーブ」のように頻繁に発生するイベントでは、コストが大きくなる可能性があります。

一般的な問題と解決策

$(document).ready の作業に時間がかかる

Malte からの個人的なアドバイス: $(document).ready では何もしないでください。ドキュメントを最終的な形式で提出してみます。イベント リスナーの登録は許可されていますが、ID セレクタとイベント委任(あるいはその両方)のみを使用できます。「マウスムーブ」などの負荷の高いイベントの場合は、必要になるまで登録を遅らせます(関連する要素でのマウスオーバー イベント)。

実際のデータを取得するために Ajax リクエストを行うなど、本当に必要な場合は、適切なアニメーションを表示します。アニメーション GIF などの場合、アニメーションをデータ URI として含めることもできます。

ページに Flash ムービーを追加したので、何もかもが遅くなる

ページに Flash を追加すると、ウィンドウの最終的なレイアウトについてブラウザと Flash プラグインの間で「交渉」する必要があるため、常にレンダリングが少し遅くなります。ページへの Flash の使用を完全に回避できない場合は、Flash の「wmode」パラメータを「window」の値(デフォルト)に設定してください。これにより、HTML 要素と Flash 要素を合成する機能が無効になります(Flash ムービーの上にある HTML 要素は表示できません。また、Flash ムービーを透明にすることはできません)。不便かもしれませんが、パフォーマンスは劇的に向上します。たとえば、youtube.com で、メインのムービー プレーヤーの上にレイヤが配置されないように注意してあることをご確認ください。

localStorage にデータを保存しているのに、アプリがスムーズに再生されない

localStorage への書き込みは、ハードディスクのスピンアップを伴う同期オペレーションです。アニメーションの実行中に「長時間実行」の同期処理は行わないようにする必要があります。localStorage へのアクセスをコード内の、ユーザーがアイドル状態でアニメーションが実行されないことを確実にする場所に移動します。

jQuery セレクタへのポイントのプロファイリングが非常に遅い

まず、document.querySelectorAll を通じてセレクタを実行できることを確認します。これは JavaScript コンソールでテストできます。例外がある場合は、JavaScript フレームワークの特別な拡張機能を使用しないようにセレクタを書き換えます。これにより、最新のブラウザではセレクタが桁違いに高速化されます。

それでも問題が解決しない場合や、最新のブラウザで速度を上げたい場合は、次のガイドラインに従ってください。

  • セレクタの右側はできるだけ具体的に指定します。
  • セレクタの右端には、使用頻度の低いタグ名を使用します。
  • それでも解決しない場合は、ID セレクタを使用できるように書き換えることを検討する

こうした DOM 操作はすべて、

大量の DOM ノードの挿入、削除、更新は、非常に遅くなる場合があります。これは通常、html の長い文字列を生成し、domNode.innerHTML = newHTML を使用して古いコンテンツを置き換えることで最適化できます。これは保守性に悪影響を及ぼす可能性があり、IE でメモリリンクが作成される可能性があるため、注意してください。

もう 1 つのよくある問題は、初期化コードで大量の HTML が作成される可能性があることです。たとえば、セレクト ボックスを多数の div に変換する jQuery プラグインは、UX のベスト プラクティスを無視してユーザーが求めていたデザインであるためです。本当にページを高速化したいのであれば、それは絶対に行わないでください。代わりに、すべてのマークアップをサーバー側から最終的な形式で提供してください。ここでも多くの問題があるため、この速度に見合う価値があるかどうかをよく考えてください。

ツール

  1. JSPerf - JavaScript の小さなスニペットのベンチマーク
  2. Firebug - Firefox でのプロファイリング
  3. Google Chrome デベロッパー ツール(Safari では WebInspector として利用可能)
  4. DOM Monster - DOM パフォーマンスの最適化
  5. DynaTrace Ajax エディション - Internet Explorer でのプロファイリングとペイントの最適化

関連情報

  1. Google の速度
  2. jQuery のパフォーマンスに関する Paul Irish 氏
  3. Extreme JavaScript Performance(スライド資料)