Web フロントエンド ハイパフォーマンス チューニングを読んでみた
最近業務でパフォーマンスに関する課題に直面したことをきっかけにこの本を先輩から教えてもらい読みました。
内容としてはブラウザのレンダリングの仕組みやチューニングの基礎などパフォーマンス改善に関する情報が記載されています。
今回は、読んでいく中で特に重要だと思った箇所を簡単にまとめてみましたので、みなさんがこの本を読むきっかけになれば幸いです。
パフォーマンスの定義
1 章の冒頭でパフォーマンス
を ユーザーの様々な振る舞いに対してウェブページが応答する速さ
と定義しています。
ブラウザのレンダリングの流れ
2 章ではブラウザのレンダリングエンジンがリソースを取得し実際にページに描画されるまでの仕組みが解説されています。
ブラウザのアドレスバーに URL を打ち込んで、 Web ページが表示されるまでにどういったプロセスをたどって処理をしているのかを追っていきます。
Loading
↓
Scripting
↓
Rendering
↓
Painting
この 4 つの工程からなるレンダリングが始まり描画されるまでを、フレームと呼び、より詳細にしたものが以下の図になります。
Loading
リソースのダウンロード (Download)
リソースのダウンロードでは、HTML 自身を含むリソースをサーバーからダウンロードします。
リソースのパース (Parse)
ダウンロードしたリソースをパースします。
例えば、ダウンロードされた HTML や CSS は、DOM ツリーや CSSOM ツリーにこのタイミングで変換されます。
Scripting
JavaScript のコードを実行します。
字句解析から構文解析を行い、ブラウザに備わっている JavaScript エンジンが実行可能なコードに変換していきます。
書籍ではこの過程も丁寧に説明されていました。
Rendering
Calculate Style
ドキュメントの DOM ツリー内の全ての DOM 要素に対してどのような CSS プロパティが当たるかを計算しています。
Layout
Calculate Style の計算が終わった後、Layout を行います。
レイアウト情報は、具体的に以下のようなものを指します。
- 要素の大きさ
- 要素のマージン
- 要素のパディング
- 要素の位置
- 要素の Z 軸の位置
Painting
Paint ・ Rasterize
DOM 要素に当たる CSS プロパティを算出した後はそれをもとに、レンダリング ツリー内の各ノードを画面上の実際のピクセルに変換します。この手順を「ペインティング」または「ラスタライジング」といいます。
レイヤーの合成 (Composite Layers)
最後の Composite Layers の処理では、ピクセルにしたレイヤーを合成して最終的なレンダリング結果を生成します。
ことの時 CPU と GPU による合成があります。基本的には CPU で処理されるのですが、なんらかの条件を満たすとき GPU で処理されます。
例えば、translate3d() 関数を使う時です。
.foober {
transform: tranlate3d(0, 10px, 10px);
}
3D 系の処理は CPU より GPU で計算した方が早いためです。
目標とすべき指標を設定する
パフォーマンスを評価する上でその指標を設定するのは人によってばらつきがあります。
例えば、ページの最初の読み込みに2秒かかったとしたらそれをパフォーマンス上問題と感じるのは人によって違います。
ここで紹介されているのが、ユーザーが遅延をどのように認識するかを調べたUX調査に基づいて作られた RAIL というパフォーマンス指標です。
Google 社の開発者 Ilya Grigorik 氏が提唱したパフォーマンスモデルで、Response, Animation, Idle, Load
のそれぞれの頭文字をとっています。
RAIL は読み込みやインタラクションなどのパフォーマンス目標を定義しています。(1000ms = 1s)
項目 | 基準時間 |
---|---|
Response | 100ms |
Animation | 16ms |
Idie | 50ms |
Load | 1000ms |
例えばResponse 100ms
とありますがこれはユーザーのなんらかのアクションに対してウェブページがユーザーインターフェース上で変化を引き起こして、応答するまでの時間を指します。この時間を超えてくるとユーザーは遅延を感じるようになります。
また RAIL モデルでパフォーマンスを評価する には RAIL の詳細な情報が記載されているので合わせて読むことをお勧めします。僕が興味を持ったのは、パフォーマンスの遅延に対するユーザーの認識です。
チューニング
書籍の後半では、JavaScript や CSS などのパフォーマンスチューニングのためのノウハウが書かれています。特に衝撃を受けた CSS のマッチング処理に関して紹介します。
CSS のマッチング処理
レンダリングエンジンは、CSS ルールセットとドキュメントに含まれる全ての DOM 要素と付き合わせてマッチング処理を行っているのですが、重要は マッチングの際には CSS セレクタは右から左に向けて処理されることです。
例えば以下のような CSS セレクタの指定があったとします。
.body > div.logo {
...
}
この場合
- クラスに logo が含まれていて
- その要素が div であり
- その親の要素名が body である
という条件になるので CSS セレクタの指定が深ければ深いほどマッチング処理に時間がかかります。
僕はなんとなく直感で CSS セレクタの指定は左から処理されていくもので指定を詳細にすればその分マッチング処理も短くなると思っていました。(恥ずかしい...)
最後に
パフォーマンス改善を行うためのテクニックだけでなく、ブラウザがレンダリングするまでの内部の仕組みや パフォーマンス測定のための Chrom DevTools の使い方まで幅広く学ぶことができました。
パフォーマンスに興味がある方はぜひ読んでみてください!!