ヒントとテクニック

  • リビジョンの URL スラッグ: Mozilla/Firefox_OS/Apps/Tips_and_techniques
  • リビジョンのタイトル: ヒントとテクニック
  • リビジョンの ID: 349431
  • 作成日:
  • 作成者: Yoshino
  • 現行リビジョン いいえ
  • コメント added tags

このリビジョンの内容

{{B2GMain()}}

Open Web Apps の開発に関するヒントやテクニック、中でも特に Firefox OS を対象としたアプリに関する最高の情報源のひとつは、Firefox OSGaia の素晴らしい開発チームです。このページでは、そうした情報の一部を紹介します。どうぞご活用ください。

インストールと更新

アプリのインストール、更新プロセス、アプリケーションマニフェストなどに関するヒントと回避策をいくつか挙げます。

アプリキャッシュマニフェストを用意してあるのにアプリが更新されない

今のところ Firefox OS では、アプリの {{HTMLElement("html")}} 要素に {{htmlattrxref("manifest", "html")}} 属性を指定しない限り、アプリキャッシュマニフェストを使ったインストール済みアプリケーションの更新が正しく行われません。この問題は今後修正されますが ({{bug(834338)}} 参照)、当面は属性を指定するだけでアプリは期待通りに更新されます。

パフォーマンス

ここでは、端末のハードウェアを停止させることなく快適に動作する Web アプリを作成しようとする皆さんの役に立つアドバイスをまとめました。

CSS アニメーションとトランジションを使う

一部のライブラリが提供する animate() 関数は、まだ様々なパフォーマンスの悪い技術 (例えば {{domxref("window.setTimeout()")}} や top/left 位置指定) を使っている可能性がありますので、代わりに CSS アニメーション を使いましょう。たいていの場合、実際には CSS トランジション を使えば、やりたいことを実現できます。ブラウザはそうしたエフェクトを最適化し、GPU を使用してプロセッサのパフォーマンスへの影響を最小限に抑えつつスムーズに処理するように設計されていますので、問題なく動作するはずです。もうひとつのメリットは、CSS で標準的な構文を使い、アプリの他のデザインとともにそれらのエフェクトを定義できるという点です。

CSS アニメーションでは、キーフレーム を使って、非常に細かくエフェクトを調整することが可能です。アニメーションの表示中に実行されたイベントを監視し、そのプロセスの設定点で実行すべき他のタスクを処理することさえ可能です。{{cssxref(":hover")}}、{{cssxref(":focus")}}、{{cssxref(":target")}} といった疑似クラスを使用して、あるいは親要素へ動的にクラスを追加・削除することで、そうしたアニメーションを簡単に実行することができます。

JavaScript でアニメーションを動的に生成あるいは変更したい場合は、James Long が作成した CSS-animations.js というシンプルなライブラリを使うこともできます。

CSS トランスフォームを使う

要素の位置や比率などを調整したいときは、絶対配置を変更し、その数値を自分自身で計算する代わりに、{{cssxref("transform")}} CSS プロパティを使いましょう。その理由は、先ほどと同じくハードウェアアクセラレーションです。ブラウザはそうしたタスクを GPU 上で処理し、他のことを CPU に処理させることが可能です。

さらにトランスフォームは、他の方法ではおそらく実現できない機能を提供します。要素を 2 次元空間内で移動させるだけでなく、3 次元空間内の移動や、ゆがみ、回転といった処理を行えるのです。Paul Irish が、パフォーマンスの観点から translate() のメリットに関する綿密な分析を行っています。ただ、一般的には、CSS アニメーションを使っても同じメリットを得られます。実現したいエフェクトのために適切なツールを使用し、最適化はブラウザに任せましょう。また、要素の位置を変更するには、簡単に拡張可能な方法を使用できます。topleft の座標変更でそうした移動をエミュレートするとなると、コードを大量に追加しなければならないでしょう。もうひとつのメリットは、{{HTMLElement("canvas")}} 内でも使えるという点です。

setInterval() の代わりに requestAnimationFrame() を使う

{{domxref("window.setInterval()")}} の呼び出しは、現状では実行可能かどうか定かではない推定フレームレートでコードを実行します。また、ブラウザが実際には描画していない、つまりビデオハードウェアが次の表示サイクルに達していないときにも結果を描画させようとします。これはプロセッサ時間の無駄遣いです (ユーザの端末のバッテリー寿命を縮める結果にもなります)。

