新しい Lighthouse API を試して、ユーザー フロー全体のパフォーマンスとベスト プラクティスを測定しましょう。
Lighthouse は、ページの初回読み込み時のパフォーマンスとベスト プラクティスをテストするのに最適なツールです。ただし、従来 Lighthouse では、ページのライフサイクルの他の側面(次のような側面)を分析することは困難でした。
- キャッシュが温まっている状態でページが読み込まれる
- Service Worker が有効になっているページ
- 潜在的なユーザー インタラクションを考慮する
そのため、Lighthouse では重要な情報が見落とされてしまう可能性があります。Core Web Vitals は、キャッシュが空のページの読み込みだけでなく、すべてのページの読み込みに基づいています。また、Cumulative Layout Shift(CLS)などの指標は、ページが開いている間ずっと測定できます。
Lighthouse に、ページのライフサイクル内の任意の時点でラボテストを実行できる新しいユーザーフロー API が追加されました。Puppeteer は、ページの読み込みをスクリプト化して合成ユーザー インタラクションをトリガーするために使用されます。Lighthouse は複数の方法で呼び出され、それらのインタラクション中に重要な分析情報を取得できます。つまり、ページの読み込み中とページでのインタラクション中にパフォーマンスを測定できます。ユーザー補助チェックは CI で実行できます。最初のビューだけでなく、購入手続きフローの深い部分でも実行して、リグレッションがないことを確認できます。
動作するユーザーフローを実現するために記述された Puppeteer スクリプトであれば、ほとんどのスクリプトに Lighthouse を任意の位置に挿入して、パフォーマンスとベスト プラクティスを測定できます。このチュートリアルでは、ユーザーフローのさまざまな部分(ナビゲーション、スナップショット、期間)を測定できる新しい Lighthouse モードについて説明します。
セットアップ
user flow API はまだプレビュー版ですが、Lighthouse では現在ご利用いただけます。以下のデモを試すには、Node バージョン 14 以降が必要です。空のディレクトリを作成し、そのディレクトリで次のコマンドを実行します。
# Default to ES modules.
echo '{"type": "module"}' > package.json
# Init npm project without the wizard.
npm init -y
# Dependencies for these examples.
npm install lighthouse puppeteer open
ナビゲーション
新しい Lighthouse の「ナビゲーション」モードは、ページのコールド ロードを分析するという、これまでの Lighthouse の標準動作に名前を付けたものです。このモードでページ読み込みのパフォーマンスをモニタリングしますが、ユーザーフローによって新たな分析情報が得られるという可能性も生まれます。
Lighthouse でページの読み込みをキャプチャするスクリプトを作成するには:
- Puppeteer を使用してブラウザを開きます。
- Lighthouse のユーザーフローを開始します。
- ターゲット URL に移動します。
import fs from 'fs';
import open from 'open';
import puppeteer from 'puppeteer';
import {startFlow} from 'lighthouse/lighthouse-core/fraggle-rock/api.js';
async function captureReport() {
const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
const flow = await startFlow(page, {name: 'Single Navigation'});
await flow.navigate('https://web.dev/performance-scoring/');
await browser.close();
const report = await flow.generateReport();
fs.writeFileSync('flow.report.html', report);
open('flow.report.html', {wait: false});
}
captureReport();
最もシンプルなフローです。レポートを開くと、1 つのステップのみを含む概要ビューが表示されます。そのステップをクリックすると、そのナビゲーションの従来の Lighthouse レポートが表示されます。
Lighthouse では通常、このページはキャッシュやローカル ストレージを先に消去してから読み込まれますが、サイトにアクセスする実際のユーザーは、キャッシュがコールド状態とウォーム状態の両方でアクセスすることになります。このようなコールド読み込みと、キャッシュがまだウォーム状態の状態でユーザーがページに戻ってくる場合では、パフォーマンスに大きな差が生じる可能性があります。
ウォーム読み込みのキャプチャ
このスクリプトに 2 つ目のナビゲーションを追加することもできます。今回は、Lighthouse のナビゲーションでデフォルトで行われるキャッシュとストレージの消去を無効にします。次の例では、web.dev 自体の記事を読み込み、キャッシュのメリットを確認しています。
async function captureReport() {
const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
const testUrl = 'https://web.dev/performance-scoring/';
const flow = await startFlow(page, {name: 'Cold and warm navigations'});
await flow.navigate(testUrl, {
stepName: 'Cold navigation'
});
await flow.navigate(testUrl, {
stepName: 'Warm navigation',
configContext: {
settingsOverrides: {disableStorageReset: true},
},
});
await browser.close();
const report = await flow.generateReport();
fs.writeFileSync('flow.report.html', report);
open('flow.report.html', {wait: false});
}
captureReport();
生成されたフロー レポートは次のようになります。
コールド ロードとウォーム ロードを組み合わせることで、実際のユーザーがどのような動作をしているか、より詳細に把握できます。ユーザーが同じアクセスで多くのページを読み込むサイトの場合は、ユーザーが実際にどのようなエクスペリエンスをしているかをよりリアルに把握できます。
スナップショット
スナップショットは、Lighthouse 監査を 1 つの時点で実行する新しいモードです。通常の Lighthouse 実行とは異なり、ページは再読み込みされません。これにより、ページをセットアップして、その状態(プルダウンが開いている、フォームが部分的に入力されているなど)でテストできるようになります。
この例では、Squoosh の詳細設定の新しい UI が Lighthouse の自動チェックに合格することを確認します。これらの設定は、画像が読み込まれ、オプション メニューが開いて詳細設定が表示されている場合にのみ表示されます。
このプロセスは Puppeteer でスクリプト化でき、各ステップで実際に Lighthouse のスナップショットを取得できます。
async function captureReport() {
const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
const flow = await startFlow(page, {name: 'Squoosh snapshots'});
await page.goto('https://squoosh.app/', {waitUntil: 'networkidle0'});
// Wait for first demo-image button, then open it.
const demoImageSelector = 'ul[class*="demos"] button';
await page.waitForSelector(demoImageSelector);
await flow.snapshot({stepName: 'Page loaded'});
await page.click(demoImageSelector);
// Wait for advanced settings button in UI, then open them.
const advancedSettingsSelector = 'form label[class*="option-reveal"]';
await page.waitForSelector(advancedSettingsSelector);
await flow.snapshot({stepName: 'Demo loaded'});
await page.click(advancedSettingsSelector);
await flow.snapshot({stepName: 'Advanced settings opened'});
browser.close();
const report = await flow.generateReport();
fs.writeFileSync('flow.report.html', report);
open('flow.report.html', {wait: false});
}
captureReport();
生成されたレポートでは、結果は概ね良好ですが、手動で確認が必要なユーザー補助の基準がいくつかある可能性があります。
期間
現場(CrUX など)とラボ(Lighthouse など)でのパフォーマンス結果の最大の違いの 1 つは、ユーザー入力がないことです。このような場合に役立つのが、期間(最後のユーザー フロー モード)です。
期間は、一定の期間にわたって Lighthouse 監査を実行します。ナビゲーションを含む場合も含まない場合もあります。これは、インタラクション中にページで何が起こっているかをキャプチャするのに最適な方法です。たとえば、デフォルトでは Lighthouse はページの読み込み中に CLS を測定しますが、フィールドでは、最初のナビゲーションからページが閉じられるまで CLS が測定されます。CLS のトリガーがユーザー操作である場合、以前の Lighthouse では検出して修正をサポートすることができませんでした。
これを示すために、広告用にスペースが予約されていない状態で、スクロール中に記事に広告が挿入される様子をシミュレートしたテストサイトを用意しました。長いカード群では、スロットがビューポートに入るとときどき赤い正方形が追加されます。これらの赤い正方形のスペースが予約されていないため、その下のカードがずれてレイアウトがずれます。
通常の Lighthouse ナビゲーションの CLS は 0 です。ただし、スクロールするとページに問題のあるレイアウト シフトが発生し、CLS 値が上昇します。
次のスクリプトでは、両方のアクションを含むユーザーフロー レポートを生成して、違いを確認します。
async function captureReport() {
const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
// Get a session handle to be able to send protocol commands to the page.
const session = await page.target().createCDPSession();
const testUrl = 'https://pie-charmed-treatment.glitch.me/';
const flow = await startFlow(page, {name: 'CLS during navigation and on scroll'});
// Regular Lighthouse navigation.
await flow.navigate(testUrl, {stepName: 'Navigate only'});
// Navigate and scroll timespan.
await flow.startTimespan({stepName: 'Navigate and scroll'});
await page.goto(testUrl, {waitUntil: 'networkidle0'});
// We need the ability to scroll like a user. There's not a direct puppeteer function for this, but we can use the DevTools Protocol and issue a Input.synthesizeScrollGesture event, which has convenient parameters like repetitions and delay to somewhat simulate a more natural scrolling gesture.
// https://chromedevtools.github.io/devtools-protocol/tot/Input/#method-synthesizeScrollGesture
await session.send('Input.synthesizeScrollGesture', {
x: 100,
y: 600,
yDistance: -2500,
speed: 1000,
repeatCount: 2,
repeatDelayMs: 250,
});
await flow.endTimespan();
await browser.close();
const report = await flow.generateReport();
fs.writeFileSync('flow.report.html', report);
open('flow.report.html', {wait: false});
}
captureReport();
これにより、通常のナビゲーションと、その後のナビゲーションとスクロールの両方を含む期間を比較するレポートが生成されます。
各ステップを詳しく見ると、ナビゲーション専用のステップの CLS は 0 です。素晴らしいサイトですね。
ただし、「移動とスクロール」の手順は異なります。現在、タイムスパンで利用できるのは、合計ブロック時間と Cumulative Layout Shift のみですが、このページの遅延読み込みのコンテンツは、明らかにサイトの CLS を奪っています。
これまで、問題がある CLS の動作を Lighthouse で特定することはできませんでしたが、実際のユーザーのエクスペリエンスではほぼ確実に表示されます。スクリプトによるインタラクションのパフォーマンス テストを行うと、ラボの忠実度が大幅に向上します。
フィードバックを探す
Lighthouse の新しいユーザーフロー API は多くの新しいことを行えますが、ユーザーが遭遇するシナリオを測定するのは複雑な場合があります。
ご不明な点がございましたら、Lighthouse のディスカッション フォーラムでお問い合わせください。バグや提案については、Issue Tracker からご報告ください。