diff --git a/files/ja/web/opensearch/index.html b/files/ja/web/opensearch/index.html deleted file mode 100644 index 6b1496a147b67e..00000000000000 --- a/files/ja/web/opensearch/index.html +++ /dev/null @@ -1,161 +0,0 @@ ---- -title: OpenSearch 記述形式 -slug: Web/OpenSearch -tags: - - Add-ons - - Guide - - OpenSearch - - Search - - Search plugins - - Web - - Web Standards -translation_of: Web/OpenSearch -original_slug: Creating_OpenSearch_plugins_for_Firefox ---- -

{{AddonSidebar}}

- -

OpenSearch 記述形式は、ウェブサイトが自分自身のために検索エンジンを記述し、ブラウザーやその他のクライアントアプリケーションがその検索エンジンを使用できるようにするものです。 OpenSearch は、(少なくとも) Firefox、Edge、Internet Explorer、Safari、Chrome が対応しています。(他のブラウザーのドキュメントへのリンクは参考資料をご覧ください。)

- -

また、Firefox では、検索候補や <SearchForm> 要素など、OpenSearch 規格にない追加機能にも対応しています。この記事では、これらの Firefox の追加機能に対応した OpenSearch 互換の検索プラグインの作成に焦点を当てます。

- -

OpenSearch 記述ファイルは、検索プラグインの自動検出で説明されているように通知することができ、ウェブページからの検索エンジンの追加で説明されているようにプログラムでインストールすることができます。

- -

OpenSearch 記述ファイル

- -

検索エンジンを記述する XML ファイルはとてもシンプルで、以下の基本的なテンプレートに従います。書いている検索エンジンに応じて、 [角括弧] で囲まれた部分をカスタマイズする必要があります。