代わりに {{domxref("window.requestAnimationFrame()")}} を使ってみましょう。これは、ブラウザが実際にアニメーションの次のフレームのビルドを開始する準備が整うまで待機し、ハードウェアが実際には何も描画しようとしていない場合は実行されません。この API が持つもうひとつのメリットは、アプリが画面上に表示されていないとき (バックグラウンドのタブにあって他のタスクが実行されている場合など) はアニメーションが実行されないということです。これはバッテリー消費を抑え、ユーザの間で悪評が立つのを防ぐことにもなります。

イベントを即時に実行する

保守的な、アクセシビリティに考慮した Web 開発者として、キーボード入力への対応という付加的なメリットを備えていることから、私たちはクリックイベントを気に入っています。モバイル端末上では、それらは非常に遅くなります。代わりに {{event("touchstart")}} や {{event("touchend")}} を使うべきです。その理由は、アプリの動作が緩慢であると感じさせるような遅延が発生しないということです。タッチ対応を始めにテストする場合、アクセシビリティも犠牲にしてはいけません。例えば、Financial Times はそのために、一般公開もされている fastclick というライブラリを使用しています。

インタフェースをシンプルに保つ

HTML5 アプリに見られる大きなパフォーマンス問題のひとつに、多くの DOM 要素を移動させることで、特にグラデーションやドロップシャドウを多用している場合、あらゆる動作が緩慢になるということが挙げられました。デザインをシンプルにし、ドラッグ&ドロップ処理を行う場合は仮の要素を移動させることで、そうした問題を大幅に改善することが可能です。

例えば、アプリ内に要素の長大なリスト (ツイート一覧など) がある場合、それらをすべて移動させようとしてはいけません。その代わりに、表示されているツイートと、その前後にある多少のツイートだけを DOM ツリー内に保持することも可能でしょう。残りは隠すか削除しましょう。DOM へアクセスする代わりに JavaScript オブジェクト内にデータを保持することで、アプリのパフォーマンスを大幅に向上させることができます。表示を、データそのものではなく、データの表現として考えましょう。これは本来の HTML をソースとして使えないということではありません。ユーザがツイートを呼んで 10 要素分スクロールしたら、表示されていない 100 要素を移動する代わりに、結果リスト内の位置によって最初と最後のコンテンツを変更するのです。同じテクニックはスプライト処理を行うゲームにも当てはまります。要素が画面上にない場合は、それらにポーリングを行う必要はありません。代わりに、画面外に出た要素を画面内に入る要素として再利用すれば良いのです。

このリビジョンのソースコード

