画面が「光る」とき、ブラウザは何を考えているのか?
フロントエンドエンジニア諸君、日々お疲れ様。
パフォーマンスチューニングの話になると、決まって「不要な再レンダリングを減らせ」という抽象的なお題目が飛んでくるだろう。だが、実際に自分の書いたコードがブラウザのエンジンをどこまで酷使しているか、その「重み」を肌で感じたことはあるか?
今日は、ブラウザが画面を描画する際の「ペイント(Paint)」という工程を可視化し、無駄な負荷を炙り出すための技術、「ペイントフラッシング(Paint Flashing)」について話そう。
ブラウザの「描画」は、決してタダではない
まず、ブラウザのレンダリングパイプラインを軽くおさらいしておこう。
JavaScriptでDOMを操作すると、ブラウザは「スタイル計算」→「レイアウト(リフロー)」→「ペイント」→「コンポジット(合成)」という重たい階段を登る。
ここで言う「ペイント」とは、ピクセルに色を塗りつける作業だ。DOMの更新によって見た目が変わるたび、ブラウザはこの作業をやり直す。これを「リペイント」と呼ぶ。
実は、このリペイントこそがモバイル端末のバッテリーを喰らい、60fps(あるいは120fps)の滑らかさを殺す最大の戦犯なんだ。
ペイントフラッシングを可視化せよ
百聞は一見にしかず。ブラウザは、どの領域を再描画しているかを緑色の枠で強調表示する「ペイントフラッシング」という強力な隠しツールを持っている。
手順:
1. Chromeの「検証(DevTools)」を開く。
2. `Command + Shift + P` (Windowsなら `Ctrl + Shift + P`) でコマンドメニューを開く。
3. `Rendering` と入力し、「Rendering」タブを表示する。
4. その中にある 「Paint flashing」 にチェックを入れる。
これだけで、画面上で「リペイントが発生した瞬間」に、その矩形が緑色にチカチカと光るはずだ。もし、クリックしただけのボタンから離れた場所まで緑色に光っていたら、それは設計を見直すサインだ。
—
実践:無駄なペイントを発生させるコードと最適化
いいか、現場でよくある「やってはいけない実装」を例に挙げよう。特定のDOM要素のスタイルを頻繁に書き換えることで、ペイント範囲がどう広がるかを確認するコードだ。
なぜこれがダメなのか?
このコードでは `width` を変更している。これはレイアウト計算(リフロー)を伴うため、ブラウザは「container」のサイズまで再計算し、その結果、広範囲がリペイントされることになる。
プロの改善策:
「ペイントだけ」で済ませるなら、`transform` や `opacity` を使うのが定石だ。これらはブラウザのコンポジット層で処理されるため、メインスレッドのレイアウト計算をスキップできる。
// 改善例:GPUアクセラレーションを活用する
target.style.transform = `scale(${Math.random()})`;
target.style.willChange = ‘transform’; // ブラウザに「ここは動くぞ」と事前にヒントを与える
チーフアーキテクトからの助言
ペイントフラッシングで見える「緑の閃光」は、ブラウザが流している汗の量だ。
もし君のアプリケーションで、関係ないはずのエリアまで緑色に光っているなら、それは「DOM構造が密結合しすぎている」か、「不要な要素まで再レンダリングの範囲に含まれている」証拠だ。
- `will-change` を乱用するな: これもメモリを喰う諸刃の剣だ。本当に激しく動く部分だけに絞れ。
- レイヤーを分離せよ: `position: absolute` や `transform` を使い、頻繁に変わるUIパーツを別のレイヤー(コンポジットレイヤー)に追い出すことで、リペイントの範囲を劇的に小さくできる。
現場では、「綺麗なコード」以上に「ブラウザの負荷を想像できるコード」が価値を持つ。
さあ、今すぐ自分のプロダクトでペイントフラッシングをONにして、画面がどれだけ無駄に光り狂っているか確認してみろ。それが、パフォーマンス改善という長い旅の第一歩だ。
健闘を祈る。

コメント