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

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

Brendan Kenny
Brendan Kenny

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

  • טעינות של דפים עם מטמון חם
  • דפים עם קובץ שירות (service worker) מופעל
  • התייחסות לאינטראקציות פוטנציאליות של משתמשים

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

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

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

הגדרה

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

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

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

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

הדוח של Lighthouse שעוסק בניווט בדף ובגלילה עם CLS נמוך

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

מבקשים משוב

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

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