<p>{{B2GMain()}}</p>
<p><a href="/ja/docs/Apps">Open Web Apps</a> の開発に関するヒントやテクニック、中でも特に Firefox OS を対象としたアプリに関する最高の情報源のひとつは、<a href="/ja/docs/Mozilla/Firefox_OS">Firefox OS</a> と <a href="/ja/docs/Mozilla/Firefox_OS/Gaia">Gaia</a> の素晴らしい開発チームです。このページでは、そうした情報の一部を紹介します。どうぞご活用ください。</p>
<h2 id=".E3.82.A4.E3.83.B3.E3.82.B9.E3.83.88.E3.83.BC.E3.83.AB.E3.81.A8.E6.9B.B4.E6.96.B0">インストールと更新</h2>
<p>アプリのインストール、更新プロセス、アプリケーションマニフェストなどに関するヒントと回避策をいくつか挙げます。</p>
<h3 id=".E3.82.A2.E3.83.97.E3.83.AA.E3.82.AD.E3.83.A3.E3.83.83.E3.82.B7.E3.83.A5.E3.83.9E.E3.83.8B.E3.83.95.E3.82.A7.E3.82.B9.E3.83.88.E3.82.92.E7.94.A8.E6.84.8F.E3.81.97.E3.81.A6.E3.81.82.E3.82.8B.E3.81.AE.E3.81.AB.E3.82.A2.E3.83.97.E3.83.AA.E3.81.8C.E6.9B.B4.E6.96.B0.E3.81.95.E3.82.8C.E3.81.AA.E3.81.84">アプリキャッシュマニフェストを用意してあるのにアプリが更新されない</h3>
<p>今のところ Firefox OS では、アプリの {{HTMLElement("html")}} 要素に {{htmlattrxref("manifest", "html")}} 属性を指定しない限り、アプリキャッシュマニフェストを使ったインストール済みアプリケーションの更新が正しく行われません。この問題は今後修正されますが ({{bug(834338)}} 参照)、当面は属性を指定するだけでアプリは期待通りに更新されます。</p>
<h2 id=".E3.83.91.E3.83.95.E3.82.A9.E3.83.BC.E3.83.9E.E3.83.B3.E3.82.B9">パフォーマンス</h2>
<p>ここでは、端末のハードウェアを停止させることなく快適に動作する Web アプリを作成しようとする皆さんの役に立つアドバイスをまとめました。</p>
<h3 id="CSS_.E3.82.A2.E3.83.8B.E3.83.A1.E3.83.BC.E3.82.B7.E3.83.A7.E3.83.B3.E3.81.A8.E3.83.88.E3.83.A9.E3.83.B3.E3.82.B8.E3.82.B7.E3.83.A7.E3.83.B3.E3.82.92.E4.BD.BF.E3.81.86">CSS アニメーションとトランジションを使う</h3>
<p>一部のライブラリが提供する <code>animate()</code> 関数は、まだ様々なパフォーマンスの悪い技術 (例えば {{domxref("window.setTimeout()")}} や <code>top</code>/<code>left</code> 位置指定) を使っている可能性がありますので、代わりに <a href="/ja/docs/CSS/Using_CSS_animations">CSS アニメーション</a> を使いましょう。たいていの場合、実際には <a href="/ja/docs/CSS/CSS_transitions">CSS トランジション</a> を使えば、やりたいことを実現できます。ブラウザはそうしたエフェクトを最適化し、GPU を使用してプロセッサのパフォーマンスへの影響を最小限に抑えつつスムーズに処理するように設計されていますので、問題なく動作するはずです。もうひとつのメリットは、CSS で標準的な構文を使い、アプリの他のデザインとともにそれらのエフェクトを定義できるという点です。</p>
<p>CSS アニメーションでは、<a href="/ja/docs/CSS/@keyframes">キーフレーム</a> を使って、非常に細かくエフェクトを調整することが可能です。アニメーションの表示中に実行されたイベントを監視し、そのプロセスの設定点で実行すべき他のタスクを処理することさえ可能です。{{cssxref(":hover")}}、{{cssxref(":focus")}}、{{cssxref(":target")}} といった疑似クラスを使用して、あるいは親要素へ動的にクラスを追加・削除することで、そうしたアニメーションを簡単に実行することができます。</p>
<p><a href="/ja/docs/JavaScript">JavaScript</a> でアニメーションを動的に生成あるいは変更したい場合は、James Long が作成した <a href="https://github.com/jlongster/css-animations.js/">CSS-animations.js</a> というシンプルなライブラリを使うこともできます。</p>
<h3 id="CSS_.E3.83.88.E3.83.A9.E3.83.B3.E3.82.B9.E3.83.95.E3.82.A9.E3.83.BC.E3.83.A0.E3.82.92.E4.BD.BF.E3.81.86">CSS トランスフォームを使う</h3>
<p>要素の位置や比率などを調整したいときは、絶対配置を変更し、その数値を自分自身で計算する代わりに、{{cssxref("transform")}} CSS プロパティを使いましょう。その理由は、先ほどと同じくハードウェアアクセラレーションです。ブラウザはそうしたタスクを GPU 上で処理し、他のことを CPU に処理させることが可能です。</p>
<p>さらにトランスフォームは、他の方法ではおそらく実現できない機能を提供します。要素を 2 次元空間内で移動させるだけでなく、3 次元空間内の移動や、ゆがみ、回転といった処理を行えるのです。Paul Irish が、パフォーマンスの観点から <a href="http://paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/"><code>translate()</code> のメリットに関する綿密な分析を行っています</a>。ただ、一般的には、CSS アニメーションを使っても同じメリットを得られます。実現したいエフェクトのために適切なツールを使用し、最適化はブラウザに任せましょう。また、要素の位置を変更するには、簡単に拡張可能な方法を使用できます。<code>top</code> や <code>left</code> の座標変更でそうした移動をエミュレートするとなると、コードを大量に追加しなければならないでしょう。もうひとつのメリットは、{{HTMLElement("canvas")}} 内でも使えるという点です。</p>
<aside>
  <div class="note">
    <p><strong>注:</strong> 今のところ、一部の環境では、ハードウェアアクセラレーションを活用するには <code>translateZ(0)</code> を使用する必要があります。これはメモリ消費量を増大させるといった問題を引き起こす可能性もありますが、こうしたテクニックは今後ずっと必要なものではありません。</p>
  </div>
