مقدمة لتشغيل المنارة برمجيًا
نشرت: 2022-03-10Lighthouse هي مجموعة Google من أدوات تحليل جودة مواقع الويب. يسمح لك بتقييم أداء موقعك ، وإمكانية الوصول إليه ، وتحسين محركات البحث ، والمزيد. كما أنه قابل للتكوين بدرجة كبيرة ، مما يجعله مرنًا بدرجة كافية ليكون مفيدًا لجميع المواقع ، من الأبسط إلى الأكثر تعقيدًا. تتضمن هذه المرونة عدة طرق مختلفة لإجراء الاختبارات ، مما يسمح لك باختيار الطريقة الأفضل لموقعك أو تطبيقك.
إحدى أبسط الطرق لتشغيل Lighthouse هي من خلال لوحة DevTools Lighthouse في Chrome. إذا فتحت موقعك في Chrome ثم فتحت DevTools من Chrome ، فسترى علامة التبويب "Lighthouse". من هناك ، إذا نقرت على "إنشاء تقرير" ، يجب أن تحصل على تقرير كامل لمقاييس جودة موقعك.
ما أركز عليه في هذا المقال ، مع ذلك ، يقع في الطرف الآخر من الطيف. يتيح لنا تشغيل Lighthouse برمجيًا باستخدام JavaScript تكوين عمليات تشغيل مخصصة ، وانتقاء واختيار الميزات التي نريد اختبارها ، وجمع النتائج وتحليلها ، وتحديد خيارات التكوين الفريدة لمواقعنا وتطبيقاتنا.
على سبيل المثال ، ربما تعمل على موقع يمكن الوصول إليه من خلال عناوين URL متعددة - لكل منها بياناته وتصميمه الخاص وربما حتى الترميز الذي تريد أن تكون قادرًا على تحليله. أو ربما ترغب في جمع البيانات من كل تشغيل اختباري وتجميعها أو تحليلها بطرق مختلفة. إن امتلاك القدرة على اختيار الطريقة التي تريد بها إجراء تحليل Lighthouse استنادًا إلى ما هو أفضل لموقعك أو تطبيقك يجعل من السهل مراقبة جودة الموقع وتحديد مكان وجود مشكلات في موقعك قبل أن تتراكم أو تتسبب في الكثير من المشكلات بالنسبة لك مستخدمو الموقع.
لا يعد تشغيل Lighthouse برمجيًا هو الخيار الأفضل لكل موقع وأنا أشجعك على استكشاف جميع الأساليب المختلفة التي صممها فريق Lighthouse لاستخدام الأداة. إذا قررت استخدام Lighthouse برمجيًا ، فمن المأمول أن تبدأ المعلومات والبرنامج التعليمي أدناه.
تخصيص خيارات المنارة
لا تقتصر ميزة تشغيل Lighthouse برمجيًا على القدرة على تكوين Lighthouse نفسها فحسب ، بل كل الأشياء التي قد تريدها أو تحتاج إلى القيام بها حول اختبارات Lighthouse. لدى Lighthouse بعض الوثائق الرائعة لتبدأ. لتحقيق أقصى استفادة من تشغيله برمجيًا ، مع ذلك ، هناك مكانان رئيسيان ستحتاج إلى البحث فيهما ومعرفة المزيد حول كيفية عمل Lighthouse: تكوين عمليات التشغيل الاختبارية والإبلاغ عن نتائج الاختبار الخاصة بك.
Lighthouse Test Run Configuration (تكوين تشغيل اختبار المنارة)
يعد تكوين تشغيل اختبار Lighthouse أحد تلك المهام التي يمكن أن تكون بسيطة أو معقدة كما تريد.
عند تشغيل Lighthouse برمجيًا ، هناك ثلاثة أماكن يمكنك من خلالها توفير خيارات مخصصة: عنوان URL الذي ستختبره ، وخيارات Chrome ، وكائن تكوين Lighthouse. يمكنك أن ترى كل هذه المعلمات الثلاثة في وظيفة تشغيل Lighthouse من وثائق Lighthouse:
function launchChromeAndRunLighthouse(url, opts, config = null) { return chromeLauncher.launch({chromeFlags: opts.chromeFlags}).then(chrome => { opts.port = chrome.port; return lighthouse(url, opts, config).then(results => { return chrome.kill().then(() => results.lhr) }); }); }
يمكنك استخدام أي كود تحتاجه لإنشاء هذه المعلمات. على سبيل المثال ، لنفترض أن لديك موقعًا به صفحات متعددة أو عناوين URL ترغب في اختبارها. ربما ترغب في إجراء هذا الاختبار في بيئة CI كجزء من مهام CI الخاصة بك ، والتحقق من جميع الصفحات الضرورية في كل مرة يتم تشغيل المهمة. باستخدام هذا الإعداد ، يمكنك استخدام JavaScript لإنشاء عناوين URL الخاصة بك وإنشاء حلقة تقوم بتشغيل Lighthouse لكل منها.
يمكن تحديد أي خيارات Chrome قد تحتاجها في كائن يتم تمريره إلى مشغل chrome. في المثال من التوثيق ، يحتوي كائن opts
على مصفوفة chromeFlags
يمكنك تمريرها إلى chrome-launcher ومنفذ حيث يمكنك حفظ المنفذ الذي يستخدمه مشغل chrome ثم تمريره إلى Lighthouse.
أخيرًا ، يتيح لك كائن تكوين Lighthouse إضافة أي خيارات خاصة بـ Lighthouse. توفر حزمة Lighthouse كائن تكوين افتراضي يمكن استخدامه كما هو أو توسيعه وتعديله. يمكنك استخدام هذا الكائن للقيام بالعديد من الأشياء ، بما في ذلك تحديد فئات اختبار Lighthouse التي تريد اختبارها.
يمكنك استخدام emulatedFormFactor
لتحديد ما إذا كنت تريد تشغيل الاختبار في جهاز محاكاة سطح المكتب أو الهاتف المحمول. يمكنك استخدام extraHeaders
لإضافة أي ملفات تعريف ارتباط قد تحتاج إلى استخدامها في المتصفح. على سبيل المثال ، اختبار يعمل فقط على فئة إمكانية الوصول على محاكي سطح المكتب والذي ينتج عنه النتائج حيث قد يكون لـ HTML كائن تكوين يبدو كالتالي:
const lighthouseOptions = { extends: 'lighthouse:default', settings: { onlyCategories: ['accessibility'], emulatedFormFactor:'desktop', output: ['html'], }, }
يمثل هذا المثال الحد الأدنى من التكوين. هناك الكثير الذي يمكنك القيام به. تحتوي مستندات تكوين Lighthouse على المزيد من المعلومات. لديهم أيضًا مجموعة من عينات كائنات التكوين لبعض عمليات التنفيذ الأكثر تعقيدًا.
تقرير النتائج المخصصة
عند تشغيل Lighthouse برمجيًا ، يمكنك إرجاع النتائج في واحد أو أكثر من ثلاثة خيارات منسقة - وهذه هي القطعة الأكثر إثارة في رأيي - يمكنك الوصول إلى كائن Lighthouse Result (LHR) الخام.
HTML ، JSON ، CSV
يقوم Lighthouse تلقائيًا بتنسيق النتائج بثلاث طرق مختلفة: HTML أو JSON أو CSV. هذه كلها نتائج مهيأة مسبقًا استنادًا إلى نموذج الإبلاغ الأساسي Lighthouse ، وهو ما تراه إذا أجريت اختبار Lighthouse داخل Chrome DevTools ، على سبيل المثال. في كائن التكوين lighthouseOptions
من القسم السابق ، يمكنك رؤية مفتاح output
الذي يحتوي على مصفوفة بسلسلة واحدة: html
. يشير هذا إلى أنني أريد فقط إرجاع النتائج بتنسيق HTML. إذا أردت الحصول على النتائج بتنسيق HTML و JSON ، فستبدو هذه المصفوفة بالشكل ['html', 'json']
.
بمجرد تشغيل Lighthouse ، سيعيد كائن نتائج يحتوي على مفتاحين: report
و lhr
. سنتحدث عن محتويات مفتاح lhr
في القسم التالي ، لكن مفتاح report
يحتوي على مصفوفة بالنتائج المنسقة كما طلبت. لذلك ، على سبيل المثال ، إذا طلبنا ['html', 'json']
، فستحتوي results.report[0]
على نتائجنا المنسقة بتنسيق HTML وسيحتوي results.report[1]
على نتائجنا بتنسيق JSON.
كائن LHR
يتيح لك تشغيل Lighthouse برمجيًا أيضًا الوصول إلى كائن نتائج أكثر مرونة: كائن LHR. يحتوي هذا الكائن على النتائج الأولية وبعض البيانات الوصفية من مسار المنارة. يمكن العثور على وثائق أكثر اكتمالاً في مستودع Lighthouse Github.
يمكنك استخدام هذه النتائج بأي عدد من الطرق ، بما في ذلك إنشاء تقارير مخصصة وجمع البيانات من عدة عمليات تشغيل للتحليل.
مثال: إجراء اختبار إمكانية الوصول للجوال وسطح المكتب
لنفترض أن لدي موقعًا يقوم بتحميل مكونات مختلفة اعتمادًا على ما إذا كان المستخدم يستخدم شاشة أصغر أو شاشة أكبر ، مما يعني أن HTML لكل إصدار من الموقع سيكون مختلفًا قليلاً. أريد التأكد من حصول كلا الإصدارين من الموقع على 95 درجة في اختبارات الوصول إلى Lighthouse وأنه لا يتم الالتزام بأي كود لفرعنا main
الذي لا يفي بهذا المعيار.
ملاحظة : إذا كنت ترغب في رؤية مثال عملي للرمز أدناه لتحليل صفحة Sparkbox الرئيسية ، يمكنك العثور على المستودع هنا.