- -
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"
-                       xmlns:moz="http://www.mozilla.org/2006/browser/search/">
-  <ShortName>[SNK]</ShortName>
-  <Description>[Search engine full name and summary]</Description>
-  <InputEncoding>[UTF-8]</InputEncoding>
-  <Image width="16" height="16" type="image/x-icon">[https://example.com/favicon.ico]</Image>
-  <Url type="text/html" template="[searchURL]">
-    <Param name="[key name]" value="{searchTerms}"/>
-    <!-- other Params if you need them… -->
-    <Param name="[other key name]" value="[parameter value]"/>
-  </Url>
-  <Url type="application/x-suggestions+json" template="[suggestionURL]"/>
-  <moz:SearchForm>[https://example.com/search]</moz:SearchForm>
-</OpenSearchDescription>
- -
-
ShortName
-
検索エンジンの短い名前です。 HTML やその他のマークアップを使用しない、 16 文字以下のプレーンテキストでなければなりません。
-
Description
-
検索エンジンの簡単な説明です。 1024 文字以下のプレーンテキストで、 HTML やその他のマークアップは使用しないでください。
-
InputEncoding
-
検索エンジンへ送信する入力欄に使用する文字エンコーディングです。
-
Image
-
-

検索エンジンのアイコンの URI です。可能であれば、 16×16 の画像を image/x-icon 形式で (/favicon.ico など)、 および 64×64 の画像を image/jpeg または image/png 形式で含めてください。

- -

この URI には data: URI スキームを使用することもできます。 (data: URI はアイコンファイルから The data: URI kitchen で生成することができます。)

- -
<Image height="16" width="16" type="image/x-icon">https://example.com/favicon.ico</Image>
-  <!-- or -->
-<Image height="16" width="16">data:image/x-icon;base64,AAABAAEAEBAAA … DAAA=</Image>
-
- -

Firefox はアイコンを base64 data: URI としてキャッシュします (検索プラグインはプロファイルsearchplugins/ フォルダーに格納されます)。これを行う際に、 http: および https: URL は data: URI に変換されます。

- -
注: リモートからアイコンを読み込む際 (すなわち、 data: URI とは対照的に https:// URI からの場合)、 Firefox は10 KBより大きなアイコンを拒否します。
- -

Firefox の検索ボックスに表示される Google の検索候補

-
-
Url
-
検索に使う 1 つまたは複数の URL を記述します。 template 属性は検索クエリーのベース URL を指定します。
-
Firefox は 3 種類の URL に対応しています。
- - -

これらの種類の URL では、ユーザーが検索バーやロケーションバーに入力した検索語に置き換えらえる {searchTerms} を使うことができます。対応している他の動的な検索引数は OpenSearch 1.1 引数に記述されています。

- -

検索候補については、 application/x-suggestions+json URL テンプレートを使用して候補リストを JSON 形式で読み取ります。サーバー上で検索候補の対応を実装する方法の詳細は 検索プラグインでの検索候補の対応を参照してください。

- -
Param
-
検索クエリと一緒に渡さなければならない引数を、キー/値のペアで指定します。値を指定する際に、 {searchTerms} を使用すると、ユーザーが検索バーに入力した検索語を挿入することができます。
-
moz:SearchForm
-
プラグインのサイトの検索ページを開くための URL。これは Firefox にユーザーが直接ウェブサイトを訪れる方法を提供します。
-
-
注意: この要素は Firefox 特有で OpenSearch 仕様の一部ではないため、この要素に対応していない他のユーザーエージェントが安全に無視できるようにするために、上の例では "moz:" XML 名前空間接頭辞を使っています。
-
-
- -

検索プラグインの自動検出

- -

検索プラグインを提供しているウェブサイトは、 Firefox ユーザがプラグインを簡単にダウンロードしてインストールできるように通知することができます。

- -

自動検出に対応するには、それぞれのプラグインの <link> 要素をウェブページの <head> セクションにします。

- -
<link rel="search"
-      type="application/opensearchdescription+xml"
-      title="searchTitle"
-      href="pluginURL">
-
- -

太字の項目を以下の説明のように置き換えてください。

- -
-
searchTitle
-
"MDC を検索" や 'Yahoo! 検索" のような実行する検索の名前です。この値は、プラグインファイルの <ShortName> と一致させる必要があります。
-
pluginURL
-
ブラウザーがダウンロードできる XML 検索プラグインの URL です。
-
- -

もしサイトが複数の検索プラグインを提供しているなら、すべてを自動検出させることができます。例を示します。

- -
<link rel="search" type="application/opensearchdescription+xml"
-      title="MySite: 著者" href="http://example.com/mysiteauthor.xml">
-
-<link rel="search" type="application/opensearchdescription+xml"
-      title="MySite: タイトル" href="http://example.com/mysitetitle.xml">
-
- -

この方法で、著者とタイトルによる検索を行うプラグインをサイトで提供することができます。

- -
-

Firefox では、検索プラグインで提供されたアイコンがある場合は、検索ボックスのアイコンが変化して示します。 (画像を参照。緑のプラスの記号です。) そのため、ユーザーのインターフェイスで検索ボックスが非表示になっている場合、これを示すことはありません一般に、この動作はブラウザーによって異なります

-Firefox での検索プラグインの見え方
- -

OpenSearch プラグインの自動更新の対応

- -

OpenSearch プラグインは自動的に更新することができます。 Url 拡張要素を type="application/opensearchdescription+xml" および rel="self" を付けて設置してください。 template 属性には、自動的に更新する OpenSearch 文書の URL を設定してください。

- -

例:

- -
<Url type="application/opensearchdescription+xml"
-     rel="self"
-     template="https://example.com/mysearchdescription.xml" />
-
- -
注: 現時点で、 addons.mozilla.org (AMO) は OpenSearch プラグインの自動更新に対応していません。自分の検索プラグインを AMO に登録したい場合は、送信前に自動更新機能を削除してください。
- -

トラブルシューティングのヒント

- -

検索プラグインの XML に問題があると、検出されたプラグインをに追加する際にエラーが発生します。エラーメッセージが参考にならない場合、以下のヒントが問題を探す手助けになる可能性があります。

- - - -

さらに、検索プラグインサービスはプラグイン開発者に役立つであろうログの仕組みを提供します。 about:config を使い 'browser.search.log' を true に設定してください。検索プラグインが追加されるとログ情報が Firefox のエラーコンソール (ツール ➤ エラーコンソール)に表示されます。

- -

参考資料

- - diff --git a/files/ja/web/opensearch/index.md b/files/ja/web/opensearch/index.md new file mode 100644 index 00000000000000..8591def481d5d1 --- /dev/null +++ b/files/ja/web/opensearch/index.md @@ -0,0 +1,153 @@ +--- +title: OpenSearch 記述形式 +slug: Web/OpenSearch +tags: + - Add-ons + - Guide + - OpenSearch + - Search + - Search plugins + - Web + - Web Standards +translation_of: Web/OpenSearch +original_slug: Creating_OpenSearch_plugins_for_Firefox +--- +{{AddonSidebar}} + +**[OpenSearch 記述形式](https://github.com/dewitt/opensearch)** は、ウェブサイトが自分自身のために検索エンジンを記述し、ブラウザーやその他のクライアントアプリケーションがその検索エンジンを使用できるようにするものです。 OpenSearch は、(少なくとも) Firefox、Edge、Internet Explorer、Safari、Chrome が対応しています。(他のブラウザーのドキュメントへのリンクは[参考資料](#reference_material)をご覧ください。) + +また、Firefox では、検索候補や `` 要素など、OpenSearch 規格にない追加機能にも対応しています。この記事では、これらの Firefox の追加機能に対応した OpenSearch 互換の検索プラグインの作成に焦点を当てます。 + +OpenSearch 記述ファイルは、[検索プラグインの自動検出](#autodiscovery_of_search_plugins)で説明されているように通知することができ、[ウェブページからの検索エンジンの追加](/ja/docs/Web/OpenSearch)で説明されているようにプログラムでインストールすることができます。 + +## OpenSearch 記述ファイル + +検索エンジンを記述する XML ファイルはとてもシンプルで、以下の基本的なテンプレートに従います。書いている検索エンジンに応じて、 _\[角括弧]_ で囲まれた部分をカスタマイズする必要があります。 + +```xml + + [SNK] + [Search engine full name and summary] + [UTF-8] + [https://example.com/favicon.ico] + + + [https://example.com/search] + +``` + +- ShortName + - : 検索エンジンの短い名前です。 HTML やその他のマークアップを使用しない、 **16 文字以下**のプレーンテキストでなければなりません。 +- Description + - : 検索エンジンの簡単な説明です。 **1024 文字以下**のプレーンテキストで、 HTML やその他のマークアップは使用しないでください。 +- InputEncoding + - : 検索エンジンへ送信する入力欄に使用する[文字エンコーディング](/ja/docs/Glossary/character_encoding)です。 +- Image + + - : 検索エンジンのアイコンの URI です。可能であれば、 16×16 の画像を `image/x-icon` 形式で (`/favicon.ico` など)、 および 64×64 の画像を `image/jpeg` または `image/png` 形式で含めてください。 + + この URI には [`data:` URI スキーム](/ja/docs/Web/HTTP/Basics_of_HTTP/Data_URIs)を使用することもできます。 (`data:` URI はアイコンファイルから [The `data:` URI kitchen](http://software.hixie.ch/utilities/cgi/data/data) で生成することができます。) + + ```xml + https://example.com/favicon.ico + + data:image/x-icon;base64,AAABAAEAEBAAA … DAAA= + ``` + + Firefox はアイコンを [base64](https://ja.wikipedia.org/wiki/Base64) `data:` URI としてキャッシュします (検索プラグインは[プロファイル](/ja/docs/Mozilla/Profile_Manager)の `searchplugins/` フォルダーに格納されます)。これを行う際に、 `http:` および `https:` URL は `data:` URI に変換されます。 + + > **Note:** リモートからアイコンを読み込む際 (すなわち、 `data:` URI とは対照的に `https://` URI からの場合)、 Firefox は**10 KB**より大きなアイコンを拒否します。 + + ![Firefox の検索ボックスに表示される Google の検索候補](searchsuggestionsample.png) + +- Url + + - : 検索に使う 1 つまたは複数の URL を記述します。 `template` 属性は検索クエリーのベース URL を指定します。 + Firefox は 3 種類の URL に対応しています。 + + - `type="text/html"` は実際の検索結果そのものの URL を指定します。 + - `type="application/x-suggestions+json"` は検索候補を読み取るための URL を指定します。 Firefox 63 以降では、 `type="application/json"` をこの別名として受け付けます。 + - `type="application/x-moz-keywordsearch"` はロケーションバーに入力されるキーワード検索の際に使用する URL を指定します。これは Firefox のみが対応しています。 + + これらの種類の URL では、ユーザーが検索バーやロケーションバーに入力した検索語に置き換えらえる `{searchTerms}` を使うことができます。対応している他の動的な検索引数は [OpenSearch 1.1 引数](http://www.opensearch.org/Specifications/OpenSearch/1.1/Draft_3#OpenSearch_1.1_parameters)に記述されています。 + + 検索候補については、 `application/x-suggestions+json` URL テンプレートを使用して候補リストを [JSON](/ja/docs/Glossary/JSON) 形式で読み取ります。サーバー上で検索候補の対応を実装する方法の詳細は [検索プラグインでの検索候補の対応](/ja/docs/Archive/Add-ons/Supporting_search_suggestions_in_search_plugins)を参照してください。 + +- Param + - : 検索クエリと一緒に渡さなければならない引数を、キー/値のペアで指定します。値を指定する際に、 `{searchTerms}` を使用すると、ユーザーが検索バーに入力した検索語を挿入することができます。 +- moz:SearchForm + + - : プラグインのサイトの検索ページを開くための URL。これは Firefox にユーザーが直接ウェブサイトを訪れる方法を提供します。 + + > **Note:** この要素は Firefox 特有で OpenSearch 仕様の一部ではないため、この要素に対応していない他のユーザーエージェントが安全に無視できるようにするために、上の例では "`moz:`" XML 名前空間接頭辞を使っています。 + +## 検索プラグインの自動検出 + +検索プラグインを提供しているウェブサイトは、 Firefox ユーザがプラグインを簡単にダウンロードしてインストールできるように通知することができます。 + +自動検出に対応するには、それぞれのプラグインの `` 要素をウェブページの `` セクションにします。 + +```html + +``` + +太字の項目を以下の説明のように置き換えてください。 + +- searchTitle + - : "MDC を検索" や 'Yahoo! 検索" のような実行する検索の名前です。この値は、プラグインファイルの `` と一致させる必要があります。 +- pluginURL + - : ブラウザーがダウンロードできる XML 検索プラグインの URL です。 + +もしサイトが複数の検索プラグインを提供しているなら、すべてを自動検出させることができます。例を示します。 + +```html + + + +``` + +この方法で、著者とタイトルによる検索を行うプラグインをサイトで提供することができます。 + +> **Note:** Firefox では、検索プラグインで提供されたアイコンがある場合は、検索ボックスのアイコンが変化して示します。 (画像を参照。緑のプラスの記号です。) そのため、ユーザーのインターフェイスで検索ボックスが非表示になっている場合、これを示すことは*ありません*。_一般に、この動作はブラウザーによって異なります_。 + +## OpenSearch プラグインの自動更新の対応 + +OpenSearch プラグインは自動的に更新することができます。 `Url` 拡張要素を `type="application/opensearchdescription+xml"` および `rel="self"` を付けて設置してください。 `template` 属性には、自動的に更新する OpenSearch 文書の URL を設定してください。 + +例: + +```xml + +``` + +> **Note:** 現時点で、 [addons.mozilla.org](https://addons.mozilla.org) (AMO) は OpenSearch プラグインの自動更新に対応していません。自分の検索プラグインを AMO に登録したい場合は、送信前に自動更新機能を削除してください。 + +## トラブルシューティングのヒント + +検索プラグインの XML に問題があると、検出されたプラグインをに追加する際にエラーが発生します。エラーメッセージが参考にならない場合、以下のヒントが問題を探す手助けになる可能性があります。 + +- サーバーは OpenSearch プラグインを、 `Content-Type: application/opensearchdescription+xml` を使用して提供するべきです。 +- 検索プラグインの XML が整形式であることを確認してください。ファイルを直接 Firefox に読み込むことでチェックすることができます。アンパーサンド (&) を `template` の URL の中では `&` にエスケープしなければなりません。タグは最後にスラッシュをまたは対応する終了タグで閉じる必要があります。 +- `xmlns` 属性は重要です。 — これがないと、 "Firefox could not download the search plugin" というエラーメッセージが出る可能性があります。 +- `text/html` の URL を含める**必要があります**。 Atom または [RSS](/ja/docs/Glossary/RSS) の URL 型のみを含む検索プラグインは (有効なものですが、 Firefox は対応していません)、 "could not download the search plugin" エラーを引き起こします。 +- リモートで取得されるファビコンは 10KB 以上でなければなりません ({{ Bug(361923) }} を参照)。 + +さらに、検索プラグインサービスはプラグイン開発者に役立つであろうログの仕組みを提供します。 `about:config` を使い '`browser.search.log`' を `true` に設定してください。検索プラグインが追加されるとログ情報が Firefox の[エラーコンソール](/ja/docs/Archive/Mozilla/Error_console) (ツール ➤ エラーコンソール)に表示されます。 + +## 参考資料 + +- [OpenSearch ドキュメント](https://github.com/dewitt/opensearch) +- [Safari 8.0 リリースノート: Quick Website Search](https://developer.apple.com/library/archive/releasenotes/General/WhatsNewInSafari/Articles/Safari_8_0.html) +- [Microsoft Edge 開発ガイド: Search provider discovery](https://docs.microsoft.com/en-us/microsoft-edge/dev-guide/browser-features/search-provider-discovery) +- [The Chromium Projects: Tab to Search](https://www.chromium.org/tab-to-search) +- imdb.com には [動作する `osd.xml`](https://m.media-amazon.com/images/G/01/imdb/images/imdbsearch-3349468880._CB470047351_.xml) があります +- [OpenSearch Plugin Generator](http://www.7is7.com/software/firefox/opensearch.html) +- [Ready2Search](http://ready.to/search/jp/) - OpenSearch プラグインの作成 (日本語可, GET メソッドのみ)。 [Customized Search through Ready2Search](http://ready.to/search/make/en_make_plugin.htm) diff --git a/files/ja/web/performance/fundamentals/index.html b/files/ja/web/performance/fundamentals/index.html deleted file mode 100644 index eec0ddf96fe40e..00000000000000 --- a/files/ja/web/performance/fundamentals/index.html +++ /dev/null @@ -1,219 +0,0 @@ ---- -title: パフォーマンスの基礎 -slug: Web/Performance/Fundamentals -tags: - - Apps - - Firefox - - Gecko - - Guide - - Performance -translation_of: Web/Performance/Fundamentals ---- -
-

パフォーマンスとは、効率性を意味します。この文書では、オープンウェブアプリの観点から、パフォーマンスとは何か、ブラウザープラットフォームでどのようにパフォーマンスを向上させるか、テストや改善にどのようなツールやプロセスを使用できるかについて一般的な説明をします。.

-
- -

パフォーマンスとは

- -

最終的には、ユーザーが知覚したパフォーマンスが唯一のパフォーマンスとなります。ユーザーは、触ったり、動かしたり、話したりして、システムに入力を与えます。その代わり、ユーザーは視覚、触覚、聴覚を通じて出力を知覚します。パフォーマンスとは、ユーザーの入力に応じてシステムが出力するものの品質のことです。

- -

他の条件が同じであれば、ユーザーが知覚するパフォーマンス (以下、UPP) 以外のターゲットに最適化されたコードは、 UPP に最適化されたコードと競合すると負けてしまいます。ユーザーは、例えば、 1 秒間に 1,000 件しかデータベーストランザクションを処理しないが応答性の高いスムーズに動くアプリの方を、 1 秒間に 100,000,000 件のデータベーストランザクションを処理するカクカクした応答性の低いアプリよりも好みます。もちろん、他の指標を最適化することは決して無意味ではありませんが、実際の UPP ターゲットが最優先です。

- -

以下の節では、必須のパフォーマンス指標を指摘し、説明します。

- -

応答性

- -

応答性とは、ユーザーの入力に応じてシステムがどれだけ速く出力 (複数の場合もある) を行うかを意味します。例えば、ユーザーが画面をタップすると、ピクセルが特定の方法で変化することを期待します。この操作の場合、応答性の指標は、タップしてからピクセルが変化するまでの経過時間となります。

- -

応答性には、複数の段階のフィードバックが含まれることがあります。アプリケーションの起動は、特に重要なケースの一つで、詳しくは後述します。

- -

応答性が重要なのは、人は無視されるとイライラしたり怒ったりするからです。アプリはユーザーの入力に応答しない間、ユーザーを無視していることになります。

- -

フレームレート

- -

フレームレートとは、システムがユーザーに表示するピクセルを変化させる速度のことです。例えば、毎秒 10 フレームのゲームよりも、毎秒 60 フレームのゲームの方が好きだというのは、理由を説明できなくても、誰もが知っている概念です。

- -

フレームレートは「サービスの質」の指標としても重要です。コンピューターのディスプレイは、現実を模倣した光子をユーザーの目に届けることで、ユーザーの目を「欺く」ように設計されています。例えば、文字が印刷された紙は、光子をあるパターンでユーザーの目に反射させます。リーダーアプリは、ピクセルを操作することで、同じようなパターンで光子を放出し、ユーザーの目を「騙す」のです。

- -

脳は考えるとき、動きはギクシャクしたバラバラなものではなく、滑らかに連続して更新されるものだと考えます。 (ストロボはそれを逆手に取り、脳の入力を奪って離散的な現実を錯覚させるから面白いのです)。コンピューターのディスプレイでは、フレームレートが高ければ高いほど、より忠実に現実を再現することができます。

- -
-

: 人間は通常、60Hz以上のフレームレートの違いを知覚することができません。そのため、最近の電子ディスプレイは、60Hzで更新するように設計されています。例えばハチドリには、テレビが途切れ途切れで非現実的に見えることでしょう。

-
- -

メモリーの使用

- -

メモリーの使用量も重要な指標です。応答性やフレームレートとは異なり、ユーザーはメモリー使用量を直接知覚することはありませんが、メモリー使用量は「ユーザーの状態」に近いものです。理想的なシステムでは、ユーザーの状態を常に 100% 維持することができます。システム内のすべてのアプリケーションは同時に実行され、すべてのアプリケーションは、ユーザーが最後にアプリケーションを操作したにユーザーが設定した状態を維持します (アプリケーションの状態はコンピュータのメモリーに保存されているため、近似値になるのです)。

- -

このことから、重要ではあるが直感的ではない副産物が得られます。設計の優れたシステムは、空きメモリー量を最大化しません。メモリーは資源であり、空きメモリーは使われていない資源であるからです。むしろ、設計の優れたシステムは、ユーザーの状態を維持するために可能な限り多くのメモリーを使用し、かつ他の UPP 目標を満たすように最適化されています。

- -

これは、システムがメモリーを浪費すべきだという意味ではありません。システムがある特定のユーザーの状態を維持するために必要以上のメモリーを使用すると、システムは他のユーザーの状態を維持するために使用できる資源を浪費していることになります。実際には、すべてのユーザーの状態を維持できるシステムはありません。ユーザーの状態に賢くメモリーを割り当てることは、以下で詳しく説明する重要な問題です。

- -

電力使用量

- -

ここで解説する最後の指標は、電力使用量です。メモリー使用量と同様に、ユーザーは、端末が他のすべての UPP 目標を維持できる時間という形で、電力使用量を間接的にしか認識しません。 UPP 目標を達成するためには、システムは必要最小限の電力しか使用しないようにする必要があります。

- -

この文書の残りの部分では、これらの指標の観点からパフォーマンスについて説明します。

- -

プラットフォームのパフォーマンスの最適化

- -

この節では、 Firefox/Gecko が、すべてのアプリケーションのレベルよりも下位で、一般的にどのようにパフォーマンスに貢献しているかを簡単に説明します。開発者やユーザーの視点から、「プラットフォームは何をしてくれるのか?」という問いに答えます。

- -

ウェブ技術

- -

ウェブプラットフォームには多くのツールが用意されていますが、中には特定の仕事に適したものもあります。アプリケーションロジックはすべて JavaScript で書かれています。グラフィックの表示には、 (高水準の宣言型言語である) HTML や CSS を使用するか、低レベルの命令型インターフェースである {{ htmlelement("canvas") }} 要素 (WebGL を含む) を使用します。 HTML/CSS と Canvas の「中間」に位置するのが SVG で、両者の利点を兼ね備えています。

- -

HTML や CSS は、フレームレートやピクセルレベルでのレンダリング制御を犠牲にして、生産性を大幅に向上させます。テキストや画像は自動的に再フローされ、 UI 要素には自動的にシステムのテーマが適用されます。また、このシステムは、様々な解像度のディスプレイや右書きの言語など、開発者が最初に思いつかないような使用方法に「組み込み」で対応します。

- -

canvas 要素は、開発者が直接描画できるピクセルバッファーを提供します。これにより、開発者はピクセルレベルでレンダリングを制御し、フレームレートを正確に制御することができますが、複数の解像度や方向、右書きの言語などに対応する必要があります。開発者は、おなじみの 2D 描画 API か、 OpenGL ES 2.0 をほぼ踏襲した「金属に近い」バインディングである WebGL を使用してキャンバスに描画します。

- -
-

: Firefox OS は、 HTMLCSSJavaScript などのウェブ技術で作られたアプリに最適化されています。一握りの基本的なシステムサービスを除いて、 Firefox OS で動作するすべてのコードはウェブアプリと Gecko エンジンから来ています。 OS のウィンドウマネージャも HTML、CSS、JavaScript で書かれています。コアとなる OS とアプリケーションは同じウェブ技術で構築されているため、これらの技術がどのように機能するかが重要になります。そこには「逃げ道」はありません。これは開発者にとって大きなメリットです。なぜなら、サードパーティのアプリケーションは、 OS が独自に行ったすべての最適化の恩恵を受けることができるからです。プリインストールされたコードだけが利用できる「魔法のパフォーマンスソース」はありません。 Firefox OS に関する詳細は、 Firefox OS のパフォーマンステストをご覧ください。

-
- -

Gecko のレンダリング

- -

Gecko の JavaScript エンジンは、実行時 (JIT) コンパイルに対応しています。これにより、アプリケーションロジックは、Java 仮想マシンのような他の仮想マシンと同等の性能を発揮し、場合によっては「ネイティブコード」に近い性能を発揮します。

- -

HTML、CSS、Canvas を支える Gecko のグラフィックパイプラインは、いくつかの方法で最適化されています。 Gecko の HTML/CSS レイアウトおよびグラフィックコードは、スクロールなどの一般的なケースでは、無効化や再描画を削減しますが、開発者はこのサポートを「無料」で受けることができます。 Gecko が「自動的に」描画したり、 canvas へアプリケーションが「手動で」描画したりするピクセルバッファーは、ディスプレイのフレームバッファーに描画される際のコピーを最小限に抑えます。これは、中間サーフェスがオーバーヘッドになるような場所 (他の多くのオペレーティングシステムにおけるアプリケーションごとの「バックバッファー」など) を避け、コンポジターハードウェアが直接アクセスできるグラフィックバッファー用の特別なメモリーを使用することで実現されています。複雑なシーンのレンダリングには、端末の GPU を使用して最大のパフォーマンスを発揮します。電力消費を抑えるために、シンプルなシーンは専用の合成ハードウェアを使ってレンダリングし、 GPU はアイドルまたはオフにしています。

- -

リッチアプリケーションでは、完全な静的コンテンツは例外です。リッチアプリケーションでは、アニメーションやトランジション効果のある動的コンテンツを使用します。トランジションやアニメーションは、アプリケーションにとって特に重要です。開発者は、 CSS を使用することで、複雑な動作をシンプルで高レベルな構文で宣言することができます。また、 Gecko のグラフィックパイプラインは、一般的なアニメーションを効率的に描画するように高度に最適化されています。良くあるアニメーションは、システムコンポジターにオフロードされ、パフォーマンスと電力効率に優れた方法でレンダリングされます。

- -

アプリの起動時のパフォーマンスは、実行時のパフォーマンスと同じくらい重要です。 Gecko は、 Web 全体を含むさまざまなコンテンツを効率的に読み込むように最適化されています。並列 HTML 解析、再フローと画像デコーディングのインテリジェントなスケジューリング、巧妙なレイアウトアルゴリズムなど、コンテンツを対象とした長年の改良は、Firefox でのウェブアプリケーションの改良にも同様に反映されます。

- -
-

: 起動時のパフォーマンスをさらに向上させるための Firefox OS の仕様についての詳細は、 Firefox OS パフォーマンステストを参照してください。

-
- -

アプリケーションのパフォーマンス

- -

この節では、「どうしたらアプリを高速にできるのか」という開発者の問いのためのものです。

- -

起動時のパフォーマンス

- -

アプリケーションの起動は、一般的に 3 つのイベントで構成されています。

- -
    -
  • 1 つ目は、アプリケーションのファーストペイント (最初のフレームを描くのに十分なアプリケーションリソースが読み込まれた時点) です。
  • -
  • 2 つ目は、アプリケーションが操作可能になった時点です。例えば、ユーザーがボタンをタップすると、アプリケーションが反応するようになります。
  • -
  • 最後のイベントは完全読み込みです。たとえば、音楽プレイヤーにユーザーのアルバムをすべて表示された時点です。
  • -
- -

高速な起動の鍵となるのは、 2 つのことを念頭に置くことです。 UPP がすべてであること、そして上記のユーザーが知覚する各イベントには「クリティカルパス」が存在することです。クリティカルパスとは、まさに、そのイベントを発生させるために実行しなければならないコードのことです。

- -

例えば、アプリケーションの最初のフレームを視覚的に描くためには、いくつかの HTML と、その HTML にスタイル付けする CSS で構成されます。

- -
    -
  1. HTML を解釈する必要がある
  2. -
  3. その HTML の DOM を構築する必要がある
  4. -
  5. DOM の一部にある画像などのリソースを読み込み、デコードする必要がある
  6. -
  7. CSS のスタイルをその DOM に適用する必要がある
  8. -
  9. スタイル付けした文書を再フローさせる必要がある
  10. -
- -

このリストのどこにも、「一般的でないメニューに必要な JS ファイルの読み込み」や「ハイスコアリスト用の画像の取得とデコード」などは含まれていません。これらの作業項目は、最初のフレームを描くためのクリティカルパスには含まれていません。

- -

当たり前のようですが、ユーザーが認識する起動イベントに早く到達するためには、クリティカルパス上のコードだけを実行することが主な「コツ」です。その場面を単純化することで、クリティカルパスを短縮します。

- -

ウェブプラットフォームは非常にダイナミックです。 JavaScript は動的に型付けされる言語であり、ウェブプラットフォームではコード、HTML、CSS、画像などのリソースを動的に読み込むことができます。これらの機能を利用して、起動後しばらくしてから不要なコンテンツを「遅延して」読み込むことで、クリティカルパスから外れた作業を先送りすることができます。

- -

起動を遅らせるもう 1 つの問題は、リクエストに対するレスポンス (データベースのロードなど) を待つことで発生するアイドルタイムです。この問題を避けるために、アプリケーションは起動時にできるだけ早くリクエストを発行する必要があります (これを「フロントローディング」と呼びます)。そうすれば、後でデータが必要になったとき、うまくいけばすでに利用可能で、アプリケーションは待つ必要がありません。

- -
-

: 起動時のパフォーマンスを向上させるための詳しい情報は、起動時のパフォーマンスを最適化するをご覧ください。

-
- -

また、ローカルにキャッシュされた静的なリソースは、高レイテンシー、低帯域幅のモバイルネットワークを介して取得された動的なデータよりもはるかに速く読み込まれることに注意してください。ネットワークへのリクエストは、アプリケーションの早期起動のためのクリティカルパスであってはなりません。ローカルキャッシュ/オフラインアプリケーションは、サービスワーカーによって実現できます。その方法については、 サービスワーカーで PWA をオフライン対応させる を参照してください。

- -

フレームレート

- -

高フレームレートを実現するためにまず重要なのは、適切な道具を選ぶことです。静止画やスクロール、アニメーションの頻度が少ないコンテンツの実装には、 HTML と CSS を使用します。レンダリングを厳密にコントロールする必要があり、テーマ性を必要としないゲームのように、高度に動的なコンテンツを実装する場合は、キャンバスを使用します。

- -

キャンバスで描かれたコンテンツでは、フレームレートの目標値を達成できるかどうかは、開発者次第です。

- -

HTML と CSS のコンテンツでは、適切なプリミティブを使用することが高フレームレートへの道となります。 Firefox は任意のコンテンツをスクロールするために高度に最適化されているため、通常はこの点を気にする必要はありません。しかし、 CSS の放射状グラデーションの代わりに静的なレンダリングを使用するなど、速度のために汎用性や品質を犠牲にすると、スクロールのフレームレートが目標値を超えてしまうことがよくあります。 CSS のメディアクエリーを使えば、こうした妥協を必要とする端末だけに制限することができます。

- -

多くのアプリケーションでは、「ページ」や「パネル」を使ったトランジションやアニメーションが使われています。例えば、ユーザーが「設定」ボタンをタップすると、アプリケーションの設定画面に遷移したり、設定メニューが「ポップアップ」したりします。 Firefox は、以下のようなシーンの遷移やアニメーションに高度に最適化されています。

- -
    -
  • 端末の画面サイズ以下のページ/パネルを使用する
  • -
  • CSS 変換や不透明度のプロパティを使った遷移やアニメーションを使用する
  • -
- -

これらのガイドラインに従った遷移やアニメーションは、システムコンポジターにオフロードされ、最大限効率的に動作します。

- -

メモリーと電力の使用量

- -

メモリーと電力使用量の改善は、スタートアップの高速化と同じような問題です。必要のない作業をしたり、普段使わない UI リソースをダラダラとロードしたりしてはいけません。効率的なデータ構造を使用し、画像などのリソースをしっかりと最適化しましょう。

- -

最近の CPU は、ほとんどアイドル状態の時に低消費電力モードに入ることができます。常にタイマーを作動させたり、不要なアニメーションを実行し続けるアプリケーションは、 CPU が低電力モードに入るのを妨げます。電力効率の良いアプリケーションは、そのようなことをしてはいけません。

- -

アプリケーションがバックグラウンドに送られると、その文書に対して {{event("visibilitychange")}} イベントが発行されます。このイベントは開発者の味方です。アプリケーションはこのイベントに耳を傾けるべきです。バックグラウンドに送られたときに、アプリケーションが読み込まれたリソースをできるだけ多く手放すと、メモリー使用量が少なくて済み、 Firefox OS の場合、廃棄される可能性も低くなります (以下のメモを参照)。これはつまり、 (すでに実行されているため) 「起動」が速く、 UPP が良いことを意味します。

- -
-

: 前述のとおり、 Firefox OS はできる限り多くのアプリケーションを同時に実行するようにしていますが、通常は端末のメモリーが不足したときにアプリケーションを破棄しなければならないことがあります。Firefox OS がどのようにメモリー使用量を管理し、メモリー不足の問題が発生したときにアプリケーションを終了するかについての詳細は、「Debugging out of memory errors on Firefox OS」を参照してください。

-
- -

アプリケーションのパフォーマンスのためのコーディングのコツ

- -

以下の実用的なヒントは、前述のアプリケーションのパフォーマンス要因の 1 つまたは複数を改善するのに役立ちます。

- -

CSS アニメーションとトランジションを使用する

- -

一部のライブラリーの animate() 関数は、おそらく現在、パフォーマンスが悪い数多くの技術 (例えば {{domxref("WindowOrWorkerGlobalScope.setTimeout")}} や top/left による位置指定) を使用しています。代わりに CSS アニメーションを使用してください。多くの場合、実際には CSS トランジションを使って実現することができます。ブラウザーはこれらの効果を最適化するように設計されており、 GPU を使用してプロセッサーのパフォーマンスへの影響を最小限に抑えながらスムーズに処理することができるため、うまく機能します。もう一つの利点は、標準化された構文を使って、アプリの他のルック&フィールと一緒に CSS でこれらの効果を定義できることです。

- -

CSS アニメーションでは、 キーフレームを使って効果を細かく制御することができます。また、アニメーション処理中に発生するイベントを監視して、アニメーション処理中の特定のポイントで実行する必要のある他のタスクを処理することもできます。これらのアニメーションは、 {{cssxref(":hover")}}, {{cssxref(":focus")}}, {{cssxref(":target")}} を使ったり、親要素に動的にクラスを追加したり削除したりすることで、簡単に起動することができます。

- -

アニメーションをその場で作成したり、 JavaScript で修正したりしたい場合は、 James Long 氏が CSS-animations.js というシンプルなライブラリーを作成していますので、そちらをご利用ください。

- -

CSS 変換を使用する

- -

コンテンツの位置やスケールなどを調整するのに、絶対位置を調整したり、すべての計算を自分で行ったりする代わりに、 CSS の {{cssxref("transform")}} プロパティを使用しましょう。その理由は、繰り返しになりますが、ハードウェアアクセラレーションです。ブラウザーはこれらの作業を GPU で行い、 CPU に他の処理をさせることができます。

- -

さらに、変換は、他では得られない機能を提供します。 2D 空間の要素を変換するだけでなく、 3 次元に変換したり、斜めにしたり、回転させたりすることができます。 Paul Irish 氏は、パフォーマンスの観点から見た translate() の利点を詳しく分析しています。しかし、一般的には、 CSS アニメーションを使用する場合と同じメリットがあります。つまり、仕事に適したツールを使用し、最適化はブラウザーに任せることができるのです。また、要素の位置を簡単に拡張できる方法を使用しています。 topleft の位置指定で変換をシミュレートする場合は、多くの追加コードが必要になります。もうひとつの利点は、 canvas 要素で作業するのと同じだということです。

- -
-

: プラットフォームによっては、 CSS アニメーションでハードウェアアクセラレーションを利用したい場合、 translateZ(0.1) 変換を割り当てる必要があります。前述のとおり、パフォーマンスが向上しますが、メモリー消費の問題もあります。テストをして、自分のアプリケーションに最適な方法を見つけてみてはいかがでしょうか。

-
- -

requestAnimationFrame()setInterval() の代わりに使用する

- -

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

- -

その代わりに、 {{domxref("window.requestAnimationFrame()")}} を使うようにしましょう。これは、ブラウザーがアニメーションの次のフレームを作り始める準備ができるまで待機し、ハードウェアが実際に何も描画しない場合は無視します。この API のもう一つの利点は、アプリが画面上に表示されていない間はアニメーションが実行されないことです (バックグラウンドで他のタスクが動作している場合など)。これにより、バッテリーの消費を抑え、ユーザーが夜空に向かってあなたの名前を罵るのを防ぐことができます。

- -

イベントを即時にする

- -

アクセシビリティに配慮した古いタイプのウェブ開発者は、キーボード入力二も対応する click イベントが大好きです。モバイル端末では、これらのイベントは遅すぎます。代わりに {{event("touchstart")}} と {{event("touchend")}} を使うべきです。これらのイベントには、アプリの操作を鈍くする遅延がないからです。最初にタッチ対応のテストを行えば、アクセシビリティも犠牲にすることはありません。例えば、 Financial Times は、そのために fastclick というライブラリーを使用しており、これを利用することができます。

- -

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

- -

HTML5 アプリのパフォーマンスに関する大きな問題のひとつに、たくさんの DOM 要素を移動させるとすべてが遅くなるということがあります。見た目をシンプルにして、ドラッグ&ドロップでプロキシー要素を移動させるようにすると非常に有効です。

- -

たとえば、長い要素のリスト (ツイートとします) がある場合、それらをすべて移動させてはいけません。代わりに、表示されているものと、現在表示されているツイートのセットの両側にいくつかあるものだけを DOM ツリーに残します。残りは隠すか削除します。データを DOM にアクセスするのではなく、 JavaScript のオブジェクトに保持することで、アプリのパフォーマンスが大幅に向上します。表示は、データそのものではなく、データのプレゼンテーションだと考えてください。だからといって、 HTML をそのままソースとして使ってはいけないというわけではありません。 HTML を一度読み込んでから 10 個の要素をスクロールさせ、表示されていない 100 個の要素を動かすのではなく、結果リストの中の自分の位置に応じて最初と最後の要素の内容を変えればいいのです。ゲームでは、スプライトにも同じことが言えます。その代わりに、画面外にスクロールした要素を新しいものが入ってきたときに再利用します。

- -

一般的なアプリケーションのパフォーマンス分析

- -

Firefox や Chrome などのブラウザーには、ページの表示速度が遅いことを診断するためのツールが組み込まれています。特に、 Firefox のネットワークモニターは、ページ上のそれぞれのネットワークリクエストがいつ発生し、どれくらいの規模で、どれくらいの時間がかかっているかを正確に時系列で表示します。

- -

Firefox のネットワークモニターが、リクエストの取得、複数のファイル、各リソースの読み込みにかかった時間をグラフで表示しているところ。

- -

ページに実行に時間がかかる JavaScript コードが含まれている場合、 JavaScript プロファイラーは最も遅いコードの行を特定します。

- -

Firefox の JavaScript プロファイラーが完成したプロファイル 1 を表示しているところ。

- -

Gecko 内蔵のプロファイラー は、プロファイラーの実行中にブラウザーのコードのどの部分がゆっくりと動作しているかについて、さらに詳細な情報を提供する非常に便利なツールです。これは使用方法が少し複雑ですが、多くの有用な詳細情報を提供してくれます。

- -

Gecko 内蔵プロファイラーウィンドウが多くのネットワーク情報を表示しているところ。

- -
-

: Android のブラウザーで Firefox を起動し、リモートデバッグを有効にすることで、これらのツールを使用することができます。

-
- -

特に、モバイルブラウザーでは、数十から数百のネットワークリクエストに時間がかかります。また、大きな画像や CSS グラデーションの描画にも時間がかかることがあります。大きなファイルのダウンロードは、高速なネットワークであっても時間がかかることがあります。これは、モバイルハードウェアの速度が遅すぎて、利用可能なすべての帯域幅を活用できない場合があるためです。モバイルウェブのパフォーマンスに関する一般的なヒントについては、 Maximiliano Firtman 氏の Mobile Web High Performance の談話をご覧ください。

- -

テストケースとバグの報告

- -

Firefox や Chrome の開発者ツールで問題が解決しない場合や、ウェブブラウザーが原因と思われる場合は、問題を最大限に分離した縮小版のテストケースを提供してみてください。それが問題の診断に役立つことがよくあります。

- -

HTML ページの静的なコピー (埋め込まれている画像、スタイルシート、スクリプトを含む) を保存、読み込みすることで問題を再現できるかどうかを確認してください。問題が再現できれば、静的ファイルを編集して個人情報を削除し、他の人に送って助けを求めてください (例えば、 Bugzilla レポートを提出するか、サーバーでホスティングして URL を共有してください)。また、上述のツールを使って収集したプロファイリング情報も共有してください。

diff --git a/files/ja/web/performance/fundamentals/index.md b/files/ja/web/performance/fundamentals/index.md new file mode 100644 index 00000000000000..bae7b7d769fc17 --- /dev/null +++ b/files/ja/web/performance/fundamentals/index.md @@ -0,0 +1,197 @@ +--- +title: パフォーマンスの基礎 +slug: Web/Performance/Fundamentals +tags: + - Apps + - Firefox + - Gecko + - Guide + - Performance +translation_of: Web/Performance/Fundamentals +--- +パフォーマンスとは、効率性を意味します。この文書では、オープンウェブアプリの観点から、パフォーマンスとは何か、ブラウザープラットフォームでどのようにパフォーマンスを向上させるか、テストや改善にどのようなツールやプロセスを使用できるかについて一般的な説明をします。. + +## パフォーマンスとは + +最終的には、ユーザーが知覚したパフォーマンスが唯一のパフォーマンスとなります。ユーザーは、触ったり、動かしたり、話したりして、システムに入力を与えます。その代わり、ユーザーは視覚、触覚、聴覚を通じて出力を知覚します。パフォーマンスとは、ユーザーの入力に応じてシステムが出力するものの品質のことです。 + +他の条件が同じであれば、ユーザーが知覚するパフォーマンス (以下、UPP) 以外のターゲットに最適化されたコードは、 UPP に最適化されたコードと競合すると負けてしまいます。ユーザーは、例えば、 1 秒間に 1,000 件しかデータベーストランザクションを処理しないが応答性の高いスムーズに動くアプリの方を、 1 秒間に 100,000,000 件のデータベーストランザクションを処理するカクカクした応答性の低いアプリよりも好みます。もちろん、他の指標を最適化することは決して無意味ではありませんが、実際の UPP ターゲットが最優先です。 + +以下の節では、必須のパフォーマンス指標を指摘し、説明します。 + +### 応答性 + +応答性とは、ユーザーの入力に応じてシステムがどれだけ速く出力 (複数の場合もある) を行うかを意味します。例えば、ユーザーが画面をタップすると、ピクセルが特定の方法で変化することを期待します。この操作の場合、応答性の指標は、タップしてからピクセルが変化するまでの経過時間となります。 + +応答性には、複数の段階のフィードバックが含まれることがあります。アプリケーションの起動は、特に重要なケースの一つで、詳しくは後述します。 + +応答性が重要なのは、人は無視されるとイライラしたり怒ったりするからです。アプリはユーザーの入力に応答しない間、ユーザーを無視していることになります。 + +### フレームレート + +フレームレートとは、システムがユーザーに表示するピクセルを変化させる速度のことです。例えば、毎秒 10 フレームのゲームよりも、毎秒 60 フレームのゲームの方が好きだというのは、理由を説明できなくても、誰もが知っている概念です。 + +フレームレートは「サービスの質」の指標としても重要です。コンピューターのディスプレイは、現実を模倣した光子をユーザーの目に届けることで、ユーザーの目を「欺く」ように設計されています。例えば、文字が印刷された紙は、光子をあるパターンでユーザーの目に反射させます。リーダーアプリは、ピクセルを操作することで、同じようなパターンで光子を放出し、ユーザーの目を「騙す」のです。 + +脳は考えるとき、動きはギクシャクしたバラバラなものではなく、滑らかに連続して更新されるものだと考えます。 (ストロボはそれを逆手に取り、脳の入力を奪って離散的な現実を錯覚させるから面白いのです)。コンピューターのディスプレイでは、フレームレートが高ければ高いほど、より忠実に現実を再現することができます。 + +> **Note:** 人間は通常、60Hz 以上のフレームレートの違いを知覚することができません。そのため、最近の電子ディスプレイは、60Hz で更新するように設計されています。例えばハチドリには、テレビが途切れ途切れで非現実的に見えることでしょう。 + +### メモリーの使用 + +**メモリーの使用量**も重要な指標です。応答性やフレームレートとは異なり、ユーザーはメモリー使用量を直接知覚することはありませんが、メモリー使用量は「ユーザーの状態」に近いものです。理想的なシステムでは、ユーザーの状態を常に 100% 維持することができます。システム内のすべてのアプリケーションは同時に実行され、すべてのアプリケーションは、ユーザーが最後にアプリケーションを操作したにユーザーが設定した状態を維持します (アプリケーションの状態はコンピュータのメモリーに保存されているため、近似値になるのです)。 + +このことから、重要ではあるが直感的ではない副産物が得られます。設計の優れたシステムは、**空き**メモリー量を最大化しません。メモリーは資源であり、空きメモリーは使われていない資源であるからです。むしろ、設計の優れたシステムは、ユーザーの状態を維持するために可能な限り多くのメモリーを使用し、かつ他の UPP 目標を満たすように最適化されています。 + +これは、システムがメモリーを**浪費**すべきだという意味ではありません。システムがある特定のユーザーの状態を維持するために必要以上のメモリーを使用すると、システムは他のユーザーの状態を維持するために使用できる資源を浪費していることになります。実際には、すべてのユーザーの状態を維持できるシステムはありません。ユーザーの状態に賢くメモリーを割り当てることは、以下で詳しく説明する重要な問題です。 + +### 電力使用量 + +ここで解説する最後の指標は、**電力使用量**です。メモリー使用量と同様に、ユーザーは、端末が他のすべての UPP 目標を維持できる時間という形で、電力使用量を間接的にしか認識しません。 UPP 目標を達成するためには、システムは必要最小限の電力しか使用しないようにする必要があります。 + +この文書の残りの部分では、これらの指標の観点からパフォーマンスについて説明します。 + +## プラットフォームのパフォーマンスの最適化 + +この節では、 Firefox/Gecko が、すべてのアプリケーションのレベルよりも下位で、一般的にどのようにパフォーマンスに貢献しているかを簡単に説明します。開発者やユーザーの視点から、「プラットフォームは何をしてくれるのか?」という問いに答えます。 + +### ウェブ技術 + +ウェブプラットフォームには多くのツールが用意されていますが、中には特定の仕事に適したものもあります。アプリケーションロジックはすべて JavaScript で書かれています。グラフィックの表示には、 (高水準の宣言型言語である) HTML や CSS を使用するか、低レベルの命令型インターフェースである {{ htmlelement("canvas") }} 要素 ([WebGL](/ja/docs/Web/API/WebGL_API) を含む) を使用します。 HTML/CSS と Canvas の「中間」に位置するのが [SVG](/ja/docs/Web/SVG) で、両者の利点を兼ね備えています。 + +HTML や CSS は、フレームレートやピクセルレベルでのレンダリング制御を犠牲にして、生産性を大幅に向上させます。テキストや画像は自動的に再フローされ、 UI 要素には自動的にシステムのテーマが適用されます。また、このシステムは、様々な解像度のディスプレイや右書きの言語など、開発者が最初に思いつかないような使用方法に「組み込み」で対応します。 + +`canvas` 要素は、開発者が直接描画できるピクセルバッファーを提供します。これにより、開発者はピクセルレベルでレンダリングを制御し、フレームレートを正確に制御することができますが、複数の解像度や方向、右書きの言語などに対応する必要があります。開発者は、おなじみの 2D 描画 API か、 OpenGL ES 2.0 をほぼ踏襲した「金属に近い」バインディングである WebGL を使用してキャンバスに描画します。 + +> **Note:** Firefox OS は、 [HTML](/ja/docs/Web/HTML)、[CSS](/ja/docs/Web/CSS)、[JavaScript](/ja/docs/Web/JavaScript) などのウェブ技術で作られたアプリに最適化されています。一握りの基本的なシステムサービスを除いて、 Firefox OS で動作するすべてのコードはウェブアプリと Gecko エンジンから来ています。 OS のウィンドウマネージャも HTML、CSS、JavaScript で書かれています。コアとなる OS とアプリケーションは同じウェブ技術で構築されているため、これらの技術がどのように機能するかが重要になります。そこには「逃げ道」はありません。これは開発者にとって大きなメリットです。なぜなら、サードパーティのアプリケーションは、 OS が独自に行ったすべての最適化の恩恵を受けることができるからです。プリインストールされたコードだけが利用できる「魔法のパフォーマンスソース」はありません。 Firefox OS に関する詳細は、 [Firefox OS のパフォーマンステスト](/ja/docs/Archive/B2G_OS/Firefox_OS_apps/Performance/Firefox_OS_performance_testing)をご覧ください。 + +### Gecko のレンダリング + +Gecko の JavaScript エンジンは、実行時 (JIT) コンパイルに対応しています。これにより、アプリケーションロジックは、Java 仮想マシンのような他の仮想マシンと同等の性能を発揮し、場合によっては「ネイティブコード」に近い性能を発揮します。 + +HTML、CSS、Canvas を支える Gecko のグラフィックパイプラインは、いくつかの方法で最適化されています。 Gecko の HTML/CSS レイアウトおよびグラフィックコードは、スクロールなどの一般的なケースでは、無効化や再描画を削減しますが、開発者はこのサポートを「無料」で受けることができます。 Gecko が「自動的に」描画したり、 `canvas` へアプリケーションが「手動で」描画したりするピクセルバッファーは、ディスプレイのフレームバッファーに描画される際のコピーを最小限に抑えます。これは、中間サーフェスがオーバーヘッドになるような場所 (他の多くのオペレーティングシステムにおけるアプリケーションごとの「バックバッファー」など) を避け、コンポジターハードウェアが直接アクセスできるグラフィックバッファー用の特別なメモリーを使用することで実現されています。複雑なシーンのレンダリングには、端末の GPU を使用して最大のパフォーマンスを発揮します。電力消費を抑えるために、シンプルなシーンは専用の合成ハードウェアを使ってレンダリングし、 GPU はアイドルまたはオフにしています。 + +リッチアプリケーションでは、完全な静的コンテンツは例外です。リッチアプリケーションでは、アニメーションやトランジション効果のある動的コンテンツを使用します。トランジションやアニメーションは、アプリケーションにとって特に重要です。開発者は、 CSS を使用することで、複雑な動作をシンプルで高レベルな構文で宣言することができます。また、 Gecko のグラフィックパイプラインは、一般的なアニメーションを効率的に描画するように高度に最適化されています。良くあるアニメーションは、システムコンポジターにオフロードされ、パフォーマンスと電力効率に優れた方法でレンダリングされます。 + +アプリの起動時のパフォーマンスは、実行時のパフォーマンスと同じくらい重要です。 Gecko は、 Web 全体を含むさまざまなコンテンツを効率的に読み込むように最適化されています。並列 HTML 解析、再フローと画像デコーディングのインテリジェントなスケジューリング、巧妙なレイアウトアルゴリズムなど、コンテンツを対象とした長年の改良は、Firefox でのウェブアプリケーションの改良にも同様に反映されます。 + +> **Note:** 起動時のパフォーマンスをさらに向上させるための Firefox OS の仕様についての詳細は、 [Firefox OS パフォーマンステスト](/ja/docs/Archive/B2G_OS/Firefox_OS_apps/Performance/Firefox_OS_performance_testing)を参照してください。 + +## アプリケーションのパフォーマンス + +この節では、「どうしたらアプリを高速にできるのか」という開発者の問いのためのものです。 + +### 起動時のパフォーマンス + +アプリケーションの起動は、一般的に 3 つのイベントで構成されています。 + +- 1 つ目は、アプリケーションの**ファーストペイント** (最初のフレームを描くのに十分なアプリケーションリソースが読み込まれた時点) です。 +- 2 つ目は、アプリケーションが操作可能になった時点です。例えば、ユーザーがボタンをタップすると、アプリケーションが反応するようになります。 +- 最後のイベントは**完全読み込み**です。たとえば、音楽プレイヤーにユーザーのアルバムをすべて表示された時点です。 + +高速な起動の鍵となるのは、 2 つのことを念頭に置くことです。 UPP がすべてであること、そして上記のユーザーが知覚する各イベントには「クリティカルパス」が存在することです。クリティカルパスとは、まさに、そのイベントを発生させるために実行しなければならないコードのことです。 + +例えば、アプリケーションの最初のフレームを視覚的に描くためには、いくつかの HTML と、その HTML にスタイル付けする CSS で構成されます。 + +1. HTML を解釈する必要がある +2. その HTML の DOM を構築する必要がある +3. DOM の一部にある画像などのリソースを読み込み、デコードする必要がある +4. CSS のスタイルをその DOM に適用する必要がある +5. スタイル付けした文書を再フローさせる必要がある + +このリストのどこにも、「一般的でないメニューに必要な JS ファイルの読み込み」や「ハイスコアリスト用の画像の取得とデコード」などは含まれていません。これらの作業項目は、最初のフレームを描くためのクリティカルパスには含まれていません。 + +当たり前のようですが、ユーザーが認識する起動イベントに早く到達するためには、*クリティカルパス上のコードだけ*を実行することが主な「コツ」です。その場面を単純化することで、クリティカルパスを短縮します。 + +ウェブプラットフォームは非常にダイナミックです。 JavaScript は動的に型付けされる言語であり、ウェブプラットフォームではコード、HTML、CSS、画像などのリソースを動的に読み込むことができます。これらの機能を利用して、起動後しばらくしてから不要なコンテンツを「遅延して」読み込むことで、クリティカルパスから外れた作業を先送りすることができます。 + +起動を遅らせるもう 1 つの問題は、リクエストに対するレスポンス (データベースのロードなど) を待つことで発生するアイドルタイムです。この問題を避けるために、アプリケーションは起動時にできるだけ早くリクエストを発行する必要があります (これを「フロントローディング」と呼びます)。そうすれば、後でデータが必要になったとき、うまくいけばすでに利用可能で、アプリケーションは待つ必要がありません。 + +> **Note:** 起動時のパフォーマンスを向上させるための詳しい情報は、[起動時のパフォーマンスを最適化する](/ja/docs/Web/Performance/Optimizing_startup_performance)をご覧ください。 + +また、ローカルにキャッシュされた静的なリソースは、高レイテンシー、低帯域幅のモバイルネットワークを介して取得された動的なデータよりもはるかに速く読み込まれることに注意してください。ネットワークへのリクエストは、アプリケーションの早期起動のためのクリティカルパスであってはなりません。ローカルキャッシュ/オフラインアプリケーションは、[サービスワーカー](/ja/docs/Web/API/Service_Worker_API)によって実現できます。その方法については、 [サービスワーカーで PWA をオフライン対応させる](/ja/docs/Web/Progressive_web_apps/Offline_Service_workers) を参照してください。 + +### フレームレート + +高フレームレートを実現するためにまず重要なのは、適切な道具を選ぶことです。静止画やスクロール、アニメーションの頻度が少ないコンテンツの実装には、 HTML と CSS を使用します。レンダリングを厳密にコントロールする必要があり、テーマ性を必要としないゲームのように、高度に動的なコンテンツを実装する場合は、キャンバスを使用します。 + +キャンバスで描かれたコンテンツでは、フレームレートの目標値を達成できるかどうかは、開発者次第です。 + +HTML と CSS のコンテンツでは、適切なプリミティブを使用することが高フレームレートへの道となります。 Firefox は任意のコンテンツをスクロールするために高度に最適化されているため、通常はこの点を気にする必要はありません。しかし、 CSS の放射状グラデーションの代わりに静的なレンダリングを使用するなど、速度のために汎用性や品質を犠牲にすると、スクロールのフレームレートが目標値を超えてしまうことがよくあります。 CSS の[メディアクエリー](/ja/docs/Web/CSS/Media_Queries/Using_media_queries)を使えば、こうした妥協を必要とする端末だけに制限することができます。 + +多くのアプリケーションでは、「ページ」や「パネル」を使ったトランジションやアニメーションが使われています。例えば、ユーザーが「設定」ボタンをタップすると、アプリケーションの設定画面に遷移したり、設定メニューが「ポップアップ」したりします。 Firefox は、以下のようなシーンの遷移やアニメーションに高度に最適化されています。 + +- 端末の画面サイズ以下のページ/パネルを使用する +- CSS 変換や不透明度のプロパティを使った遷移やアニメーションを使用する + +これらのガイドラインに従った遷移やアニメーションは、システムコンポジターにオフロードされ、最大限効率的に動作します。 + +### メモリーと電力の使用量 + +メモリーと電力使用量の改善は、スタートアップの高速化と同じような問題です。必要のない作業をしたり、普段使わない UI リソースをダラダラとロードしたりしてはいけません。効率的なデータ構造を使用し、画像などのリソースをしっかりと最適化しましょう。 + +最近の CPU は、ほとんどアイドル状態の時に低消費電力モードに入ることができます。常にタイマーを作動させたり、不要なアニメーションを実行し続けるアプリケーションは、 CPU が低電力モードに入るのを妨げます。電力効率の良いアプリケーションは、そのようなことをしてはいけません。 + +アプリケーションがバックグラウンドに送られると、その文書に対して {{event("visibilitychange")}} イベントが発行されます。このイベントは開発者の味方です。アプリケーションはこのイベントに耳を傾けるべきです。バックグラウンドに送られたときに、アプリケーションが読み込まれたリソースをできるだけ多く手放すと、メモリー使用量が少なくて済み、 Firefox OS の場合、廃棄される可能性も低くなります (以下のメモを参照)。これはつまり、 (すでに実行されているため) 「起動」が速く、 UPP が良いことを意味します。 + +> **Note:** 前述のとおり、 Firefox OS はできる限り多くのアプリケーションを同時に実行するようにしていますが、通常は端末のメモリーが不足したときにアプリケーションを破棄しなければならないことがあります。Firefox OS がどのようにメモリー使用量を管理し、メモリー不足の問題が発生したときにアプリケーションを終了するかについての詳細は、「[Debugging out of memory errors on Firefox OS](/ja/docs/Archive/B2G_OS/Debugging/Debugging_OOMs)」を参照してください。 + +### アプリケーションのパフォーマンスのためのコーディングのコツ + +以下の実用的なヒントは、前述のアプリケーションのパフォーマンス要因の 1 つまたは複数を改善するのに役立ちます。 + +#### CSS アニメーションとトランジションを使用する + +一部のライブラリーの `animate()` 関数は、おそらく現在、パフォーマンスが悪い数多くの技術 (例えば {{domxref("WindowOrWorkerGlobalScope.setTimeout")}} や `top`/`left` による位置指定) を使用しています。代わりに [CSS アニメーション](/ja/docs/Web/CSS/CSS_Animations/Using_CSS_animations)を使用してください。多くの場合、実際には [CSS トランジション](/ja/docs/Web/CSS/CSS_Transitions/Using_CSS_transitions)を使って実現することができます。ブラウザーはこれらの効果を最適化するように設計されており、 GPU を使用してプロセッサーのパフォーマンスへの影響を最小限に抑えながらスムーズに処理することができるため、うまく機能します。もう一つの利点は、標準化された構文を使って、アプリの他のルック&フィールと一緒に CSS でこれらの効果を定義できることです。 + +CSS アニメーションでは、 [キーフレーム](/ja/docs/Web/CSS/@keyframes)を使って効果を細かく制御することができます。また、アニメーション処理中に発生するイベントを監視して、アニメーション処理中の特定のポイントで実行する必要のある他のタスクを処理することもできます。これらのアニメーションは、 {{cssxref(":hover")}}, {{cssxref(":focus")}}, {{cssxref(":target")}} を使ったり、親要素に動的にクラスを追加したり削除したりすることで、簡単に起動することができます。 + +アニメーションをその場で作成したり、 [JavaScript](/ja/docs/Web/JavaScript) で修正したりしたい場合は、 James Long 氏が [CSS-animations.js](https://github.com/jlongster/css-animations.js/) というシンプルなライブラリーを作成していますので、そちらをご利用ください。 + +#### CSS 変換を使用する + +コンテンツの位置やスケールなどを調整するのに、絶対位置を調整したり、すべての計算を自分で行ったりする代わりに、 CSS の {{cssxref("transform")}} プロパティを使用しましょう。その理由は、繰り返しになりますが、ハードウェアアクセラレーションです。ブラウザーはこれらの作業を GPU で行い、 CPU に他の処理をさせることができます。 + +さらに、変換は、他では得られない機能を提供します。 2D 空間の要素を変換するだけでなく、 3 次元に変換したり、斜めにしたり、回転させたりすることができます。 Paul Irish 氏は、パフォーマンスの観点から見た [`translate()` の利点を詳しく分析](https://paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/)しています。しかし、一般的には、 CSS アニメーションを使用する場合と同じメリットがあります。つまり、仕事に適したツールを使用し、最適化はブラウザーに任せることができるのです。また、要素の位置を簡単に拡張できる方法を使用しています。 `top` と `left` の位置指定で変換をシミュレートする場合は、多くの追加コードが必要になります。もうひとつの利点は、 `canvas` 要素で作業するのと同じだということです。 + +> **Note:** プラットフォームによっては、 CSS アニメーションでハードウェアアクセラレーションを利用したい場合、 `translateZ(0.1)` 変換を割り当てる必要があります。前述のとおり、パフォーマンスが向上しますが、メモリー消費の問題もあります。テストをして、自分のアプリケーションに最適な方法を見つけてみてはいかがでしょうか。 + +#### `requestAnimationFrame()` を `setInterval()` の代わりに使用する + +{{domxref("WindowOrWorkerGlobalScope.setInterval")}} の呼び出しは、現在の状況下で可能かどうかわからない推定フレームレートでコードを実行します。このコードは、ブラウザーが実際に描画していない間、つまりビデオハードウェアが次の表示サイクルに達していない間にも、結果をレンダリングするようブラウザーに指示します。これはプロセッサー時間を浪費し、ユーザーの端末のバッテリー寿命を縮めることにもつながります。 + +その代わりに、 {{domxref("window.requestAnimationFrame()")}} を使うようにしましょう。これは、ブラウザーがアニメーションの次のフレームを作り始める準備ができるまで待機し、ハードウェアが実際に何も描画しない場合は無視します。この API のもう一つの利点は、アプリが画面上に表示されていない間はアニメーションが実行されないことです (バックグラウンドで他のタスクが動作している場合など)。これにより、バッテリーの消費を抑え、ユーザーが夜空に向かってあなたの名前を罵るのを防ぐことができます。 + +#### イベントを即時にする + +アクセシビリティに配慮した古いタイプのウェブ開発者は、キーボード入力二も対応する click イベントが大好きです。モバイル端末では、これらのイベントは遅すぎます。代わりに {{event("touchstart")}} と {{event("touchend")}} を使うべきです。これらのイベントには、アプリの操作を鈍くする遅延がないからです。最初にタッチ対応のテストを行えば、アクセシビリティも犠牲にすることはありません。例えば、 Financial Times は、そのために [fastclick](https://github.com/ftlabs/fastclick) というライブラリーを使用しており、これを利用することができます。 + +#### インターフェイスをシンプルに保つ + +HTML5 アプリのパフォーマンスに関する大きな問題のひとつに、たくさんの [DOM](/ja/docs/Web/API/Document_Object_Model) 要素を移動させるとすべてが遅くなるということがあります。見た目をシンプルにして、ドラッグ&ドロップでプロキシー要素を移動させるようにすると非常に有効です。 + +たとえば、長い要素のリスト (ツイートとします) がある場合、それらをすべて移動させてはいけません。代わりに、表示されているものと、現在表示されているツイートのセットの両側にいくつかあるものだけを DOM ツリーに残します。残りは隠すか削除します。データを DOM にアクセスするのではなく、 JavaScript のオブジェクトに保持することで、アプリのパフォーマンスが大幅に向上します。表示は、データそのものではなく、データのプレゼンテーションだと考えてください。だからといって、 HTML をそのままソースとして使ってはいけないというわけではありません。 HTML を一度読み込んでから 10 個の要素をスクロールさせ、表示されていない 100 個の要素を動かすのではなく、結果リストの中の自分の位置に応じて最初と最後の要素の内容を変えればいいのです。ゲームでは、スプライトにも同じことが言えます。その代わりに、画面外にスクロールした要素を新しいものが入ってきたときに再利用します。 + +## 一般的なアプリケーションのパフォーマンス分析 + +Firefox や Chrome などのブラウザーには、ページの表示速度が遅いことを診断するためのツールが組み込まれています。特に、 [Firefox のネットワークモニター](/ja/docs/Tools/Network_Monitor)は、ページ上のそれぞれのネットワークリクエストがいつ発生し、どれくらいの規模で、どれくらいの時間がかかっているかを正確に時系列で表示します。 + +![Firefox のネットワークモニターが、リクエストの取得、複数のファイル、各リソースの読み込みにかかった時間をグラフで表示しているところ。](network-monitor.jpg) + +ページに実行に時間がかかる JavaScript コードが含まれている場合、 [JavaScript プロファイラー](/ja/docs/Tools/Performance)は最も遅いコードの行を特定します。 + +![Firefox の JavaScript プロファイラーが完成したプロファイル 1 を表示しているところ。](javascript-profiler.png) + +[Gecko 内蔵のプロファイラー](/ja/docs/Performance/Profiling_with_the_Built-in_Profiler) は、プロファイラーの実行中にブラウザーのコードのどの部分がゆっくりと動作しているかについて、さらに詳細な情報を提供する非常に便利なツールです。これは使用方法が少し複雑ですが、多くの有用な詳細情報を提供してくれます。 + +![Gecko 内蔵プロファイラーウィンドウが多くのネットワーク情報を表示しているところ。](gecko-profiler.png) + +> **Note:** Android のブラウザーで Firefox を起動し、[リモートデバッグ](/ja/docs/Tools/Remote_Debugging)を有効にすることで、これらのツールを使用することができます。 + +特に、モバイルブラウザーでは、数十から数百のネットワークリクエストに時間がかかります。また、大きな画像や CSS グラデーションの描画にも時間がかかることがあります。大きなファイルのダウンロードは、高速なネットワークであっても時間がかかることがあります。これは、モバイルハードウェアの速度が遅すぎて、利用可能なすべての帯域幅を活用できない場合があるためです。モバイルウェブのパフォーマンスに関する一般的なヒントについては、 Maximiliano Firtman 氏の [Mobile Web High Performance](https://www.slideshare.net/firt/mobile-web-high-performance) の談話をご覧ください。 + +### テストケースとバグの報告 + +Firefox や Chrome の開発者ツールで問題が解決しない場合や、ウェブブラウザーが原因と思われる場合は、問題を最大限に分離した縮小版のテストケースを提供してみてください。それが問題の診断に役立つことがよくあります。 + +HTML ページの静的なコピー (埋め込まれている画像、スタイルシート、スクリプトを含む) を保存、読み込みすることで問題を再現できるかどうかを確認してください。問題が再現できれば、静的ファイルを編集して個人情報を削除し、他の人に送って助けを求めてください (例えば、 [Bugzilla](https://bugzilla.mozilla.org/) レポートを提出するか、サーバーでホスティングして URL を共有してください)。また、上述のツールを使って収集したプロファイリング情報も共有してください。 diff --git a/files/ja/web/performance/how_browsers_work/index.html b/files/ja/web/performance/how_browsers_work/index.html deleted file mode 100644 index 93404959420edc..00000000000000 --- a/files/ja/web/performance/how_browsers_work/index.html +++ /dev/null @@ -1,216 +0,0 @@ ---- -title: 'ページの生成: ブラウザーの動作の仕組み' -slug: Web/Performance/How_browsers_work -tags: - - Browsers - - Compositing - - Critical rendering path - - DNS Lookup - - Navigation - - Page load - - Painting - - SSL/TLS Handshake - - TCP handshake - - Web Performance - - render -translation_of: Web/Performance/How_browsers_work ---- -

ユーザーは、読み込みが速く、スムーズに操作できるコンテンツを、ウェブで体験することを求めています。したがって、開発者はこれらふたつの目標を達成するために努力しなければいけません。

- -

どうやって性能そして体感性能を改善するか理解するためには、ブラウザーがどのように動作するかを理解することが役に立ちます。

- -

概要

- -

速いサイトはより良いユーザー体験をもたらします。ユーザーは読み込みが速く、スムーズに操作できるコンテンツを体験することを求め、期待しています。

- -

ウェブの性能における 2 つの主要な課題は、レイテンシーに関する諸問題と、多くの場合ブラウザーはシングルスレッドであるという事実に関する諸問題を理解することです。

- -

レイテンシーは、速い読み込みを実現するために克服しなければいけない一番の脅威です。読み込みを速くしようとする開発者のゴールは、リクエストされた情報をできる限り速く送信すること、または少なくともとても速いように見せることです。ネットワークのレイテンシーは、バイト情報をコンピューターまで送信するのにかかる時間のことです。ウェブの性能は、ページの読み込みを出来る限り速くするよう私たちが何をするかにかかっています。

- -

多くの場合、ブラウザーはシングルスレッドだと考えられます。スムーズな操作を実現しようとする開発者のゴールは、滑らかなスクロール、タッチ操作への反応など、期待通りのサイトの操作を実現することです。メインスレッドが全ての処理を時間内に完了し、その上でユーザーの操作を常にハンドリングできるよう保証するために、描画時間が鍵となります。ブラウザーがシングルスレッドであることによる特性を理解し、メインスレッドの責務を最小限に抑え、可能かつ適切な場合に、描画のスムーズさと操作への即時の反応を実現することで、ウェブの性能が改善されます。

- - - -

ナビゲーションはウェブページを読み込むための最初の一歩です。ユーザーが URL をアドレスバーに入力したり、リンクをクリックしたり、またはフォームを送信したり、ページをリクエストするたびごとにナビゲーションが発生します。

- -

ウェブの性能における目標の 1 つは、ナビゲーションが完了するまでの時間を最小限にすることです。理想的な条件下において、一般的にこの時間が長すぎることはありませんが、レイテンシーと帯域幅が遅延を引き起こす邪魔者になる場合があります。

- -

DNS ルックアップ

- -

ウェブページへのナビゲーションの最初の一歩は、ページのアセットがどこにあるか見つけることです。https://example.com へアクセスする場合、その HTML のページは IP アドレスが 93.184.216.34 のサーバーに存在します。これまでに一度もそのサイトを訪れたことがなかった場合、DNS ルックアップが必要になります。

- -

ブラウザーが DNS ルックアップをリクエストし、そのリクエストは最終的にネームサーバーによって処理され、ネームサーバーが IP アドレスを返します。この最初のリクエストの後、多くの場合その IP アドレスはしばらくの間キャッシュされ、ネームサーバーへ再接続する代わりにキャッシュから IP アドレスを取得することによって、後続するリクエストの速度を向上します。

- -

DNS ルックアップは、一般的に、1 回のページ読み込みの中でホスト名ごとに 1 回だけ必要になります。しかし、DNS ルックアップは要求されたページが参照するユニークなホストネームそれぞれに対して実行が必要です。必要なフォントや画像、スクリプト、広告、メトリクスのそれぞれが異なるホスト名を持っている場合は、それぞれに対して DNS ルックアップが必要です。

- -

携帯電話のリクエストは、まずセルタワーに送られ、次に電話会社の中央コンピューターに送られた後、インターネットに送信される

- -

これはとくにモバイルネットワークにおいて性能上の問題になる可能性があります。ユーザーがモバイルネットワークを利用している場合、DNS ルックアップは、権威 DNS サーバーへ到達するために、電話機から基地局へ送信される必要があります。電話機と基地局、そしてネームサーバー間の距離によって重大な遅延が発生する場合があります。

- -

TCP ハンドシェイク

- -

IP アドレスが判明すると、ブラウザーは {{glossary('TCP handshake','TCP 3 ウェイハンドシェイク')}}を通じてサーバーとのコネクションを設定します。この仕組みは、通信を意図する 2 つの主体が—この場合はブラウザーとウェブサーバーが—、データを送信する前に、多くの場合 {{glossary('HTTPS')}} を用いて、ネットワーク TCP ソケットコネクションのパラメーターを交換できるよう設計されています。

- -

TCP の 3 ウェイハンドシェイクは、しばしば、"SYN-SYN-ACK"、より正確には SYN、SYN-ACK、ACK と呼ばれます。これは 2 つのコンピューターの間で TCP のセッションを開始するために、TCP によって 3 つのメッセージが送受信されることを表します。つまり、これはそれぞれのサーバーの間で 3 回以上のメッセージのやりとりが必要であり、そのためのリクエストが生成されなければいけないことを意味しています。

- -

TLS ネゴシエーション

- -

HTTPS によって確立される安全なコネクションでは、もう 1 つのハンドシェイクが必要です。このハンドシェイク、より正確に言うと {{glossary('TLS')}} ネゴシエーションは、通信の暗号化に使用する暗号の種類を決定し、サーバーを認証し、実際のデータ送信が始まる前に安全な通信の準備を整えます。この処理は、コンテンツのリクエストを実際に送信する前に、さらに 3 回のラウンドトリップを必要とします。

- -

DNS ルックアップ、TCP ハンドシェイク、そして TLS ハンドシェイクの 5 つのステップ (clienthello、serverhello、証明書、clientkey、サーバーとクライアントの両方の完了)。

- -

通信を安全にするためにページ読み込みの時間が追加されますが、ブラウザーとサーバーの間で送信されるデータが第三者に解読されないという安全な通信は、レイテンシーに見合う価値があるものです。

- -

8 回のラウンドトリップを経て、ブラウザーはようやくリクエストを送ることができます。

- -

レスポンス

- -

ウェブサーバーへのコネクションが確立されると、ブラウザーはユーザーに代わって最初の HTTP GET リクエストを送信します。ウェブサイトであれば、多くの場合その対象は HTML ファイルです。リクエストを受け取ったサーバーは、適当なレスポンスヘッダーと HTML のコンテンツを返します。

- -
<!doctype HTML>
-<html>
- <head>
-  <meta charset="UTF-8"/>
-  <title>My simple page</title>
-  <link rel="stylesheet" src="styles.css"/>
-  <script src="myscript.js"></script>
-</head>
-<body>
-  <h1 class="heading">My Page</h1>
-  <p>A paragraph with a <a href="https://example.com/about">link</a></p>
-  <div>
-    <img src="myimage.jpg" alt="image description"/>
-  </div>
-  <script src="anotherscript.js"></script>
-</body>
-</html>
- -

この最初のリクエストへのレスポンスは、受信データの最初のバイト (First Byte) を含んでいます。{{glossary('Time to First Byte')}} (TTFB) は、ユーザーがリクエストを実行した時点から—たとえば、リンクをクリックした時点から— HTML の最初のパケットを受信するまでの時間を表します。コンテンツの最初のかたまり (Chunk) は一般的に 14kB のデータです。

- -

上記のサンプルコードでは、リクエストされたコンテンツは明らかに 14kB より小さいですが、後述するように、リンクされたリソースは、ブラウザーのパース処理がそのリンクにたどり着くまでリクエストされることはありません。

- -

TCP スロースタート / 14kB ルール

- -

最初の応答パケットは 14kB になります。これは、{{glossary('TCP slow start','TCP スロースタート')}}の一部で、ネットワークコネクションの速度を制御するアルゴリズムの影響です。スロースタートは、ネットワークの最大の帯域幅が確定するまで徐々に送信するデータ量が増やします。

- -

{{glossary('TCP slow start','TCP スロースタート')}}において、サーバーは最初のパケットを受信した後、次のパケットのサイズを 28kB に倍増させます。さらに後続のパケットについて事前に決めた上限に達するか、ネットワークの輻輳を検知するまでサイズを増やします。

- -

TCP スロースタート

- -

最初のページ読み込みに関する 14kB ルールを聞いたことがあった場合、それは TCP スロースタートが理由です。そしてこれはウェブの性能の最適化が最初の 14kB にフォーカスする理由でもあります。TCP スロースタートは、ネットワークの輻輳を防ぎ、ネットワーク性能に対して適正なデータ転送速度を徐々に探り出します。

- -

輻輳制御

- -

サーバーが TCP パケットとしてデータを送信する一方で、ユーザー側のクライアントは確認応答、ACK を返してデータが配送されたことを確認します。コネクションには、ハードウェアやネットワークの条件によって許容量上の制限があります。サーバーが大きすぎるパケットを速すぎる速度で送信した場合、破棄されるでしょう。つまり、確認応答がない場合があるということです。サーバーはこれを missing ACK として処理します。輻輳制御アルゴリズムは、パケットを送信して確認応答を受け取るこのフローを使って送信レート (send rate) を決定します。

- -

パース処理

- -

データの最初のかたまりを受け取ると、ブラウザーは受信した情報のパース処理を始めることができます。{{glossary('speculative parsing', 'パース処理')}}は、ネットワークから受信したデータを {{glossary('DOM')}} と {{glossary('CSSOM')}} に変換するステップです。DOM と CSSOM は、レンダラーがページを画面へ描画するために利用されます。

- -

DOM はブラウザー向けのマークアップの内部的な表現です。DOM は外部に公開されており、JavaScript の様々な API を通じて操作できます。

- -

ブラウザーは、リクエストしたページの HTML が最初の 14kB のパケットより大きかった場合でも、手元にあるデータに基づいてパース処理を開始し、サイトを描画しようとします。これは、ウェブの性能を最適化する時にに、ブラウザーがページの描画を始めるために必要なすべてのデータ、あるいは少なくともページのテンプレート (最初の描画に必要となる CSS と HTML) を最初の 14kB に含めることが重要となる理由です。何か 1 つでも画面に描画を行うには、その前に HTML と CSS、JavaScript がパースされなければいけません。

- -

DOM ツリーの構築

- -

クリティカルレンダリングパスの 5 つのステップを説明します。

- -

最初のステップは HTML のマークアップを処理し、DOM ツリーを構築することです。HTML のパース処理は、トークン化とツリーの構築に分かれます。HTML のトークンは開始タグと終了タグ、属性の名前と値を含みます。ドキュメントが正しく構成されていればパース処理は単純で、速度も速くなります。パーサーはトークン化された入力情報をドキュメントツリーを構成するドキュメントに変換します。

- -

DOM ツリーはドキュメントのコンテンツを表します。<html> 要素は最初のタグであり、ドキュメントツリーのルートノードとなります。ツリーには、異なるタグ同士の関係と階層構造が反映されます。他のタグの中にネストされたタグは子要素となります。DOM ノードの数が増えるほど、DOM ツリーの構築にかかる時間は長くなります。

- -

サンプルコードの DOM ツリーで、テキストノードを含むすべてのノードが表示されています。

- -

パーサーが画像のようなノンブロッキングリソースを発見した場合、ブラウザーはそのリソースをリクエストし、そのままパース処理を継続します。CSS ファイルに遭遇した場合もパース処理を継続できます、しかし async または defer 属性がない <script> タグはレンダリングをブロックし、HTML のパース処理を停止します。ブラウザーのプリロードスキャナーがブロックの時間を減らしますが、それでも過度のスクリプトの使用は重大なボトルネックになり得ます。

- -

プリロードスキャナー

- -

ブラウザーが DOM ツリーを構築する間はそのプロセスがメインスレッドを占有します。その間にプリロードスキャナーが処理可能なコンテンツをパースし、CSS や JavaScript、ウェブフォントのような優先度の高いリソースのリクエストを行います。プリロードスキャナーのおかげで、リクエストするべき外部リソースへの参照をパーサーが見つけるのを待たなくて良くなります。バックグラウンドでリソースを取得するため、メインの HTML パーサーが該当のアセットにたどり着いた時には、すでにそれらのリソースが転送中あるいはダウンロード済みになっています。プリロードスキャナーによる最適化によりブロッキングを減らすることができます。

- -
<link rel="stylesheet" src="styles.css"/>
-<script src="myscript.js" async></script>
-<img src="myimage.jpg" alt="image description"/>
-<script src="anotherscript.js" async></script>
-
- -

この例では、メインスレッドが HTML と CSS をパースしている間に、プリロードスキャナーがスクリプトと画像を探索し、それらのダウンロードを開始します。もし JavaScript の実行順序が重要でないなら、スクリプトがプロセスをブロックしないように async 属性または defer 属性を追加しましょう。

- -

CSS の取得は HTML のパース処理あるいはダウンロードをブロックしません。しかし JavaScript の実行をブロックします。その理由は、しばしば JavaScript が CSS プロパティの要素への影響を問い合わせるために使われるからです。

- -

CSSOM の構築

- -

クリティカルレンダリングパスの 2 つめのステップは CSS を処理して CSSOM ツリーを構築することです。CSS のオブジェクトモデルは DOM によく似ています。DOM と CSSOM はどちらもツリー構造です。この 2 つは独立したデータ構造を持ちます。ブラウザーは、CSS のルールをブラウザーが理解できるスタイルのマップに変換します。ブラウザーは CSS のルールセットを読み取り、CSS セレクターにもとづいて、親、子、兄弟の関係から構成されるノードのツリーを生成します。

- -

HTML の場合と同様に、ブラウザーは受信した CSS のルールをブラウザーが実行可能な形式に変換しなければいけません。そのために、ブラウザーは HTML をオブジェクトに変換する場合と同じプロセスを CSS に対しても実行します。

- -

CSSOM ツリーはユーザーエージェントのスタイルシートから取得したスタイルを含みます。ブラウザーは、ノードに対して適用される最も一般的なルールからスタートして、より特定されたルールを再帰的に適用し、最終的なスタイルを計算します。つまり、プロパティの値をカスケードします。

- -

CSSOM の構築はとても高速であるため、現在の開発者ツールはそれ自体をユニークな色で表示しません。その代わりに、開発者ツールの「スタイルの再計算」は、CSS を解析して CSSOM ツリーを構築し、再帰的にスタイルを計算するトータルの時間を表示します。ウェブの性能の最適化の観点から言うと、CSSOM を生成するトータルの時間は一般的に1回の DNS ルックアップにかかる時間よりも少ないため、それほどの苦労はないと言えます。

- -

その他の処理

- -

JavaScript のコンパイル

- -

CSS がパースされ、CSSOM が生成される間、JavaScript ファイルを含む他のアセットが(プリロードスキャナーによって)ダウンロードされます。JavaScript は、インタープリターに処理され、コンパイル、パース処理を経て実行されます。スクリプトはパース処理によって抽象構文木に変換されます。いくつかのブラウザーエンジンは、{{glossary('Abstract Syntax Tree', '抽象構文木')}}をインタープリターへ引き渡し、メインスレッドで実行されるバイトコードを出力します。これが JavaScript のコンパイル処理に当たります。

- -

アクセシビリティツリーの構築

- -

ブラウザーはコンテンツを理解し翻訳する補助機器で使用されるアクセシビリティツリーも構築します。アクセシビリティオブジェクトモデル (AOM) は補助機器向けの DOM のようなものです。ブラウザーは、DOM が更新されるとアクセシビリティツリーも更新します。アクセシビリティツリーは補助機能それ自体からは変更できません。

- -

AOM が構築されるまで、スクリーンリーダーでコンテンツにアクセスできません。

- -

レンダリング

- -

レンダリングのステップは、スタイル、レイアウト、描画、そして合成で構成されます。パースのステップで作成された CSSOM と DOM のツリーはレンダーツリーの形式へと組み合わされ、すべてのビジュアル要素のレイアウトを計算するために使用されてスクリーンに描画されます。いくつかのケースでは、CPU の代わりに GPU を使用してスクリーンの一部を描画し、メインスレッドを解放してパフォーマンスを改善するために、コンテンツ自身をレイヤーに昇格し、合成を行います。

- -

スタイル

- -

クリティカルレンダリングパスの 3 番目のステップは DOM と CSSOM をレンダーツリーの形式へと組み合わせることです。計算されたスタイルのツリー、あるいはレンダーツリー、の構築は DOM ツリーのルートからスタートし、目に見える (Visible) ノードをトラバースします。

- -

ユーザーエージェントのスタイルシートにある <head> のような表示されることないタグとその子要素、script { display: none; } のように display: none を指定されたすべてのノード、はレンダリングの結果に影響しないためレンダーツリーには含まれません。visibility: hidden が適用されたノードは、スペースを確保するためレンダーツリーに含まれます。上記のサンプルコード内の script ノードは、ユーザーエージェントのデフォルトを上書きするディレクティブが指定されていないためレンダーツリーに含まれません。

- -

それぞれの目に見えるノードには、CSSOM のルールが適用されます。レンダーツリーはすべての目に見えるノードをコンテンツと計算されたスタイルを合わせて保持します。すべての関連するスタイルと DOM 上の目に見えるノードをマッチングし、CSS カスケードに基づいて、それぞれのノードに対応する計算されたスタイルを決定します。

- -

レイアウト

- -

クリティカルレンダリングパスの 4 番目のステップは各ノードの平面状の位置を計算するためにレイアウト処理を実行することです。レイアウトはレンダーツリーに含まれるすべてのノードの幅と高さ、位置を決める処理です。さらにページ上のそれぞれオブジェクトのサイズと位置を決定します。再フローは、続いて発生するドキュメント全体、あるいはページの一部分のサイズと位置を決める処理です。

- -

レンダーツリーが構築されるとすぐにレイアウトが始まります。レンダーツリーは計算されたスタイルを踏まえてどのノードが表示されるか (非表示であっても) 特定しますが、寸法や位置は特定しません。各オブジェクトの正確なサイズと位置を決めるために、ブラウザーがレンダーツリーのルートからトラバースを行います。

- -

ウェブページ上では、ほとんどすべての要素はボックスです。異なるデバイス、異なるデスクトップの設定は、ビューポートのサイズの数が無制限に存在することを示しています。このフェーズにおいて、ビューポートのサイズを考慮して、ブラウザーはすべての異なるボックスのスクリーン上の寸法を決定します。ビューポートのサイズを基本として、レイアウトは一般的にボディからスタートし、すべてのボディの子孫をそれぞれの要素のボックスモデルプロパティに合わせてレイアウトし、画像のように寸法がわからない代替要素のためのプレースホルダースペースを作成します。

- -

ノードのサイズとポジションが決められる最初のタイミングをレイアウトと呼びます。続いて発生するノードのサイズと位置の再計算を再フロー呼びます。私たちの例では、画像が返される前に最初のレイアウトが発生すると考えられます。画像のサイズを宣言していなかったため、画像のサイズがわかるとすぐに再フローが発生します。

- -

描画

- -

クリティカルレンダリングパスの最後のステップは個別のノードをスクリーンに描画することです。最初に発生する描画を first meaningful paint と呼びます。描画またはラスタライズのフェーズにおいて、ブラウザーはレイアウトフェーズで計算されたそれぞれのボックスをスクリーン上の実際のピクセルに変換します。描画は、テキスト、色、境界、シャドウ、ボタンや画像のような置換要素を含む、要素のすべての視覚的な部分をスクリーンに描くことを含みます。ブラウザーはこれを超高速で実行する必要があります。

- -

スムーズなスクロールとアニメーションを実現するために、スタイルの計算や再フロー、描画などメインスレッドを占有するすべての処理は、16.67ms 未満で完了する必要があります。2048 x 1536 の解像度を持つ iPad は 3,145,000 を超えるピクセルを持っています。それら大量のピクセルは高速に描画されなければいけません。2回目以降の描画を最初の描画より高速にするため、スクリーンへの描画は一般的に複数のレイヤーに分解されます。この場合に合成が必要になります。

- -

描画は描画ツリー内の要素をレイヤーに分解します。コンテンツを GPU (CPU 上のメインスレッドの代わりになる) 上のレイヤーに昇格させることで、描画と再描画のパフォーマンスを向上します。<video><canvas>など、レイヤーを生成する特定のプロパティと要素があります。opacity、3D transformwill-change、その他いくつかの CSS プロパティを持つ要素も同様です。これらのノードは、その子孫が上記の理由でそれ自身のレイヤーを必要とするのでなければ、子孫と一緒に自身のレイヤー上に描画されます。

- -

レイヤーはパフォーマンスを改善しますが、メモリー管理の面ではコストのかかる処理です。そのため、ウェブのパフォーマンス最適化戦略の中で濫用するべきものではありません。

- -

合成

- -

ドキュメントのセクションが異なるレイヤーに描画されて重なり合う場合、コンテンツをスクリーン上に正しい順番で描画するために合成が必要になります。

- -

ページがアセットの読み込みを続ける間も再フローは発生します (後ほど出てくる図を見てください)。再フローは再描画と再合成を引き起こします。画像のサイズを指定していた場合再フローは必要ありません。再描画が必要なレイヤーのみが再描画され、必要があれば合成が行われます。しかし、私たちのサンプルでは画像のサイズを指定しませんでした。画像がサーバーから取得されたとき、レンダリングプロセスはレイアウトステップまで戻り、そこから再開します。

- -

操作可能性

- -

メインスレッドがページの描画を完了したら「これで終わり」と思うかもしれません。しかし、必ずしもそうとは言えません。読み込み処理が、遅延された onload イベントの発行により実行される JavaScript を含む場合、メインスレッドがビジー状態となりスクロールやタッチ、その他の操作ができない場合があります。

- -

{{glossary('Time to Interactive')}} (TTI) は、DNS ルックアップと SSL コネクション を始める最初のリクエストからページが操作可能になるまでどのくらい時間がかかったかを示す測定値です。操作可能であるとは、ページがユーザーの操作に 50ms 以内に応答する {{glossary('First Contentful Paint')}} の後の時点を言います。メインスレッドがパース処理、コンパイル、JavaScript の実行に占有されている場合、ユーザーの操作にタイムリーに (50ms より早く) 応答することができません。

- -

以下の例では、画像の読み込みは高速かもしれませんが、anotherscript.js ファイルが 2MB あり、しかもユーザーのネットワークは低速です。このケースでは、ユーザーはページのコンテンツをすぐに見ることができるかもしれませんが、スクリプトがダウンロードされるまでスクロールを実行できない可能性があります。これは良いユーザー体験とは言えません。この WebPageTest の例からわかるように、メインスレッドを占有することは避けなければいけません。

- -

メインスレッドは javascript ファイルのダウンロード、解析、実行で占められています (高速接続時)。

- -

この例では、DOM コンテンツの読み込みプロセスは 1.5 秒以上かかっており、メインスレッドがすべての時間を完全に占有され、クリックイベントや画面のタップに応答できなくなっています。

- -

関連情報

- - diff --git a/files/ja/web/performance/how_browsers_work/index.md b/files/ja/web/performance/how_browsers_work/index.md new file mode 100644 index 00000000000000..6ac38eb0f87a25 --- /dev/null +++ b/files/ja/web/performance/how_browsers_work/index.md @@ -0,0 +1,217 @@ +--- +title: 'ページの生成: ブラウザーの動作の仕組み' +slug: Web/Performance/How_browsers_work +tags: + - Browsers + - Compositing + - Critical rendering path + - DNS Lookup + - Navigation + - Page load + - Painting + - SSL/TLS Handshake + - TCP handshake + - Web Performance + - render +translation_of: Web/Performance/How_browsers_work +--- +ユーザーは、読み込みが速く、スムーズに操作できるコンテンツを、ウェブで体験することを求めています。したがって、開発者はこれらふたつの目標を達成するために努力しなければいけません。 + +どうやって性能そして体感性能を改善するか理解するためには、ブラウザーがどのように動作するかを理解することが役に立ちます。 + +## 概要 + +速いサイトはより良いユーザー体験をもたらします。ユーザーは読み込みが速く、スムーズに操作できるコンテンツを体験することを求め、期待しています。 + +ウェブの性能における 2 つの主要な課題は、レイテンシーに関する諸問題と、多くの場合ブラウザーはシングルスレッドであるという事実に関する諸問題を理解することです。 + +レイテンシーは、速い読み込みを実現するために克服しなければいけない一番の脅威です。読み込みを速くしようとする開発者のゴールは、リクエストされた情報をできる限り速く送信すること、または少なくともとても速いように見せることです。ネットワークのレイテンシーは、バイト情報をコンピューターまで送信するのにかかる時間のことです。ウェブの性能は、ページの読み込みを出来る限り速くするよう私たちが何をするかにかかっています。 + +多くの場合、ブラウザーはシングルスレッドだと考えられます。スムーズな操作を実現しようとする開発者のゴールは、滑らかなスクロール、タッチ操作への反応など、期待通りのサイトの操作を実現することです。メインスレッドが全ての処理を時間内に完了し、その上でユーザーの操作を常にハンドリングできるよう保証するために、描画時間が鍵となります。ブラウザーがシングルスレッドであることによる特性を理解し、メインスレッドの責務を最小限に抑え、可能かつ適切な場合に、描画のスムーズさと操作への即時の反応を実現することで、ウェブの性能が改善されます。 + +## ナビゲーション + +*ナビゲーション*はウェブページを読み込むための最初の一歩です。ユーザーが URL をアドレスバーに入力したり、リンクをクリックしたり、またはフォームを送信したり、ページをリクエストするたびごとにナビゲーションが発生します。 + +ウェブの性能における目標の 1 つは、ナビゲーションが完了するまでの時間を最小限にすることです。理想的な条件下において、一般的にこの時間が長すぎることはありませんが、レイテンシーと帯域幅が遅延を引き起こす邪魔者になる場合があります。 + +### DNS ルックアップ + +ウェブページへのナビゲーションの最初の一歩は、ページのアセットがどこにあるか見つけることです。`https://example.com` へアクセスする場合、その HTML のページは IP アドレスが `93.184.216.34` のサーバーに存在します。これまでに一度もそのサイトを訪れたことがなかった場合、DNS ルックアップが必要になります。 + +ブラウザーが DNS ルックアップをリクエストし、そのリクエストは最終的にネームサーバーによって処理され、ネームサーバーが IP アドレスを返します。この最初のリクエストの後、多くの場合その IP アドレスはしばらくの間キャッシュされ、ネームサーバーへ再接続する代わりにキャッシュから IP アドレスを取得することによって、後続するリクエストの速度を向上します。 + +DNS ルックアップは、一般的に、1 回のページ読み込みの中でホスト名ごとに 1 回だけ必要になります。しかし、DNS ルックアップは要求されたページが参照するユニークなホストネームそれぞれに対して実行が必要です。必要なフォントや画像、スクリプト、広告、メトリクスのそれぞれが異なるホスト名を持っている場合は、それぞれに対して DNS ルックアップが必要です。 + +![携帯電話のリクエストは、まずセルタワーに送られ、次に電話会社の中央コンピューターに送られた後、インターネットに送信される](latency.jpg) + +これはとくにモバイルネットワークにおいて性能上の問題になる可能性があります。ユーザーがモバイルネットワークを利用している場合、DNS ルックアップは、権威 DNS サーバーへ到達するために、電話機から基地局へ送信される必要があります。電話機と基地局、そしてネームサーバー間の距離によって重大な遅延が発生する場合があります。 + +### TCP ハンドシェイク + +IP アドレスが判明すると、ブラウザーは {{glossary('TCP handshake','TCP 3 ウェイハンドシェイク')}}を通じてサーバーとのコネクションを設定します。この仕組みは、通信を意図する 2 つの主体が—この場合はブラウザーとウェブサーバーが—、データを送信する前に、多くの場合 {{glossary('HTTPS')}} を用いて、ネットワーク TCP ソケットコネクションのパラメーターを交換できるよう設計されています。 + +TCP の 3 ウェイハンドシェイクは、しばしば、"SYN-SYN-ACK"、より正確には SYN、SYN-ACK、ACK と呼ばれます。これは 2 つのコンピューターの間で TCP のセッションを開始するために、TCP によって 3 つのメッセージが送受信されることを表します。つまり、これはそれぞれのサーバーの間で 3 回以上のメッセージのやりとりが必要であり、そのためのリクエストが生成されなければいけないことを意味しています。 + +### TLS ネゴシエーション + +HTTPS によって確立される安全なコネクションでは、もう 1 つのハンドシェイクが必要です。このハンドシェイク、より正確に言うと {{glossary('TLS')}} ネゴシエーションは、通信の暗号化に使用する暗号の種類を決定し、サーバーを認証し、実際のデータ送信が始まる前に安全な通信の準備を整えます。この処理は、コンテンツのリクエストを実際に送信する前に、さらに 3 回のラウンドトリップを必要とします。 + +![DNS ルックアップ、TCP ハンドシェイク、そして TLS ハンドシェイクの 5 つのステップ (clienthello、serverhello、証明書、clientkey、サーバーとクライアントの両方の完了)。](ssl.jpg) + +通信を安全にするためにページ読み込みの時間が追加されますが、ブラウザーとサーバーの間で送信されるデータが第三者に解読されないという安全な通信は、レイテンシーに見合う価値があるものです。 + +8 回のラウンドトリップを経て、ブラウザーはようやくリクエストを送ることができます。 + +## レスポンス + +ウェブサーバーへのコネクションが確立されると、ブラウザーはユーザーに代わって最初の [HTTP `GET` リクエスト](/ja/docs/Web/HTTP/Methods)を送信します。ウェブサイトであれば、多くの場合その対象は HTML ファイルです。リクエストを受け取ったサーバーは、適当なレスポンスヘッダーと HTML のコンテンツを返します。 + +```html + + + + + My simple page + + + + +

My Page

+

A paragraph with a link

+
+ image description +
+ + + +``` + +この最初のリクエストへのレスポンスは、受信データの最初のバイト (First Byte) を含んでいます。{{glossary('Time to First Byte')}} (TTFB) は、ユーザーがリクエストを実行した時点から—たとえば、リンクをクリックした時点から— HTML の最初のパケットを受信するまでの時間を表します。コンテンツの最初のかたまり (Chunk) は一般的に 14kB のデータです。 + +上記のサンプルコードでは、リクエストされたコンテンツは明らかに 14kB より小さいですが、後述するように、リンクされたリソースは、ブラウザーのパース処理がそのリンクにたどり着くまでリクエストされることはありません。 + +### TCP スロースタート / 14kB ルール + +最初の応答パケットは 14kB になります。これは、{{glossary('TCP slow start','TCP スロースタート')}}の一部で、ネットワークコネクションの速度を制御するアルゴリズムの影響です。スロースタートは、ネットワークの最大の帯域幅が確定するまで徐々に送信するデータ量が増やします。 + +{{glossary('TCP slow start','TCP スロースタート')}}において、サーバーは最初のパケットを受信した後、次のパケットのサイズを 28kB に倍増させます。さらに後続のパケットについて事前に決めた上限に達するか、ネットワークの輻輳を検知するまでサイズを増やします。 + +![TCP スロースタート](congestioncontrol.jpg) + +最初のページ読み込みに関する 14kB ルールを聞いたことがあった場合、それは TCP スロースタートが理由です。そしてこれはウェブの性能の最適化が最初の 14kB にフォーカスする理由でもあります。TCP スロースタートは、ネットワークの輻輳を防ぎ、ネットワーク性能に対して適正なデータ転送速度を徐々に探り出します。 + +### 輻輳制御 + +サーバーが TCP パケットとしてデータを送信する一方で、ユーザー側のクライアントは確認応答、ACK を返してデータが配送されたことを確認します。コネクションには、ハードウェアやネットワークの条件によって許容量上の制限があります。サーバーが大きすぎるパケットを速すぎる速度で送信した場合、破棄されるでしょう。つまり、確認応答がない場合があるということです。サーバーはこれを missing ACK として処理します。輻輳制御アルゴリズムは、パケットを送信して確認応答を受け取るこのフローを使って送信レート (send rate) を決定します。 + +## パース処理 + +データの最初のかたまりを受け取ると、ブラウザーは受信した情報のパース処理を始めることができます。{{glossary('speculative parsing', 'パース処理')}}は、ネットワークから受信したデータを {{glossary('DOM')}} と {{glossary('CSSOM')}} に変換するステップです。DOM と CSSOM は、レンダラーがページを画面へ描画するために利用されます。 + +DOM はブラウザー向けのマークアップの内部的な表現です。DOM は外部に公開されており、JavaScript の様々な API を通じて操作できます。 + +ブラウザーは、リクエストしたページの HTML が最初の 14kB のパケットより大きかった場合でも、手元にあるデータに基づいてパース処理を開始し、サイトを描画しようとします。これは、ウェブの性能を最適化する時にに、ブラウザーがページの描画を始めるために必要なすべてのデータ、あるいは少なくともページのテンプレート (最初の描画に必要となる CSS と HTML) を最初の 14kB に含めることが重要となる理由です。何か 1 つでも画面に描画を行うには、その前に HTML と CSS、JavaScript がパースされなければいけません。 + +### DOM ツリーの構築 + +[クリティカルレンダリングパス](/ja/docs/Web/Performance/Critical_rendering_path)の 5 つのステップを説明します。 + +最初のステップは HTML のマークアップを処理し、DOM ツリーを構築することです。HTML のパース処理は、[トークン化](/ja/docs/Web/API/DOMTokenList)とツリーの構築に分かれます。HTML のトークンは開始タグと終了タグ、属性の名前と値を含みます。ドキュメントが正しく構成されていればパース処理は単純で、速度も速くなります。パーサーはトークン化された入力情報をドキュメントツリーを構成するドキュメントに変換します。 + +DOM ツリーはドキュメントのコンテンツを表します。[``](/ja/docs/Web/HTML/Element/html) 要素は最初のタグであり、ドキュメントツリーのルートノードとなります。ツリーには、異なるタグ同士の関係と階層構造が反映されます。他のタグの中にネストされたタグは子要素となります。DOM ノードの数が増えるほど、DOM ツリーの構築にかかる時間は長くなります。 + +![サンプルコードの DOM ツリーで、テキストノードを含むすべてのノードが表示されています。](dom.gif) + +パーサーが画像のようなノンブロッキングリソースを発見した場合、ブラウザーはそのリソースをリクエストし、そのままパース処理を継続します。CSS ファイルに遭遇した場合もパース処理を継続できます、しかし [`async`](/ja/docs/Web/JavaScript/Reference/Statements/async_function) または `defer` 属性がない ` +image description + +``` + +この例では、メインスレッドが HTML と CSS をパースしている間に、プリロードスキャナーがスクリプトと画像を探索し、それらのダウンロードを開始します。もし JavaScript の実行順序が重要でないなら、スクリプトがプロセスをブロックしないように `async` 属性または `defer` 属性を追加しましょう。 + +CSS の取得は HTML のパース処理あるいはダウンロードをブロックしません。しかし JavaScript の実行をブロックします。その理由は、しばしば JavaScript が CSS プロパティの要素への影響を問い合わせるために使われるからです。 + +### CSSOM の構築 + +クリティカルレンダリングパスの 2 つめのステップは CSS を処理して CSSOM ツリーを構築することです。CSS のオブジェクトモデルは DOM によく似ています。DOM と CSSOM はどちらもツリー構造です。この 2 つは独立したデータ構造を持ちます。ブラウザーは、CSS のルールをブラウザーが理解できるスタイルのマップに変換します。ブラウザーは CSS のルールセットを読み取り、CSS セレクターにもとづいて、親、子、兄弟の関係から構成されるノードのツリーを生成します。 + +HTML の場合と同様に、ブラウザーは受信した CSS のルールをブラウザーが実行可能な形式に変換しなければいけません。そのために、ブラウザーは HTML をオブジェクトに変換する場合と同じプロセスを CSS に対しても実行します。 + +CSSOM ツリーはユーザーエージェントのスタイルシートから取得したスタイルを含みます。ブラウザーは、ノードに対して適用される最も一般的なルールからスタートして、より特定されたルールを再帰的に適用し、最終的なスタイルを計算します。つまり、プロパティの値をカスケードします。 + +CSSOM の構築はとても高速であるため、現在の開発者ツールはそれ自体をユニークな色で表示しません。その代わりに、開発者ツールの「スタイルの再計算」は、CSS を解析して CSSOM ツリーを構築し、再帰的にスタイルを計算するトータルの時間を表示します。ウェブの性能の最適化の観点から言うと、CSSOM を生成するトータルの時間は一般的に1回の DNS ルックアップにかかる時間よりも少ないため、それほどの苦労はないと言えます。 + +### その他の処理 + +#### JavaScript のコンパイル + +CSS がパースされ、CSSOM が生成される間、JavaScript ファイルを含む他のアセットが(プリロードスキャナーによって)ダウンロードされます。JavaScript は、インタープリターに処理され、コンパイル、パース処理を経て実行されます。スクリプトはパース処理によって抽象構文木に変換されます。いくつかのブラウザーエンジンは、{{glossary('Abstract Syntax Tree', '抽象構文木')}}をインタープリターへ引き渡し、メインスレッドで実行されるバイトコードを出力します。これが JavaScript のコンパイル処理に当たります。 + +#### アクセシビリティツリーの構築 + +ブラウザーはコンテンツを理解し翻訳する補助機器で使用される[アクセシビリティ](/ja/docs/Learn/Accessibility)ツリーも構築します。アクセシビリティオブジェクトモデル (AOM) は補助機器向けの DOM のようなものです。ブラウザーは、DOM が更新されるとアクセシビリティツリーも更新します。アクセシビリティツリーは補助機能それ自体からは変更できません。 + +AOM が構築されるまで、[スクリーンリーダー](/ja/docs/Web/Accessibility/ARIA/ARIA_Screen_Reader_Implementors_Guide)でコンテンツにアクセスできません。 + +## レンダリング + +レンダリングのステップは、スタイル、レイアウト、描画、そして合成で構成されます。パースのステップで作成された CSSOM と DOM のツリーはレンダーツリーの形式へと組み合わされ、すべてのビジュアル要素のレイアウトを計算するために使用されてスクリーンに描画されます。いくつかのケースでは、CPU の代わりに GPU を使用してスクリーンの一部を描画し、メインスレッドを解放してパフォーマンスを改善するために、コンテンツ自身をレイヤーに昇格し、合成を行います。 + +### スタイル + +クリティカルレンダリングパスの 3 番目のステップは DOM と CSSOM をレンダーツリーの形式へと組み合わせることです。計算されたスタイルのツリー、あるいはレンダーツリー、の構築は DOM ツリーのルートからスタートし、目に見える (Visible) ノードをトラバースします。 + +ユーザーエージェントのスタイルシートにある `` のような表示されることないタグとその子要素、`script { display: none; }` のように `display: none` を指定されたすべてのノード、はレンダリングの結果に影響しないためレンダーツリーには含まれません。`visibility: hidden` が適用されたノードは、スペースを確保するためレンダーツリーに含まれます。上記のサンプルコード内の `script` ノードは、ユーザーエージェントのデフォルトを上書きするディレクティブが指定されていないためレンダーツリーに含まれません。 + +それぞれの目に見えるノードには、CSSOM のルールが適用されます。レンダーツリーはすべての目に見えるノードをコンテンツと計算されたスタイルを合わせて保持します。すべての関連するスタイルと DOM 上の目に見えるノードをマッチングし、[CSS カスケード](/ja/docs/Web/CSS/Cascade)に基づいて、それぞれのノードに対応する計算されたスタイルを決定します。 + +### レイアウト + +クリティカルレンダリングパスの 4 番目のステップは各ノードの平面状の位置を計算するためにレイアウト処理を実行することです。*レイアウト*はレンダーツリーに含まれるすべてのノードの幅と高さ、位置を決める処理です。さらにページ上のそれぞれオブジェクトのサイズと位置を決定します。*再フロー*は、続いて発生するドキュメント全体、あるいはページの一部分のサイズと位置を決める処理です。 + +レンダーツリーが構築されるとすぐにレイアウトが始まります。レンダーツリーは計算されたスタイルを踏まえてどのノードが表示されるか (非表示であっても) 特定しますが、寸法や位置は特定しません。各オブジェクトの正確なサイズと位置を決めるために、ブラウザーがレンダーツリーのルートからトラバースを行います。 + +ウェブページ上では、ほとんどすべての要素はボックスです。異なるデバイス、異なるデスクトップの設定は、ビューポートのサイズの数が無制限に存在することを示しています。このフェーズにおいて、ビューポートのサイズを考慮して、ブラウザーはすべての異なるボックスのスクリーン上の寸法を決定します。ビューポートのサイズを基本として、レイアウトは一般的にボディからスタートし、すべてのボディの子孫をそれぞれの要素のボックスモデルプロパティに合わせてレイアウトし、画像のように寸法がわからない代替要素のためのプレースホルダースペースを作成します。 + +ノードのサイズとポジションが決められる最初のタイミングをレイアウトと呼びます。続いて発生するノードのサイズと位置の再計算を再フロー呼びます。私たちの例では、画像が返される前に最初のレイアウトが発生すると考えられます。画像のサイズを宣言していなかったため、画像のサイズがわかるとすぐに再フローが発生します。 + +### 描画 + +クリティカルレンダリングパスの最後のステップは個別のノードをスクリーンに描画することです。最初に発生する描画を [first meaningful paint](/ja/docs/Glossary/first_meaningful_paint) と呼びます。描画またはラスタライズのフェーズにおいて、ブラウザーはレイアウトフェーズで計算されたそれぞれのボックスをスクリーン上の実際のピクセルに変換します。描画は、テキスト、色、境界、シャドウ、ボタンや画像のような置換要素を含む、要素のすべての視覚的な部分をスクリーンに描くことを含みます。ブラウザーはこれを超高速で実行する必要があります。 + +スムーズなスクロールとアニメーションを実現するために、スタイルの計算や再フロー、描画などメインスレッドを占有するすべての処理は、16.67ms 未満で完了する必要があります。2048 x 1536 の解像度を持つ iPad は 3,145,000 を超えるピクセルを持っています。それら大量のピクセルは高速に描画されなければいけません。2回目以降の描画を最初の描画より高速にするため、スクリーンへの描画は一般的に複数のレイヤーに分解されます。この場合に合成が必要になります。 + +描画は描画ツリー内の要素をレイヤーに分解します。コンテンツを GPU (CPU 上のメインスレッドの代わりになる) 上のレイヤーに昇格させることで、描画と再描画のパフォーマンスを向上します。[`