Table of Contents
仕組みを知る
ブラウザ内のコンポーネント
レンダリングエンジン
: HTMLの描写エンジンJavaScript エンジン
: JavaScript の実行環境を提供するソフト ウェアコンポーネント
ブラウザレンダリングの流れ
(1) Loading
↓
(2) Scripting
↓
(3) Rendering
↓
(4) Painting
①Loading(リソース読み込み)
Loadingで行われる事。
(1) リソースのダウンロード(Download)
サーバからリソースの取得
(2) リソースのパース(Parse)
取得したリソースを公文解析してレンダリングエンジンの内部表現に変換する。
HTTPレスポンスとして返されるHTMLは下記の工程でDOMツリーへと変換される。
1. 字句解析によるトークンのリスト化
2. 構文解析による構文木の構築
3. 構文木内にある JavaScript を実行しつつ DOM ツリーの構築
②Scripting(Javascript実行)
JSのコードをJSエンジンに引き渡して実行させる。
一般的な流れは下記
JSコード
↓
字句解析
↓
構文解析
↓
コンパイル
↓
実行
処理系内部の仮想マシン、もしくはCPUで実行される
③Rendering(レイアウトツリー構築)
スタイルの計算(Calculate Style)とレイアウト(Layout)が行われる。
スタイルの計算
: DOMツリーの中内の全てのDOM要素に対してどのようなCSSプロパティが当たるかを計算(すべての DOM 要素に対して、CSS ルールの CSS セレクタがマッチするかを総当りで試行する。)レイアウト(Layout)
: DOM ツリー内のすべてのノードの視覚的なレイアウ ト情報の計算、レイアウト( Layout)を行う
④Painting(レンダリング結果の描画 )
このフェーズでようやくレンダリングエンジンは ユーザーが見ることができる実際のピクセルを描画する。
このフェーズでは下記を行う。
ペイント(Paint)
: RednerTreeを元にDisplay Listと呼ばれる内部の低レベルグラフィック エンジンのための命令の列を生成ラスタライズ(Rasterize)
: 生成された命令を用いて実際にピクセル(ビットマップ )へと 描画レイヤーの合成(Composite Layers)
: ピクセルにしたレイヤーを合成して最終 的なレンダリング結果を生成
チューニングの基礎
チューニングのトレードオフ
- 開発者の時間的リソース
- コードの単純さ(可読性、保守性、拡張性)
推測するな、計測せよ
効果的なチューニングのためには、まずは計測し、どうすることが最も効果的 なのか検討していく必要がある。
ボトルネックを探し出す
ある一連の処理の中で最も多くの時間を消費し ている箇所をボトルネック
と呼ぶ。
チューニングのトレードオフによる無駄なペナルティを避けるためには、ボト ルネックを特定することは必要不可欠。
目指すべき指標を設定する
RAILというパフォーマンス指標が存在する
Response(応答)
: ユーザーの何らかのアクションに対してウェブページがユーザー インターフェイス上の変化を引き起こして、応答するまでの時間Animation(アニメーション)
: アニメーション中に連続して行われるフレームの中で 1 フレー ムの処理の時間Idle(アイドル処理)
: アイドル状態に実行される JavaScript の処理時間Load(読み込み)
: ウェブページのコンテンツの読み込みにかかる時間
下記がそれぞれの目安の基準時間
計測する手段
- Chrome DevTools などデベロッパーツールによる計測
- JavaScript による計測
- パフォーマンス診断ツールの利用
- パフォーマンスの継続的監視
リソース読み込みのチューニング
読み込むリソースの大きさと数を減らす
リソースの最小化
HTML,CSS,JS等のファイルは改行・タブ等の不要なバイトを含むので、それぞれリソース最小化ツールを使用する事でリソースサイズを小さくできる。
適切な画像形式を選択する
画像ファイルはその形式ごとに適した用途があります。それぞれの用途に最適 な画像を用いることでファイルサイズを削減できる可能性がある。
リソースを事前に読み込みしておく
DNS プリフェッチ
link 要素の rel 属性に dns-prefetch を指定すると、href 属性に指 定したドメインの名前解決をバックグラウンドで処理してくれる。
名前解決さ れたドメインの IP アドレスはブラウザのキャッシュに格納される。
リソースのプリフェッチ
link 要素の rel 属性に prefetch を指定すると、リソースの事前読み込みを行 うことが可能。
事前読み込みされたリソースはブラウザのキャッシュ内に格納される。
コネクションの接続
rel 属性に preconnect を指定すると、指定したドメインへの接続のみをあら かじめ行
プリレンダリング
rel 属性に prerender を指定すると、ウェブページのレンダリングをバックグ ラウンドで行わせることができる。
Gzip圧縮を活用する
HTTP/1.1ではHTTPレスポンスのコンテンツを圧縮して配信可能。
コンテンツを圧縮する事でサイズを大きく減らすことができる。
CDNを用いてリソースを配信する
CDN(Content Delivery Network)を利用することで、リソースの配信を最適化することが可能。
CDN とは、ウェブのリソースを配信することに最適化されたネットワークの ことを指す。
ウェブサイトのリソースをキャッシュし、世界中に置かれているCDNの配信サーバーにキャッシュし、
そのサーバーがかわりにそのコンテンツを配信することで、
1つのサーバーで配信するよりも負荷が分散され、かつ高速なリソース配信を行うことができるという仕組み
有名なCDNにCloudflare
, Amazon CloudFront
, Fastly
などがある。
リダイレクトをしない
ウェブサイト内の不要なリダイレクトは避けるべき。 リダイレクトは HTTP リクエストを余分にやりとりする必要がある。
また、違うドメインへのリダイレクトは、Keep-Alive も有効にならないので、余計 な DNS の名前解決や TCP3 ウェイハンドシェイクなどの接続の前処理を再び行 う必要がる。
ブラウザのキャッシュを活用する
ブラウザのキャッシュを活用することで、HTTP リクエストの数を減らしたり、HTTP レスポンスのサイズをとても小さくしたりすることが可能。
Expiresヘッダー(強いキャッシュ)
HTTP では、HTTP レスポンスヘッダーに Expires ヘッダーを設定すること で、リソースのキャッシュをブラウザ側に指示可能。
キャッシュされたファイルが消えるか、期限 が切れるまでは、ブラウザが動作しているマシンの内部にキャッシュされ続ける 強いキャッシュ。
Cache-Controlヘッダーの設定(強いキャッシュ)
Expires ヘッダーと同じ強いキャッシュを有効にできます。Cache-Control によってキャッシュを一度 有効にすることでブラウザにキャッシュが存在する場合にはそのリソースへの HTTP リクエストは送信されないようにる。
ブラウザは、Cache-Control ヘッダーと Expires ヘッダー両方が設定されてい る場合には Cache-Control ヘッダーを優先する。
Last-Modifiedヘッダーの設定(弱いキャッシュ)
Last-Modified ヘッダーには、その URL のリソースが最後に変更されたのが、 いつなのかを設定する。
クライアントが送信する HTTP リクエスト内に含まれている条件に合致すれば、 HTTPサーバーは304 Not Modifiedレスポンスを返すことで不要なデータの送 信を抑えることが可能。
キャッシュしつつ、変更が発生した場合に は即時キャッシュをクリアしたい場合に利用される。
ETagヘッダーの設定(弱いキャッシュ)
ブラウザがあるリソースに対して初めてアクセスするとき、HTTP サーバー はレスポンスヘッダーの中に次のような Etag ヘッダーを返送。
Etag: "E8sKOBq0HCGxD2KPqSX2EyVC2q7Rmd"
ブラウザは取得したファイルと ETag の対を保存しておく。ブラウザは HTTP リク エストヘッダーの中に次のような If-None-Match ヘッダーを送信します。ここで 指定しているのは先程の Etag の値です。
If-None-Match: "E8sKOBq0HCGxD2KPqSX2EyVC2q7Rmd"
HTTP サーバーは、HTTP クライアントからこの If-None-Match ヘッダー を受け取ると、リソースの現在の ETag の値と比較します。これらが同じであ れば、リソースは変わっていないことになるので、HTTPサーバーは304 Not Modified という、リソースを含まないレスポンスヘッダーだけの HTTP レスポ ンスを返す。
Service Workerの利用
Service Workerを使えば、JavaScript からキャッシュの制御を柔軟に行うことが可能。
一度 Service Worker が登録されると、ブラウザがリ ソースを取得する際には Service Worker 内に記述されているロジックを参照して キャッシュからリソースを取得するかウェブサーバーからリソースを取得するかを決める。
Service Worker は、ウェブページとウェブサーバーの間にあるプロクシのよう な形で動作する。