תהליכי העבודה ב-Lighthouse

כדאי לנסות את Lighthouse API חדש כדי למדוד ביצועים ושיטות מומלצות לכל אורך התהליך של המשתמש.

Brendan Kenny
Brendan Kenny

Lighthouse הוא כלי מצוין לבדיקת ביצועים ושיטות מומלצות במהלך טעינת הדף הראשונית. עם זאת, באופן מסורתי היה קשה להשתמש ב-Lighthouse כדי לנתח היבטים אחרים של חיי הדף, כמו:

  • הדף נטען באמצעות מטמון חם
  • דפים שהופעל בהם Service Worker
  • התייחסות לאינטראקציות פוטנציאליות של משתמשים

המשמעות היא שמערכת Lighthouse עלולה לפספס מידע חיוני. מדדי הליבה לבדיקת חוויית המשתמש באתר מבוססים על כל הטעינות של דפים, לא רק על דפים עם מטמון ריק. בנוסף, אפשר למדוד מדדים כמו Cumulative Layout Shift (CLS) לכל משך הזמן שבו דף נפתח.

ב-Lighthouse יש ממשק API חדש לזרימת משתמשים שמאפשר לבצע בדיקות מעבדה בכל שלב במהלך החיים של דף. Puppeteer משמש לטעינת דפים ולהפעלת אינטראקציות של משתמשים סינתטיים. אפשר להפעיל את Lighthouse במספר דרכים כדי להפיק תובנות מרכזיות במהלך האינטראקציות האלה. כלומר, ניתן למדוד את הביצועים גם במהלך טעינת הדף וגם במהלך אינטראקציות עם הדף. אפשר לבצע בדיקות נגישות ב-CI, לא רק בתצוגה הראשונית, אלא גם עמוק בתוך תהליך התשלום כדי לוודא ששום דבר לא חוזר לאחור.

עכשיו אפשר להוסיף Lighthouse לכל סקריפט של Puppeteer כדי להבטיח זרימה של משתמש פעיל בכל שלב, כדי למדוד את הביצועים ושיטות מומלצות לכל אורכו. המדריך הזה כולל הסבר על המצבים החדשים של Lighthouse שיכולים למדוד חלקים שונים בתהליכים של המשתמשים: ניווטים, תמונות מצב וטווחי זמן.

הגדרה

ממשקי ה-API של זרימת המשתמשים עדיין נמצאים בתצוגה מקדימה, אבל הם זמינים ב-Lighthouse היום. כדי לנסות את ההדגמות הבאות, יש צורך בגרסה 14 ומעלה של Node. יוצרים ספרייה ריקה ומריצים בה את הפקודה:

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

זה התהליך הפשוט ביותר. כשפותחים את הדוח, מוצגת בו תצוגת סיכום עם שלב אחד בלבד. לחיצה על השלב הזה תפתח דוח רגיל של Lighthouse על אותו ניווט.

דוח זרימה של Lighthouse שבו מוצג ניווט יחיד
הצגת הדוח בזמן אמת

כפי שקורה בדרך כלל ב-Lighthouse, דף זה נטען לאחר שניקוי המטמון או האחסון המקומי בוצע קודם, אבל למשתמשים אמיתיים שייכנסו לאתר יהיה שילוב של ביקורים עם מטמון במצב קר וחמים, ויכול להיות הבדל גדול בביצועים בין טעינה במצב התחלתי (cold) לבין משתמש שחוזר לדף עם מטמון עדיין חמים.

צילום של עומס חם

אפשר גם להוסיף ניווט שני לסקריפט הזה, והפעם להשבית את ניקוי המטמון והאחסון שמתבצע על ידי 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 שמציג שני ניווטים, אחד קר והשני חם, עם ציון ביצועים גבוה יותר
הצגת הדוח בזמן אמת

השילוב של טעינה קרה וטעינה חמה מספק תמונה מלאה יותר על החוויה של משתמשים אמיתיים. אם יש לכם אתר שבו משתמשים טוענים דפים רבים באותו ביקור, יכול להיות שתוכלו לראות בצורה מציאותית יותר את מה שהם רואים בשדה.

תמונת מצב

קובצי snapshot הם מצב חדש שבו מריצים ביקורות של Lighthouse בנקודת זמן אחת. בניגוד להרצה רגילה של Lighthouse, הדף לא נטען מחדש. כך מתבטלת היכולת להגדיר דף ולבדוק אותו במצבו המדויק: לדוגמה, באמצעות תפריט נפתח פתוח או טופס שמולא באופן חלקי.

בדוגמה הזו, נניח שאתם רוצים לבדוק שחלק מממשק המשתמש החדש של ההגדרות המתקדמות ב-Squoosh עובר את הבדיקות האוטומטיות של 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) לבין בשיעור ה-Lab (כמו מ-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.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();

הפעולה הזו יוצרת דוח שמשווה בין ניווט רגיל לבין פרק זמן שכולל גם ניווט וגם גלילה לאחר מכן:

דוח זרימה של Lighthouse שמציג קבוצת תמונות מצב שצולמו
הצגת הדוח בזמן אמת

בהמשך מפורטים כל שלב, בשלב 'ניווט בלבד' מוצג ערך CLS של 0. אתר מצוין!

הדוח Lighthouse שכולל רק ניווט בדפים עם כל המדדים הירוקים

לעומת זאת, האפשרות 'ניווט וגלילה' מספרת סיפור אחר. בשלב הזה, רק 'זמן חסימה כולל' ו'שינוי פריסה מצטברת' זמינים לפי פרקי זמן, אבל התוכן שנטען באופן מדורג בדף הזה מנצל בבירור את ה-CLS של האתר.

דוח של Lighthouse שמספק מידע על ניווט בדפים וגלילה עם כשל ב-CLS

בעבר, Lighthouse לא הייתה אפשרות לזהות את ההתנהגות הבעייתית הזו של CLS, אבל היא הייתה מופיעה כמעט בוודאות בחוויה של משתמשים אמיתיים. בדיקת הביצועים באינטראקציות שמבוססות על סקריפטים משפרת משמעותית את האיכות בשיעור ה-Lab.

מתבצע חיפוש של משוב

באמצעות ממשקי ה-API החדשים של זרימת משתמשים ב-Lighthouse אפשר לעשות הרבה דברים חדשים, אבל עדיין יכול להיות מורכב.

אתם יכולים לפנות אם יש לכם שאלות בפורומים לדיון ב-Lighthouse או לדווח על באגים או הצעות באתר המעקב אחר בעיות.