WebPageTest を使用してレイアウトの不安定性の問題を特定し、修正する手順。
以前の投稿で、WebPageTest での Cumulative Layout Shift(CLS)の測定について説明しました。CLS はすべてのレイアウト シフトの集計値です。そこで、この投稿では、ページ上の個々のレイアウト シフトを詳しく調べて、不安定さの原因を特定し、実際に問題を解決してみようと思います。
レイアウト シフトを測定する
Layout Instability API を使用すると、ページ上のすべてのレイアウト シフト イベントのリストを取得できます。
new Promise(resolve => {
new PerformanceObserver(list => {
resolve(list.getEntries().filter(entry => !entry.hadRecentInput));
}).observe({type: "layout-shift", buffered: true});
}).then(console.log);
これにより、入力イベントの前に発生したレイアウト シフトの配列が生成されます。
[
{
"name": "",
"entryType": "layout-shift",
"startTime": 210.78500000294298,
"duration": 0,
"value": 0.0001045969445437389,
"hadRecentInput": false,
"lastInputTime": 0
}
]
この例では、210 ミリ秒で 0.01% という非常に小さなシフトが 1 回発生しています。
変化の発生時刻と重大度を把握することは、変化の原因を特定するうえで役立ちます。WebPageTest に戻って、ラボ環境でさらにテストを行いましょう。
WebPageTest でレイアウト シフトを測定する
WebPageTest で CLS を測定するのと同様に、個々のレイアウト シフトを測定するにはカスタム指標が必要です。幸い、Chrome 77 が安定版になったため、プロセスは簡単になりました。レイアウト不安定性 API はデフォルトで有効になっているため、Chrome 77 内の任意のウェブサイトでこの JS スニペットを実行して、すぐに結果を取得できます。WebPageTest では、デフォルトの Chrome ブラウザを使用できるため、コマンドライン フラグや Canary の使用について心配する必要はありません。
そこで、WebPageTest のカスタム指標を生成するようにスクリプトを変更します。
[LayoutShifts]
return new Promise(resolve => {
new PerformanceObserver(list => {
resolve(JSON.stringify(list.getEntries().filter(entry => !entry.hadRecentInput)));
}).observe({type: "layout-shift", buffered: true});
});
このスクリプトの Promise は、配列自体ではなく、配列の JSON 表現に解決されます。これは、カスタム指標で生成できるのが文字列や数値などのプリミティブ データ型のみであるためです。
テストに使用するウェブサイトは ismyhostfastyet.com です。これは、ウェブホストの実際の読み込みパフォーマンスを比較するために私が作成したサイトです。
レイアウトの不安定さの原因を特定する
結果で、LayoutShifts カスタム指標に次の値が設定されていることがわかります。
[
{
"name": "",
"entryType": "layout-shift",
"startTime": 3087.2349999990547,
"duration": 0,
"value": 0.3422101449275362,
"hadRecentInput": false,
"lastInputTime": 0
}
]
まとめると、3087 ミリ秒で 34.2% のレイアウト変更が 1 回発生しています。原因を特定するために、WebPageTest のフィルムストリップ ビューを使用してみましょう。

フィルムストリップの 3 秒付近までスクロールすると、レイアウト シフトが 34% 発生した原因がカラフルなテーブルであることがわかります。ウェブサイトは JSON ファイルを非同期で取得し、テーブルにレンダリングします。テーブルは最初は空であるため、結果が読み込まれるまで待機してテーブルを埋めようとすると、シフトが発生します。