</aside>
<h3 id="setInterval()_.E3.81.AE.E4.BB.A3.E3.82.8F.E3.82.8A.E3.81.AB_requestAnimationFrame()_.E3.82.92.E4.BD.BF.E3.81.86"><code>setInterval()</code> の代わりに <code>requestAnimationFrame()</code> を使う</h3>
<p>{{domxref("window.setInterval()")}} の呼び出しは、現状では実行可能かどうか定かではない推定フレームレートでコードを実行します。また、ブラウザが実際には描画していない、つまりビデオハードウェアが次の表示サイクルに達していないときにも結果を描画させようとします。これはプロセッサ時間の無駄遣いです (ユーザの端末のバッテリー寿命を縮める結果にもなります)。</p>
<p>代わりに {{domxref("window.requestAnimationFrame()")}} を使ってみましょう。これは、ブラウザが実際にアニメーションの次のフレームのビルドを開始する準備が整うまで待機し、ハードウェアが実際には何も描画しようとしていない場合は実行されません。この API が持つもうひとつのメリットは、アプリが画面上に表示されていないとき (バックグラウンドのタブにあって他のタスクが実行されている場合など) はアニメーションが実行されないということです。これはバッテリー消費を抑え、ユーザの間で悪評が立つのを防ぐことにもなります。</p>
<h3 id=".E3.82.A4.E3.83.99.E3.83.B3.E3.83.88.E3.82.92.E5.8D.B3.E6.99.82.E3.81.AB.E5.AE.9F.E8.A1.8C.E3.81.99.E3.82.8B">イベントを即時に実行する</h3>
<p>保守的な、アクセシビリティに考慮した Web 開発者として、キーボード入力への対応という付加的なメリットを備えていることから、私たちはクリックイベントを気に入っています。モバイル端末上では、それらは非常に遅くなります。代わりに {{event("touchstart")}} や {{event("touchend")}} を使うべきです。その理由は、アプリの動作が緩慢であると感じさせるような遅延が発生しないということです。タッチ対応を始めにテストする場合、アクセシビリティも犠牲にしてはいけません。例えば、Financial Times はそのために、一般公開もされている <a href="https://github.com/ftlabs/fastclick">fastclick</a> というライブラリを使用しています。</p>
<h3 id=".E3.82.A4.E3.83.B3.E3.82.BF.E3.83.95.E3.82.A7.E3.83.BC.E3.82.B9.E3.82.92.E3.82.B7.E3.83.B3.E3.83.97.E3.83.AB.E3.81.AB.E4.BF.9D.E3.81.A4">インタフェースをシンプルに保つ</h3>
<p>HTML5 アプリに見られる大きなパフォーマンス問題のひとつに、多くの <a href="/ja/docs/DOM">DOM</a> 要素を移動させることで、特にグラデーションやドロップシャドウを多用している場合、あらゆる動作が緩慢になるということが挙げられました。デザインをシンプルにし、ドラッグ&ドロップ処理を行う場合は仮の要素を移動させることで、そうした問題を大幅に改善することが可能です。</p>
<p>例えば、アプリ内に要素の長大なリスト (ツイート一覧など) がある場合、それらをすべて移動させようとしてはいけません。その代わりに、表示されているツイートと、その前後にある多少のツイートだけを DOM ツリー内に保持することも可能でしょう。残りは隠すか削除しましょう。DOM へアクセスする代わりに JavaScript オブジェクト内にデータを保持することで、アプリのパフォーマンスを大幅に向上させることができます。表示を、データそのものではなく、データの表現として考えましょう。これは本来の HTML をソースとして使えないということではありません。ユーザがツイートを呼んで 10 要素分スクロールしたら、表示されていない 100 要素を移動する代わりに、結果リスト内の位置によって最初と最後のコンテンツを変更するのです。同じテクニックはスプライト処理を行うゲームにも当てはまります。要素が画面上にない場合は、それらにポーリングを行う必要はありません。代わりに、画面外に出た要素を画面内に入る要素として再利用すれば良いのです。</p>
Revert to this revision