โฟลว์ของผู้ใช้ 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 (จนถึงตอนนี้) ซึ่งก็คือการวิเคราะห์ Cold Load ของหน้าเว็บ โหมดนี้ใช้เพื่อตรวจสอบประสิทธิภาพการโหลดหน้าเว็บ แต่โฟลว์ผู้ใช้ยังเปิดโอกาสให้ได้รับข้อมูลเชิงลึกใหม่ๆ ด้วย

วิธีเขียนสคริปต์ 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 และ Warm และอาจมีความแตกต่างด้านประสิทธิภาพอย่างมากระหว่าง Cold Load เช่นนี้กับผู้ใช้ที่กลับมายังหน้าเว็บที่มีแคชแบบ Warm อยู่

กำลังจับภาพการโหลดที่อบอุ่น

นอกจากนี้ คุณยังเพิ่มการนําทางที่ 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 ที่แสดงการนําทาง 2 รายการ ได้แก่ การนําทางแบบ Cold และการนําทางแบบ Warm ซึ่งมีคะแนนประสิทธิภาพสูงกว่า

การรวมการโหลดแบบ Cold และ Warm จะช่วยให้เห็นภาพที่สมบูรณ์ยิ่งขึ้นเกี่ยวกับสิ่งที่ผู้ใช้จริงกำลังประสบอยู่ หากคุณมีเว็บไซต์ที่ผู้ใช้โหลดหลายหน้าในการเข้าชมครั้งเดียวกัน ข้อมูลนี้อาจช่วยให้คุณเห็นภาพที่สมจริงยิ่งขึ้นเกี่ยวกับสิ่งที่ผู้ใช้พบในภาคสนาม

สแนปชอต

สแนปชอตเป็นโหมดใหม่ที่เรียกใช้การตรวจสอบ Lighthouse ณ จุดใดจุดหนึ่งในเวลา ซึ่งแตกต่างจากการเรียกใช้ Lighthouse ตามปกติ เนื่องจากจะไม่มีการโหลดหน้าซ้ำ ซึ่งจะช่วยให้คุณตั้งค่าหน้าเว็บและทดสอบหน้าเว็บในสถานะที่แน่นอนได้ เช่น เมื่อเปิดเมนูแบบเลื่อนลงหรือกรอกแบบฟอร์มบางส่วน

สำหรับตัวอย่างนี้ สมมติว่าคุณต้องการตรวจสอบว่า UI ใหม่สำหรับการตั้งค่าขั้นสูงภายใน 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) และในห้องทดลอง (เช่น จาก Lighthouse) คือการไม่มีข้อมูลจากผู้ใช้ นี่คือจุดที่ช่วงเวลา (โหมดโฟลว์ผู้ใช้โหมดสุดท้าย) จะช่วยได้

ช่วงเวลาจะเรียกใช้การตรวจสอบ Lighthouse ในช่วงระยะเวลาหนึ่ง ซึ่งอาจรวมหรือไม่รวมการนําทางก็ได้ ซึ่งเป็นวิธีที่ยอดเยี่ยมในการบันทึกสิ่งที่เกิดขึ้นกับหน้าเว็บระหว่างการโต้ตอบ ตัวอย่างเช่น โดยค่าเริ่มต้น Lighthouse จะวัด CLS ระหว่างการโหลดหน้าเว็บ แต่ในภาคสนาม ระบบจะวัด CLS ตั้งแต่การนำทางครั้งแรกจนกว่าหน้าเว็บจะปิด หากการโต้ตอบของผู้ใช้เป็นทริกเกอร์ของ CLS Lighthouse จะตรวจจับและช่วยแก้ไขไม่ได้ก่อนหน้านี้

การนําทาง Lighthouse ปกติจะมี CLS เป็น 0 อย่างไรก็ตาม เมื่อเลื่อนดู หน้าเว็บจะมีการเปลี่ยนแปลงเลย์เอาต์ที่เป็นปัญหาและค่า CLS จะเพิ่มขึ้น

สคริปต์ต่อไปนี้จะสร้างรายงานโฟลว์ผู้ใช้ที่มีทั้ง 2 การดำเนินการเพื่อแสดงความแตกต่าง

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 ที่ครอบคลุมเฉพาะการนำทางหน้าเว็บที่มีเมตริกสีเขียวทั้งหมด

อย่างไรก็ตาม ขั้นตอน "ไปยังส่วนต่างๆ และเลื่อน" แสดงให้เห็นถึงเรื่องราวที่แตกต่างออกไป ปัจจุบันมีเพียงเวลาทั้งหมดในการบล็อกและ Cumulative Layout Shift เท่านั้นที่ใช้ได้ในช่วงเวลา แต่เนื้อหาที่โหลดแบบ Lazy Loading ในหน้านี้ทำให้ CLS ของเว็บไซต์ลดลงอย่างเห็นได้ชัด

รายงาน Lighthouse ที่ครอบคลุมการนำทางหน้าเว็บและการเลื่อนที่มี CLS ไม่ผ่าน

ก่อนหน้านี้ Lighthouse ไม่สามารถระบุลักษณะการทำงานของ CLS ที่เป็นปัญหาได้ แม้ว่าลักษณะการทำงานดังกล่าวจะปรากฏในประสบการณ์ของผู้ใช้จริงเกือบแน่นอนก็ตาม การทดสอบประสิทธิภาพผ่านการโต้ตอบตามสคริปต์ช่วยเพิ่มความแม่นยำของห้องปฏิบัติการได้อย่างมาก

ต้องการความคิดเห็น

API โฟลว์ผู้ใช้ใหม่ใน Lighthouse ทำสิ่งใหม่ๆ ได้มากมาย แต่อาจยังคงซับซ้อนในการวัดสถานการณ์ที่ผู้ใช้พบ

หากมีข้อสงสัย โปรดติดต่อเราในฟอรัมการสนทนาของ Lighthouse และแจ้งข้อบกพร่องหรือคำแนะนำในIssue Tracker