Lighthouse のユーザーフロー

新しい Lighthouse API を試して、ユーザーフロー全体のパフォーマンスとベスト プラクティスを測定します。

Brendan Kenny
Brendan Kenny

Lighthouse は、初期ページ読み込み時のパフォーマンスとベスト プラクティスをテストするための優れたツールです。しかし、従来は、Lighthouse を使用してページのライフサイクルの他の側面を分析することは困難でした。たとえば、次のような側面です。

  • ウォーム キャッシュでのページ読み込み
  • Service Worker が有効になっているページ
  • ユーザー インタラクションの可能性を考慮する

つまり、Lighthouse が重要な情報を見逃す可能性があります。Core Web Vitals は、キャッシュが空のページ読み込みだけでなく、すべてのページ読み込みに基づいています。また、Cumulative Layout Shift(CLS)などの指標は、ページが開いている間ずっと測定可能です。

Lighthouse には、ページのライフサイクル内の任意の時点でラボテストを実行できる新しいユーザーフロー API があります。Puppeteer は、ページ読み込みをスクリプト化し、合成ユーザー インタラクションをトリガーするために使用されます。Lighthouse は、これらのインタラクション中に重要な分析情報をキャプチャするために、複数の方法で呼び出すことができます。つまり、ページの読み込み中とページでのインタラクション中にパフォーマンスを測定できます。ユーザー補助チェックは、最初のビューだけでなく、購入手続きのフローの深い部分でも CI で実行して、回帰がないことを確認できます。

ユーザーフローが機能することを確認するために作成された Puppeteer スクリプトのほぼすべてに、任意の時点で Lighthouse を挿入して、パフォーマンスとベスト プラクティスを全体的に測定できるようになりました。このチュートリアルでは、ユーザーフローのさまざまな部分(ナビゲーション、スナップショット、タイムスパン)を測定できる新しい Lighthouse モードについて説明します。

セットアップ

ユーザーフロー 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 でページ読み込みをキャプチャするスクリプトを作成するには:

  1. Puppeteer を使用してブラウザを開きます。
  2. Lighthouse ユーザーフローを開始します。
  3. ターゲット 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 レポートが表示されます。

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();

生成されるフローレポートは次のようになります。

2 つのナビゲーション(コールド ナビゲーションとウォーム ナビゲーション)を示す Lighthouse フロー レポート。ウォーム ナビゲーションのパフォーマンス スコアの方が高い

コールド ロードとウォーム ロードを組み合わせることで、実際のユーザーが体験していることをより詳細に把握できます。ユーザーが同じ訪問で多くのページを読み込むサイトがある場合、これにより、フィールドでユーザーが経験していることをより現実的に把握できる可能性があります。

スナップショット

スナップショットは、Lighthouse 監査を 1 回だけ実行する新しいモードです。通常の Lighthouse の実行とは異なり、ページは再読み込みされません。これにより、ページを設定して、プルダウンが開いている状態やフォームに部分的に入力されている状態など、正確な状態でテストできるようになります。

この例では、Squoosh 内の [Advanced Settings] の新しい UI が Lighthouse の自動チェックに合格することを確認するとします。これらの設定は、画像が読み込まれ、オプション メニューが展開されて詳細設定が表示されている場合にのみ表示されます。

Squoosh の詳細設定メニュー
Squoosh の詳細設定メニュー

このプロセスは 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();

生成されたレポートには、結果は概ね良好であることが示されていますが、手動で確認する必要があるユーザー補助の基準がいくつかあります。

取得した一連のスナップショットを示す Lighthouse フロー レポート

期間

フィールド(CrUX など)とラボ(Lighthouse など)のパフォーマンス結果の最大の違いの一つは、ユーザー入力がないことです。ここで、最後のユーザーフロー モードであるタイムスパンが役立ちます。

タイムスパンは、一定期間にわたって 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.example.com/';
  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();

これにより、通常のナビゲーションと、ナビゲーションとその後のスクロールの両方を含むタイムスパンを比較するレポートが生成されます。

取得された一連のスナップショットを示す Lighthouse フロー レポート

各ステップを詳しく調べると、ナビゲーションのみのステップの CLS は 0 です。素晴らしいサイトですね。

ページ ナビゲーションのみを対象とし、すべての指標が緑色で表示されている Lighthouse レポート

しかし、「移動とスクロール」のステップでは、異なる結果が示されています。現在、タイムスパンで利用できるのは Total Blocking Time と Cumulative Layout Shift のみですが、このページの遅延読み込みコンテンツは、サイトの CLS を明らかに低下させています。

ページ ナビゲーションとスクロールを対象とした Lighthouse レポートで、CLS が不合格になっている

以前は、Lighthouse ではこの問題のある CLS の動作を特定できませんでしたが、実際のユーザーのエクスペリエンスにはほぼ確実に現れていました。スクリプト化されたインタラクションに対するパフォーマンス テストにより、ラボの忠実度が大幅に向上します。

フィードバックを求めている

Lighthouse の新しいユーザーフロー API では、さまざまな新しいことが可能になりますが、ユーザーが遭遇するシナリオの種類を測定するのは、依然として複雑な場合があります。

ご不明な点がございましたら、Lighthouse のディスカッション フォーラムからお問い合わせください。また、バグやご提案がございましたら、Issue Trackerからご報告ください。