mizchiさんのパフォーマンスチューニングイベントに関するメモ
-
[社内勉強会] mizchiさんのパフォーマンスチューニングイベントについていくための準備をしました
- LAPRASさんの事前勉強会。これを公開してくれるのもありがたいですね
- https://tech-blog.lapras.com/techBlogs/web-performance
-
mizchiさんによる「LAPRAS 公開パフォーマンスチューニング」~調査編~
- 2時間半とボリュームもりもりだけど見る価値しかない
書籍では学べないノウハウがここにはあった…!
アーカイブもあるので全Webエンジニア、インフラエンジニア見た方がいい内容だと思う
たまにNetworkタブを見るくらいしかしてない自分のふわっと知識レベルでは正直、初見ですべては理解できなかったけどポイントを押さえ実際に分析をしてみて少しでもモノにしたい
LAPRASさんの事前勉強会
この動画を知ったのは当日なので、アーカイブ見たのは事後になる
- CoreWebVitals
- Lighthouseスコア
- ブラウザレンダリングの流れ
- 頻出(かも)ワード
Figjamまで公開してくれている…!
CoreWebVitals
Googleがユーザー体験を評価するために定めた重要なパフォーマンス指標
- 初期ロード時
- LCP (Largest Contentful Paint)
- ユーザーがページにアクセスしてから、ビューポートに表示される最大のコンテンツ(画像やテキストやブロックなど)が描画されるまでの時間
- CLS (Cumulative Layout Shift)
- ページの表示中に発生する予期しないレイアウトの移動を影響度で数値化したもの
- LCP (Largest Contentful Paint)
- ユーザー操作時
- INP (Interaction to Next Paint) … ※ これはlighthouseでは計測できない
- ユーザーによるページアクセスの全期間中に発生するすべてのクリック、タップ、キーボード操作などのインタラクションに対する応答性。FIDの後続(First Input Delay)
- INP (Interaction to Next Paint) … ※ これはlighthouseでは計測できない
補足
- 現時点でCoreWebVitalsがSEOにどういう影響を与えてるかAIに聞いてみた
結論としては、影響度は小。CoreWebVitalsのようなラボデータよりも、従来のSEO対策のようなフィールドデータの方が強いらしい(どんなに高速なページでもユーザーニーズがないとスコア上がらないはそれはそう)
ただ、フィールドデータを元にCoreWebVitalsが定められているので決して軽視していいものではない
Lighthouseスコア
ラボデータなので、通信環境などでスコアが全くことなるので注意
- LCP (Largest Contentful Paint)
- CLS (Cumulative Layout Shift)
- FCP (First Contentful Pain)
- ユーザーがページにアクセスしてから最初の要素が画面に表示されるまでの時間
- TBT (Total Blocking Time) … 200ms以内が良好な値
- https://web.dev/articles/tbt?hl=ja
- メインスレッドがブロックされて、ユーザーがページを操作できない合計時間。FCPからTTI(Time To Interactive)までに発生する50ms以上の長いタスクによってメインスレッドがどれだけ長くブロックされているかを示す
- Speed Index … 3.4s以内が良好な値
- https://developer.chrome.com/docs/lighthouse/performance/speed-index?hl=ja
- ページのコンテンツが視覚的にどれだけ早く表示されるかを示す。ユーザーが視覚的に表示が完了したと感じるまでの経過時間。上記の評価に対する総合スコア的な位置付けなのであまりみなくてもいい
ブラウザレンダリングの流れ
ざっくりブラウザがページをレンダリングするまでの流れ
Rendering Engineは今はBlink
レンダリングプロセス
レンダリングエンジンによって若干プロセスが異なる
頻出(かも)ワード
勉強会当日に出そうなワードを確認する
- メインスレッド
- https://developer.mozilla.org/ja/docs/Glossary/Main_thread
-
POINT
- HTMLを同期的に解釈して処理していくもの。CSS読み込み後にHTMLを表示するなど順序が保証されている
- Service Worker
- https://developer.mozilla.org/ja/docs/Web/API/Service_Worker_API
-
POINT
- メインスレッドから処理を逃すみたいな文脈で出てくる
- PWAでオフラインでも動くようにしたいとか、HTTPのリクエストをプロキシでキャッシュ、APIのモック(MSWとか)
- Web Worker
- https://developer.mozilla.org/ja/docs/Web/API/Web_Workers_API
-
POINT
- ServiceWorkerの一種。DOMにアクセスできない
- 重い処理を別スレッドに逃してメッセージを通してやりとりするみたいなもの
- これを使った有名なもので、Partytownというものがある
- 3rdパーティスクリプトをWebWorkerに流すことでメインスレッドのブロックをなくす
- Server Timing API
- https://zenn.dev/mizchi/articles/server-timing-header-for-frontend
- https://developer.mozilla.org/ja/docs/Glossary/Server_Timing
-
POINT
- サーバーからブラウザへのレスポンスヘッダとして、リクエスト内で発生した指標を送ることができる
- それをDeveloperToolで見ることができる
- Scriptのdeferとasync
- https://developer.mozilla.org/ja/docs/Web/HTML/Element/script
- https://stackoverflow.com/questions/10808109/script-tag-async-defer
-
POINT
- 何も書かないとメインスレッド上で実行されHTMLのパースとかをブロックする
- deferやasyncを使うことでブロッキングされることなく実行してくれる
- どちらもダウンロードは別スレッドだけど、実行タイミングが異なる。deferは実行順序を保証してくれる
- preload属性
- https://developer.mozilla.org/ja/docs/Web/Performance/Speculative_loading
-
POINT
- Next,Nuxtとかはやってくれてるらしいもので、次のページで必要な要素を先に取得しておく
- prefetch, preconnectなどいくつか種類がある
- dev.toはこの仕組みかはわからないが、hover時に先に取りにいってる
- クリティカルレンダリングパス
- https://web.dev/learn/performance/understanding-the-critical-path?hl=ja
-
POINT
- レンダリングに必須なパス。以下のどれかをブロックしてないかは初期レンダリング時に見ておく必要がある
mizchiさんのjsconfの資料より頭に入れとくと良さそうなもの
前提として頭に入れとくとよさそうな内容を抜粋
自分で分析試してみる時もこの辺を改めてみながら進める
以下、スライド
mizchiさんによる「LAPRAS 公開パフォーマンスチューニング」~調査編~
おおまかな流れ
- 本日の期待値と事前知識
- 実践・パフォーマンス計測
- Network request blocking を使用した調査
- Override Content でAPIの応答やcssを書き換える
- Webpack chunk / bundle analyzer 周りのお話
- 答え合わせ-事前に行った調査の結果の共有
- まとめTALK
- 番外編 - フロントエンドの計測においてソースコードはノイズにもなり得る
本日の期待値と事前知識
メインスレッドで行われているHTML Parserとは別に、全体をガーッと見にいくプリロードスキャナというものが存在する。SPAでは初回ロードで含まれてないソースがあるけど、Viteとかがプリロードヘッダーを挿入してくれてるから、バンドル解析の結果ここ絶対先にくるみたいなものを読んでくれている(へぇー)
実践・パフォーマンス計測
どういう手順で分析していくか
- Lighthouse
- Performance
- network
Lighthouse
デフォルト設定でまずはぶん回す
できれば分析用のChrome拡張すら入ってない状態で回した方が良い
プライベートブラウザでの検証がおすすめだけど、localStorageが使えないなど特有の差分には注意
Treemapを見てアセットの実行比率を確認する
Webpackのバンドルアナライザーのようなものは「View Treemap」から見ることができる
DIANOSTICSを確認する
一般的に言えそうなことが重要度が高いものから順に列挙されている
フッターがCLSのスコアを下げている要因になっていることが一例として紹介されている
メインコンテンツが遅延読み込みな都合上、ファーストビューでチラッとフッターが見えるが故にこっちを優先して読み込むような処理が走ってしまっている
全部をみる必要はないけど、LCPの要素は確認しておいた方がいい
(ただ、ここを最適化すれば良いというわけではない)
Performanceタブを見る
日本だと以下のスロットリングで見ると良いらしい
あまりにも遅い場合は検証に支障が出るのでスロットリングを外す
詳細なデータがたくさんあるけど、問題がどの辺にありそうかの仮説をもって読まないと読めない
LCPが1番大事。LCPに至るまでに何が起きているか前後を探る
例ではバナーのところでレイアウトシフト起きてるねとか
Networkも大事。Networkタブと違ってタイミングも見ている
縦軸がラウンドトリップ。これを減らすことが高速化のポイント
下図の青いやつなど、リクエストが折り返されているものも見ることができる
MainはCPUに起因するもの
赤いものがロングタスク(CPU処理は1タスクあたり16msになるのが理想?)
初期化はどうしてもCPUバウンドになるけどその後のロングタスクはよろしくない
レイアウトジャンクといってスクロールしている時に止まるみたいな体験の悪化につながる
SPAのページとかはParseHTMLを見ておいた方が良い
HTMLがレンダリングされるまでに何が起きているか内訳が見れる
ソースマップを注入することで、(anonymouse)の内部が見れたりするけどそこまで優先度は高くない
Networkタブをみる
右クリックで「waterfall」が表示できる。おそらく赤い線がLCP?
TBTが重い時、Sizeでソートする
Service Workerでキャッシュしてると見えないことがあるかも
次にTimeで見る。APIレスポンスが重いやつが見れる
Queueingは他のリクエストが多いから待ち時間が発生しているやつ
Fetch/XHRはTimeで見て他は、Sizeで見ることが多い
Network request blocking を使用した調査
サードパーティJSなどをブロッキングして純粋なページパフォーマンスを見る
APIをブロッキングしてエラーハンドリング実際にできてるかのチェックも良さそう
パス指定でもいけるしドメイン自体をブロックすることもできる
Override Content でAPIの応答やcssを書き換える
Networkタブなどコンテキストメニューから「Override Content」で使える
ここで作ったファイルはローカルに保存されるので検証中に間違えてブラウザ閉じちゃったとかでも再開できるのが地味にありがたそう
ユースケースとしてはAPIモック、CSSを上書きしてCLSが解消されるかチェックする時など
JSも上書きできるから開発環境だと検証しづらいちょっとしたやつを差し込むとかもあり?
HTMLタグを上書きしてdeferやasyncつけたり、重そうな特定の要素外してみたりもできる
動画の中で注意点としてあったのは
- リクエストしたものを上書きしてるだけだからリクエスト自体は発生してる
- 普通に見たい時に設定切るの忘れるとおま環になる
Webpack chunk / bundle analyzer 周りのお話
Webpack chunk
チャンクが細かすぎるかも?という指摘。Webpack Chunk Sizeの設定がそうなっちゃってるかも
細かすぎると逆に悪化しちゃう可能性もありえる
Bundle Analyzer
lodashがでかい、重複している。依存経路を見ておいた方がいいらしい
# 依存経路の確認
yarn why lodash/npm explain lodash
ツリーシェイクをしてくれるライブラリとそうじゃないものがある?
マイナーなライブラリだとこの辺りやってくれないものもあるそう
package.jsonメンテできてるかとか普段どれだけいいコード書いてこれたかがTBTに現れる