それだけではありません。ページが視覚的に完了するまでの時間(約 4.3 秒)を見ると、「Is my host fast yet?」ページの <h1>
が突然表示されていることがわかります。これは、サイトでウェブフォントが使用されており、レンダリングを最適化するための対策が講じられていないことが原因です。この場合、レイアウトが実際に移動することはありませんが、タイトルを読むのに時間がかかりすぎるため、ユーザー エクスペリエンスは低下します。
レイアウトの不安定さを修正する
非同期で生成されたテーブルがビューポートの 3 分の 1 をシフトさせていることがわかったので、修正しましょう。JSON の結果が実際に読み込まれるまでテーブルの内容はわかりませんが、DOM がレンダリングされるときにレイアウト自体が比較的安定するように、テーブルに何らかのプレースホルダ データを入力することはできます。
プレースホルダ データを生成するコードは次のとおりです。
function getRandomFiller(maxLength) {
var filler = '█';
var len = Math.ceil(Math.random() * maxLength);
return new Array(len).fill(filler).join('');
}
function getRandomDistribution() {
var fast = Math.random();
var avg = (1 - fast) * Math.random();
var slow = 1 - (fast + avg);
return [fast, avg, slow];
}
// Temporary placeholder data.
window.data = [];
for (var i = 0; i < 36; i++) {
var [fast, avg, slow] = getRandomDistribution();
window.data.push({
platform: getRandomFiller(10),
client: getRandomFiller(5),
n: getRandomFiller(1),
fast,
avg,
slow
});
}
updateResultsTable(sortResults(window.data, 'fast'));
プレースホルダ データは、並べ替えられる前にランダムに生成されます。この例では、「█」文字がランダムな回数繰り返されてテキストのビジュアル プレースホルダが作成され、3 つの主な値の分布がランダムに生成されています。また、テーブルのすべての色を彩度を落とすスタイルを追加して、データがまだ完全に読み込まれていないことを明確にしました。
レイアウトの安定性には、使用するプレースホルダの見た目は関係ありません。プレースホルダの目的は、コンテンツが表示されることと、ページが壊れていないことをユーザーに保証することです。
JSON データの読み込み中のプレースホルダは次のようになります。

ウェブフォントの問題に対処する方がはるかに簡単です。このサイトでは Google Fonts を使用しているため、CSS リクエストで display=swap
プロパティを渡すだけで済みます。以上です。Fonts API は、フォント宣言に font-display: swap
スタイルを追加します。これにより、ブラウザはすぐにフォールバック フォントでテキストをレンダリングできます。修正を含む対応するマークアップは次のとおりです。
<link href="https://fonts.googleapis.com/css?family=Chivo:900&display=swap" rel="stylesheet">
最適化の検証
WebPageTest でページを再実行すると、変更前後の比較を生成して、違いを可視化し、レイアウトの不安定さの新しい度合いを測定できます。

[
{
"name": "",
"entryType": "layout-shift",
"startTime": 3070.9349999997357,
"duration": 0,
"value": 0.000050272187989256116,
"hadRecentInput": false,
"lastInputTime": 0
}
]
カスタム指標によると、3, 071 ミリ秒(以前とほぼ同じタイミング)でレイアウト シフトが発生していますが、シフトの重大度は 0.005% と大幅に小さくなっています。これで構いません。
また、フィルムストリップから、<h1>
フォントがすぐにシステム フォントにフォールバックし、ユーザーがより早く読めるようになっていることもわかります。
まとめ
複雑なウェブサイトでは、この例よりも多くのレイアウト シフトが発生する可能性がありますが、修正プロセスは同じです。WebPageTest にレイアウトの不安定性指標を追加し、結果を視覚的な読み込みフィルムストリップと照合して原因を特定し、プレースホルダを使用して画面の領域を予約することで修正を実装します。
(もう 1 つ)実際のユーザーが経験したレイアウトの不安定さを測定する
最適化の前後に WebPageTest を実行して、指標の改善を確認できるのは良いことですが、実際に重要なのは、ユーザー エクスペリエンスが向上していることです。サイトを改善しようとしているのは、そのためではないでしょうか?
そこで、従来のウェブ パフォーマンス指標に加えて、実際のユーザーのレイアウトの不安定さに関するエクスペリエンスを測定し始めることができれば、素晴らしいでしょう。現場からのデータは、問題の所在や修正による効果を把握するうえで不可欠であり、最適化フィードバック ループの重要な要素です。
独自のレイアウトの不安定性データを収集するだけでなく、Chrome UX レポートもご確認ください。このレポートには、数百万ものウェブサイトでの実際のユーザー エクスペリエンスから得られた CLS データが含まれています。このツールを使用すると、自分(または競合他社)のパフォーマンスを確認したり、ウェブ全体のレイアウトの不安定さの状況を調べたりできます。