جرِّب واجهة برمجة تطبيقات Lighthouse الجديدة لقياس الأداء وأفضل الممارسات في مسار المستخدم.
Lighthouse هي أداة رائعة لاختبار الأداء وأفضل الممارسات أثناء تحميل الصفحة الأولي. ومع ذلك، كان من الصعب في السابق استخدام Lighthouse لتحليل جوانب أخرى من عمر الصفحة، مثل:
- يتم تحميل الصفحة باستخدام ذاكرة تخزين مؤقت دافئة
- الصفحات التي تتضمّن مشغّل خدمات مفعَّلاً
- مراعاة تفاعلات المستخدمين المحتملة
وهذا يعني أنّ Lighthouse قد تفوّت معلومات حيوية. تستند مؤشرات أداء الويب الأساسية إلى جميع عمليات تحميل الصفحات، وليس فقط تلك التي تحتوي على ذاكرة تخزين مؤقت فارغة. بالإضافة إلى ذلك، يمكن قياس مقاييس مثل متغيّرات التصميم التراكمية (CLS) طوال مدة فتح الصفحة.
تتضمّن أداة Lighthouse واجهة برمجة تطبيقات جديدة لمسار المستخدم تتيح إجراء الاختبارات المعملية في أي وقت خلال فترة عمل الصفحة. يُستخدَم Puppeteer لكتابة نصوص برمجية لعمليات تحميل الصفحات وبدء تفاعلات المستخدمين الاصطناعية، ويمكن استدعاء Lighthouse بطرق متعددة للحصول على إحصاءات رئيسية خلال هذه التفاعلات. وهذا يعني أنّه يمكن قياس الأداء أثناء تحميل الصفحة و أثناء التفاعلات مع الصفحة. يمكن إجراء عمليات التحقّق من تسهيل الاستخدام في CI، ليس فقط في العرض الأولي ولكن في أعماق مسار الدفع للتأكّد من عدم تراجع أي شيء.
يمكن الآن إدراج Lighthouse في أي نقطة في أي نص برمجي تقريبًا في Puppeteer مكتوب لضمان مسار مستخدم فعّال، وذلك لقياس الأداء وأفضل الممارسات طوال الوقت. سيتناول هذا الدليل التعليمي أوضاع Lighthouse الجديدة التي يمكنها قياس أجزاء مختلفة من مسارات المستخدمين: عمليات التنقّل واللقطات والفترات الزمنية.
الإعداد
لا تزال واجهات برمجة التطبيقات الخاصة بمسار المستخدم في مرحلة المعاينة، ولكنّها متاحة في 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 من أجل التقاط عملية تحميل صفحة:
- استخدِم 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();
هذا هو أبسط مسار. عند فتح التقرير، يعرض طريقة عرض ملخّصة تتضمّن الخطوة الواحدة فقط. سيؤدي النقر على هذه الخطوة إلى الكشف عن تقرير Lighthouse تقليدي لعملية التنقّل هذه.
كما هو معتاد في Lighthouse، يتم تحميل هذه الصفحة بعد محو أي ذاكرة تخزين مؤقت أو مساحة تخزين محلية أولاً، ولكن المستخدمين الحقيقيين الذين يزورون موقعًا إلكترونيًا سيحصلون على مزيج من الزيارات باستخدام ذاكرة التخزين المؤقت الباردة والدافئة، ويمكن أن يكون هناك اختلاف كبير في الأداء بين تشغيل على البارد مثل هذا والمستخدم الذي يعود إلى الصفحة باستخدام ذاكرة تخزين مؤقت لا تزال دافئة.
التقاط حمولة دافئة
يمكنك أيضًا إضافة عملية تنقّل ثانية إلى هذا النص البرمجي، وهذه المرة من خلال إيقاف محو ذاكرة التخزين المؤقت ومساحة التخزين التي تنفّذها أداة 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 في نقطة زمنية واحدة. بخلاف عملية تشغيل Lighthouse العادية، لا تتم إعادة تحميل الصفحة. يتيح لك ذلك إعداد صفحة واختبارها في حالتها الدقيقة: مع فتح قائمة منسدلة أو ملء نموذج جزئيًا، على سبيل المثال.
في هذا المثال، لنفترض أنّك تريد التأكّد من أنّ بعض واجهات المستخدم الجديدة لـ "الإعدادات المتقدّمة" ضمن Squoosh تجتاز عمليات التحقّق المبرمَجة في 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) في عدم توفّر إدخالات من المستخدمين. هنا يأتي دور الفترة الزمنية، وهي آخر وضع لمسار المستخدم.
تُجري الفترة الزمنية عمليات تدقيق Lighthouse على مدار فترة زمنية معيّنة، وقد تتضمّن أو لا تتضمّن عملية تنقّل. هذه طريقة رائعة لتسجيل ما يحدث في الصفحة أثناء التفاعلات. على سبيل المثال، تقيس أداة Lighthouse تلقائيًا متغيّر CLS أثناء تحميل الصفحة، ولكن في الميدان، يتم قياس متغيّر CLS من التنقّل الأولي إلى أن يتم إغلاق الصفحة. إذا كانت تفاعلات المستخدمين هي السبب في حدوث متغيّرات التصميم التراكمية، فلن تتمكّن أداة Lighthouse من رصدها والمساعدة في إصلاحها.
ستكون قيمة CLS في التنقّل العادي في Lighthouse هي 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();
يؤدي ذلك إلى إنشاء تقرير يقارن بين عملية تنقّل عادية وفترة زمنية تحتوي على كل من التنقّل والتمرير بعد ذلك:
بالتعمّق في كل خطوة، تظهر قيمة CLS تساوي 0 في خطوة التنقّل فقط. موقع إلكتروني رائع!
ومع ذلك، فإن خطوة "التنقل والتمرير" تروي قصة مختلفة. في الوقت الحالي، لا يتوفّر سوى "إجمالي وقت الحظر" و"متغيّرات التصميم التراكمية" في الفترات الزمنية، ولكنّ المحتوى الذي يتم تحميله بشكل بطيء على هذه الصفحة يؤدي بوضوح إلى انخفاض قيمة "متغيّرات التصميم التراكمية" للموقع الإلكتروني.
في السابق، لم يكن بإمكان Lighthouse تحديد سلوك CLS الذي يتضمّن مشاكل، على الرغم من أنّه سيظهر بالتأكيد في تجربة المستخدمين الحقيقيين. يؤدي اختبار الأداء من خلال التفاعلات المستندة إلى نصوص برمجية إلى تحسين دقة الاختبارات المعملية بشكل كبير.
أبحث عن ملاحظات
يمكن لواجهات برمجة التطبيقات الجديدة الخاصة بمسار المستخدم في Lighthouse تنفيذ العديد من المهام الجديدة، ولكن قد يظل من الصعب قياس نوع السيناريوهات التي يواجهها المستخدمون.
يُرجى التواصل معنا لطرح أي أسئلة في منتديات المناقشة في Lighthouse، وإرسال أي أخطاء أو اقتراحات في أداة تتبُّع المشاكل.