يمكنني تكوين Lighthouse لتشغيل فئة إمكانية الوصول مرتين ، مع توفير كائنات تكوين مختلفة لكل منها - أحدهما يقوم بإعداد emulatedFormFactor
على desktop
والآخر يقوم بتعيينه على mobile
. طريقة سهلة للقيام بذلك هي إنشاء مصفوفة من كلا الكائنين ، كما هو موضح أدناه.
const lighthouseOptionsArray = [ { extends: 'lighthouse:default', settings: { onlyCategories: ['accessibility'], emulatedFormFactor:'desktop', output: ['html', 'json'], }, }, { extends: 'lighthouse:default', settings: { onlyCategories: ['accessibility'], emulatedFormFactor:'mobile', output: ['html', 'json'], }, }, ]
بعد ذلك ، يمكنني إنشاء وظيفة ستمر عبر هذه المصفوفة وتشغيل اختبار Lighthouse لكل كائن موجود داخل المصفوفة.
هناك شيء واحد يجب ملاحظته وهو أنه من الضروري إدخال تأخير بين كل عملية تشغيل ، وإلا فقد يتم الخلط بين Chromium وستنتهي أخطاء التشغيل. من أجل القيام بذلك ، أضفت وظيفة wait
تُرجع وعدًا عند اكتمال الفاصل الزمني setTimeout
.
function wait(val) { return new Promise(resolve => setTimeout(resolve, val)); } function launchLighthouse(optionSet, opts, results) { return chromeLauncher .launch({ chromeFlags: opts.chromeFlags }) .then(async chrome => { opts.port = chrome.port; try { results = await lighthouse(url, opts, optionSet); } catch (e) { console.error("lighthouse", e); } if (results) reportResults(results, runEnvironment, optionSet, chrome); await wait(500); chrome.kill(); }); } async function runLighthouseAnalysis() { let results; const opts = { chromeFlags: ["--no-sandbox", "--headless"] }; for (const optionSet of lighthouseOptionsArray) { console.log("****** Starting Lighthouse analysis ******"); await launchLighthouse(optionSet, opts, results); } }
في هذه الحالة ، أقوم بإرسال النتائج إلى وظيفة reportResults
. من هناك ، أقوم بحفظ النتائج في الملفات المحلية ، وطباعة النتائج إلى وحدة التحكم ، وإرسال النتائج إلى وظيفة ستحدد ما إذا كانت الاختبارات تجتاز أو تفشل في عتبة الوصول الخاصة بنا.
async function reportResults(results, runEnvironment, optionSet, chrome) { if (results.lhr.runtimeError) { return console.error(results.lhr.runtimeError.message); } await writeLocalFile(results, runEnvironment, optionSet); printResultsToTerminal(results.lhr, optionSet); return passOrFailA11y(results.lhr, optionSet, chrome); }
بالنسبة لهذا المشروع ، أريد أن أكون قادرًا على حفظ نتائج JSON في دليل محدد لعمليات اختبار CI الخاصة بنا وملف HTML في دليل محدد لعمليات الاختبار المحلية الخاصة بنا. الطريقة التي تعرض بها Lighthouse هذه الأنواع المختلفة من النتائج هي في مصفوفة بالترتيب الذي تم طلبها به.
إذن ، في هذا المثال ، في كائن lighthouseOptions
الخاص بنا ، تطلب المصفوفة HTML أولاً ، ثم JSON. لذلك ستحتوي مصفوفة report
على النتائج بتنسيق HTML أولاً والنتائج بتنسيق JSON ثانيًا. تقوم وظيفة writeToLocalFile
بعد ذلك بحفظ الإصدار الصحيح من النتائج في ملف باسم مخصص.
function createFileName(optionSet, fileType) { const { emulatedFormFactor } = optionSet.settings; const currentTime = new Date().toISOString().slice(0, 16); const fileExtension = fileType === 'json' ? 'json' : 'html'; return `${currentTime}-${emulatedFormFactor}.${fileExtension}`; } function writeLocalFile(results, runEnvironment, optionSet) { if (results.report) { const fileType = runEnvironment === 'ci' ? 'json' : 'html'; const fileName = createFileName(optionSet, fileType); fs.mkdirSync('reports/accessibility/', { recursive: true }, error => { if (error) console.error('error creating directory', error); }); const printResults = fileType === 'json' ? results.report[1] : results.report[0]; return write(printResults, fileType, `reports/accessibility/${fileName}`).catch(error => console.error(error)); } return null; }
أريد أيضًا طباعة النتائج على الجهاز مع انتهاء الاختبار. يوفر هذا طريقة سريعة وسهلة لعرض النتائج دون الحاجة إلى فتح ملف.
function printResultsToTerminal(results, optionSet) { const title = results.categories.accessibility.title; const score = results.categories.accessibility.score * 100; console.log('\n********************************\n'); console.log(`Options: ${optionSet.settings.emulatedFormFactor}\n`); console.log(`${title}: ${score}`); console.log('\n********************************'); }
وأخيرًا ، أريد أن أكون قادرًا على الفشل في اختباراتي إذا كانت درجات إمكانية الوصول لا تفي بعتبي من 95.
function passOrFailA11y(results, optionSet, chrome) { const targetA11yScore = 95; const { windowSize } = optionSet; const accessibilityScore = results.categories.accessibility.score * 100; if (accessibilityScore) { if (windowSize === 'desktop') { if (accessibilityScore < targetA11yScore) { console.error(`Target accessibility score: ${targetA11yScore}, current accessibility score ${accessibilityScore}`); chrome.kill(); process.exitCode = 1; } } if (windowSize === 'mobile') { if (accessibilityScore < targetA11yScore) { console.error(`Target accessibility score: ${targetA11yScore}, current accessibility score ${accessibilityScore}`); chrome.kill(); process.exitCode = 1; } } } }
أدعوكم جميعًا للتلاعب بها واستكشاف جميع الطرق المختلفة التي يمكن أن تساعد بها Lighthouse في مراقبة جودة موقعك.
ملاحظات نهائية
بينما أبقيت المثال أعلاه بسيطًا نسبيًا عن قصد ، آمل أن يكون قد أعطاك نظرة عامة جيدة على ما يمكن إنجازه عند تشغيل Lighthouse برمجيًا. وآمل أن يكون هذا مصدر إلهام لك لإيجاد طرق جديدة لاستخدام هذه الأداة المرنة والقوية.
كما قال بيتر دراكر:
"إذا كنت لا تستطيع قياسه ، فلا يمكنك تحسينه."
إن القدرة على قياس جودة موقعنا على الويب ومراقبتها ، خاصة بالنسبة للمواقع المعقدة ، ستقطع شوطًا طويلاً نحو مساعدتنا في بناء شبكة ويب أفضل.
مزيد من القراءة على SmashingMag:
- اختبار A / B لتجارب الأجهزة المحمولة أولاً
- كيفية اختبار مفهوم التصميم من أجل الفعالية
- أهمية اختبار إمكانية الوصول اليدوي
- التعلم الآلي لمطوري الواجهة الأمامية باستخدام Tensorflow.js
- ابدأ بتصميم واجهة المستخدم باستخدام هذه النصائح لتسريع سير عملك
واجهة أمامية مفيدة وبتات UX مفيدة ، يتم تسليمها مرة واحدة في الأسبوع.
مع الأدوات التي تساعدك على إنجاز عملك بشكل أفضل. اشترك واحصل على قوائم التحقق من تصميم الواجهة الذكية من Vitaly بتنسيق PDF عبر البريد الإلكتروني.
على الواجهة الأمامية وتجربة المستخدم. يثق به 190.000 شخص.