آلية إنشاء "إحصاءات الأداء" والغرض من ذلك

في الإصدار 102 من Chrome، ستلاحظ لوحة تجريبية جديدة، وهي إحصاءات الأداء، في "أدوات مطوّري البرامج". في هذه المشاركة، سنناقش ليس فقط سبب عملنا على لوحة جديدة، بل سنوضّح أيضًا التحديات الفنية التي واجهتنا والقرارات التي اتّخذناها خلال هذه العملية.

ALT_TEXT_HERE

ما هو الغرض من إنشاء لوحة أخرى؟

نشرنا فيديو حول سبب إنشاء لوحة "إحصاءات الأداء" وكيفية الحصول على إحصاءات قابلة للاستخدام عن أداء موقعك الإلكتروني، إذا لم يسبق لك الاطّلاع عليها.

تشكّل لوحة الأداء الحالية مصدرًا رائعًا إذا كنت تريد الاطّلاع على جميع البيانات الخاصة بموقعك الإلكتروني في مكان واحد، ولكننا نعتقد أنّ ذلك قد يكون مربكًا بعض الشيء. إذا لم تكن خبيرًا في الأداء، فمن الصعب أن تعرف بالضبط ما تبحث عنه وأجزاء التسجيل ذات الصلة.

انتقِل إلى لوحة "الإحصاءات"، حيث سيظل بإمكانك عرض مخطط زمني لتتبُّع بياناتك وفحصها، بالإضافة إلى الحصول على قائمة مفيدة بما تعتبره "أدوات المطوّرين" "الإحصاءات" الرئيسية التي تستحق التدقيق فيها. ستحدِّد ميزة "الإحصاءات" بعض المشاكل، مثل طلبات حظر العرض ومتغيّرات التصميم والمهام التي تستغرق وقتًا طويلاً، على سبيل المثال لا الحصر، والتي يمكن أن تؤثّر سلبًا في أداء تحميل الصفحة في موقعك الإلكتروني وعلى نتائج مؤشرات أداء الويب الأساسية (CWV) لموقعك الإلكتروني. بالإضافة إلى عملية الإبلاغ عن المشاكل، ستوفّر لك "إحصاءات الأداء" اقتراحات قابلة للتنفيذ لتحسين نتائج CWV، كما ستزوّدك بروابط تؤدي إلى المزيد من المراجع والمستندات.

رابط الملاحظات والآراء في اللوحة

هذه اللوحة تجريبية ونريد معرفة ملاحظاتك. يُرجى إعلامنا إذا واجهت أي أخطاء أو إذا كانت لديك طلبات ميزات تعتقد أنّها ستساعدك عند العمل على تحسين أداء موقعك الإلكتروني.

كيفية إنشاء "إحصاءات الأداء"

مثل بقية أدوات مطوري البرامج، أنشأنا ميزة "إحصاءات الأداء" في TypeScript واستخدمنا مكوّنات الويب المستندة إلى lit-html لإنشاء واجهة المستخدم. تختلف "إحصاءات الأداء" عن "إحصاءات YouTube" في أنّ واجهة المستخدم الأساسية هي عنصر HTML canvas، ويتم رسم المخطط الزمني على هذه اللوحة. يأتي الكثير من التعقيد من إدارة هذه اللوحة: ليس فقط رسم التفاصيل الصحيحة في المكان الصحيح، ولكن إدارة أحداث الماوس (على سبيل المثال: أين نقر المستخدم على لوحة الرسم؟ هل نقروا على حدث رسمناه؟) والتأكد من أننا نعيد عرض اللوحة بشكل فعال.

مقاطع صوتية متعددة ضمن لوحة واحدة

بالنسبة إلى موقع إلكتروني معيّن، هناك عدّة "مسارات" نريد عرضها، يمثّل كلّ منها فئة مختلفة من البيانات. على سبيل المثال، ستعرض لوحة "الإحصاءات" ثلاثة مسارات تلقائيًا:

ونحن نواصل إضافة ميزات إلى اللوحة، لذا نتوقع إضافة المزيد من القنوات.

كان هدفنا الأولي هو أن يعرض كل مسار من هذه المسارات <canvas> خاصًا به، بحيث تصبح طريقة العرض الرئيسية عبارة عن عناصر متعددة للوحة مكدسة عموديًا. سيؤدي ذلك إلى تبسيط العرض على مستوى المقطع الصوتي، لأنّه يمكن عرض كل مقطع صوتي بشكل منفصل ولن يكون هناك خطر من عرض مقطع صوتي خارج حدوده، ولكن للأسف، يواجه هذا النهج مشكلتَين رئيسيتين:

إنّ عرض عناصر canvas (أو إعادة عرضها) يتطلّب استهلاكًا كبيرًا للطاقة، واستخدام عدة لوحات رسم يتطلّب استهلاكًا أكبر من استخدام لوحة رسم واحدة، حتى إذا كانت هذه اللوحة أكبر. يصبح عرض أيّ عناصر مركّبة تمتدّ على مسارات متعددة (مثل الخطوط العمودية لوضع علامات على الأحداث، مثل وقت FCP) معقّدًا: علينا عرضها على لوحات متعددة والتأكّد من عرضها معًا ومحاذاة كلّها بشكلٍ صحيح.

وبما أنّنا استخدمنا canvas واحدًا للواجهة UI بأكملها، كان علينا معرفة كيفية ضمان عرض كل مسار في الإحداثيات الصحيحة وعدم تداخله مع مسار آخر. على سبيل المثال، إذا كان ارتفاع مقطع صوتي معيّن 100 بكسل، لا يمكننا السماح له بعرض محتوى يبلغ ارتفاعه 120 بكسل وجعله ينسكب على المقطع الصوتي الذي يليه. لحلّ هذه المشكلة، يمكننا استخدام clip. قبل عرض كل مقطع صوتي، نرسم مستطيلاً يمثّل نافذة المقطع الصوتي المرئية. يضمن ذلك أنّ أي مسارات يتم رسمها خارج هذه الحدود سيتم اقتطاعها بواسطة اللوحة.

canvasContext.beginPath();
canvasContext.rect(
    trackVisibleWindow.x, trackVisibleWindow.y, trackVisibleWindow.width, trackVisibleWindow.height);
canvasContext.clip();

لم نردّ أيضًا أن يعرف كل مقطع صوتي موقعه عموديًا: يجب أن يتم عرض كل مقطع صوتي كما لو كان يتم عرضه عند (0، 0)، ولدينا مكوّن أعلى مستوى (نسميه TrackManager) لإدارة موضع المقطع الصوتي العام. ويمكن إجراء ذلك باستخدام translate، الذي ينقل اللوحة بوضع (x, y) معيّن. على سبيل المثال:

canvasContext.translate(0, 10); // Translate by 10px in the y direction
canvasContext.rect(0, 0, 10, 10); // draw a rectangle at (0, 0) that’s 10px high and wide

على الرغم من ضبط الرمز rect على 0, 0 كموضع، سيؤدي تطبيق الترجمة بشكل عام إلى عرض المستطيل على 0, 10. يتيح لنا ذلك العمل على مستوى مسار كما لو كنا بصدد عرض المحتوى في (0, 0)، ونطلب من مدير المسار ترجمة المحتوى أثناء عرض كل مسار لضمان عرض كل مسار بشكل صحيح أسفل المسار السابق.

لوحات عرض خارج الشاشة للمقاطع الصوتية واللقطات المميّزة

إنّ عرض اللوحة مرتفع التكلفة نسبيًا، ونريد التأكّد من أنّ لوحة "الإحصاءات" تظل سلسة الاستجابة أثناء استخدامها. أحيانًا لا يمكنك تجنب الاضطرار إلى إعادة عرض لوحة الرسم بالكامل: على سبيل المثال، إذا قمت بتغيير مستوى التكبير، فيجب علينا البدء مرة أخرى وإعادة عرض كل شيء. إنّ إعادة عرض اللوحة باهظة التكلفة بشكل خاص لأنّه لا يمكنك إعادة عرض جزء صغير منها فقط، بل عليك محو اللوحة بالكامل وإعادة رسمها. يختلف ذلك عن إعادة عرض DOM حيث يمكن للأدوات احتساب الحد الأدنى من العمل المطلوب وعدم إزالة كل شيء والبدء من جديد.

من بين المجالات التي واجهنا فيها مشاكل مرئية هي ميزة التمييز. عند تمرير مؤشر الماوس فوق المقاييس في الجزء، يتم تمييزها على المخطط الزمني، وبالمثل إذا قمت بالتمرير فوق إحصاءات لحدث معين، نرسم حدًا أزرق حول هذا الحدث.

وتمّ تطبيق هذه الميزة في البداية من خلال رصد حركة الماوس فوق عنصر يؤدي إلى تمييز النص، ثم رسمه مباشرةً على اللوحة الرئيسية. تحدث المشكلة عندما نحتاج إلى إزالة التمييز: الخيار الوحيد هو إعادة رسم كل شيء. من المستحيل إعادة رسم المنطقة التي كان فيها التمييز (وذلك بدون تغييرات معمارية كبيرة)، ولكن إعادة رسم اللوحة بأكملها فقط لأنّنا نريد إزالة حدود زرقاء حول عنصر واحد كان يبدو لنا أمرًا مبالغًا فيه. وكان هناك أيضًا تأخّر في الظهور إذا كنت تتحرّك بسرعة بالماوس فوق عناصر مختلفة لعرض عدة عناصر مميّزة بشكل متتابع وسلس.

لحلّ هذه المشكلة، قسمنا واجهة المستخدم إلى لوحتَين خارج الشاشة: اللوحة "الرئيسية" التي يتم عرض الأغاني عليها، ولوحة "أهم التفاصيل" التي يتم فيها رسم أهم التفاصيل. وبعد ذلك، نعرض اللوحة من خلال نسخ هذه اللوحات على اللوحة الواحدة التي تظهر على الشاشة للمستخدم. يمكننا استخدام الطريقة drawImage في سياق لوحة يمكن أن تأخذ لوحة أخرى كمصدر لها.

يعني ذلك أنّ إزالة أحد التمييزات لا تؤدي إلى إعادة رسم اللوحة الرئيسية، بل يمكننا بدلاً من ذلك محو اللوحة المعروضة على الشاشة، ثم نسخ اللوحة الرئيسية إلى اللوحة المرئية. إنّ عملية نسخ لوحة فنية غير مكلفة، ولكنّ الرسم هو ما يتطلّب تكلفة عالية. لذلك، من خلال نقل الإضاءات إلى لوحة فنية منفصلة، نتجنب هذه التكلفة عند تفعيل الإضاءات وإيقافها.

تحليل التتبّع الذي تم اختباره بشكل شامل

من بين مزايا إنشاء ميزة جديدة من الصفر أنّه يمكنك التفكير في الخيارات الفنية التي تمّ اتخاذها سابقًا وإجراء تحسينات عليها. كان من بين الأمور التي أردنا تحسينها تقسيم الرمز البرمجي صراحةً إلى جزأين مختلفَين تمامًا تقريبًا:

تحليل ملف التتبُّع واستخراج البيانات المطلوبة اعرض مجموعة من المقاطع الصوتية.

من خلال فصل عملية التحليل (الجزء 1) عن عمل واجهة المستخدم (الجزء 2)، تمكّنا من إنشاء نظام تحليل متين. ويتم تنفيذ كل عملية تتبُّع من خلال سلسلة من المعالجات المسؤولة عن مشاكل مختلفة: يحسب LayoutShiftHandler كل المعلومات التي نحتاجها لعمليات Layout Shifts، ويعالج NetworkRequestsHandler بشكلٍ حصري عمليات سحب طلبات الشبكة. كان من المفيد أيضًا إجراء خطوة التحليل الصريح هذه التي تتضمّن عناصر تحكّم مختلفة مسؤولة عن أجزاء مختلفة من التتبّع: يمكن أن يصبح تحليل التتبّع معقّدًا جدًا، ويساعد ذلك في التركيز على مشكلة واحدة في كل مرة.

وتمكّنا أيضًا من اختبار تحليل التتبّع بشكل شامل من خلال تسجيلات في "أدوات مطوّري البرامج" وحفظها ثم تحميلها كجزء من مجموعة الاختبار. وهذا أمر رائع لأنّه يمكننا إجراء الاختبار باستخدام عمليات تتبُّع حقيقية، وعدم إنشاء كميات هائلة من بيانات التتبُّع المزيّفة التي قد تصبح قديمة.

اختبار لقطة شاشة لواجهة مستخدم لوحة الرسم

في ما يخصّ موضوع الاختبار، نختبر عادةً مكوّنات الواجهة الأمامية من خلال عرضها في المتصفّح والتأكّد من أنّها تعمل على النحو المتوقّع. ويمكننا إرسال أحداث النقر لتشغيل التعديلات والتأكّد من أنّ نموذج DOM الذي تنشئه المكوّنات صحيح. يعمل هذا النهج بشكل جيد بالنسبة لنا ولكنه يفشل عند التفكير في العرض على لوحة رسم. لا توجد طريقة لفحص لوحة الرسم وتحديد ما يتم رسمه هناك! وبالتالي، فإنّ أسلوبنا المعتاد المتمثل في التقديم ثم الاستعلام غير مناسب.

لكي نتمكّن من إجراء بعض الاختبارات، لجأنا إلى اختبار لقطات الشاشة. يبدأ كل اختبار في تشغيل لوحة، ويعرض المسار الذي نريد اختباره، ثم يأخذ لقطة شاشة لعنصر لوحة الرسم. ويتم بعد ذلك تخزين لقطة الشاشة هذه في قاعدة بياناتنا، وستقارن عمليات الاختبار المستقبلية لقطة الشاشة المخزّنة بلقطة الشاشة التي يتم إنشاؤها. إذا كانت لقطات الشاشة مختلفة، سيفشل الاختبار. ونوفّر أيضًا علامة لإجراء الاختبار وفرض تعديل لقطة الشاشة بعد إجراء تغيير متعمّد على العرض ونحتاج إلى تعديل الاختبار.

إنّ اختبارات لقطات الشاشة ليست مثالية وليست دقيقة جدًا، إذ يمكنك فقط اختبار عرض المكوّن بالكامل على النحو المتوقّع، بدلاً من إجراء تأكيدات أكثر تحديدًا. في البداية، كنا نستخدم هذه الاختبارات بشكل مفرط لضمان عرض كل مكوّن (HTML أو لوحة) بشكل صحيح. أدّى ذلك إلى إبطاء مجموعة الاختبار بشكل كبير، وأدى إلى حدوث مشاكل أدّت إلى تعذّر التقاط لقطات شاشة متعددة وتطلبت تعديلها، وذلك بسبب تعديلات صغيرة وغير ذات صلة تقريبًا على واجهة المستخدم (مثل تغييرات الألوان البسيطة أو إضافة بعض الهوامش بين العناصر). لقد خفّضنا الآن من استخدامنا لقطات الشاشة، ونستخدمها فقط للمكوّنات المستندة إلى مساحة العرض، وقد أدى هذا التوازن إلى تحقيق نتائج جيدة حتى الآن.

الخاتمة

لقد كانت تجربة إنشاء لوحة "إحصاءات الأداء" الجديدة ممتعة للغاية وغنية بالمعلومات. لقد تعلمنا الكثير عن ملفات التتبّع والعمل باستخدام لوحة الرسم وغير ذلك الكثير. نأمل أن تستمتع باستخدام اللوحة الجديدة، ونتطلّع إلى معرفة ملاحظاتك.

لمزيد من المعلومات عن لوحة "إحصاءات الأداء"، اطّلِع على المقالة إحصاءات الأداء: الحصول على إحصاءات قابلة للاستخدام عن أداء موقعك الإلكتروني.

تنزيل قنوات المعاينة

يمكنك استخدام Chrome كناري، أو إصدار مطوّري البرامج، أو الإصدار التجريبي، كمتصفِّح التطوير التلقائي. تتيح لك قنوات المعاينة هذه الوصول إلى أحدث ميزات DevTools، وتتيح لك اختبار واجهات برمجة تطبيقات منصات الويب المتطوّرة، وتساعدك في العثور على المشاكل في موقعك الإلكتروني قبل أن يعثر عليها المستخدمون.

التواصل مع فريق "أدوات مطوّري البرامج في Chrome"

استخدِم الخيارات التالية لمناقشة الميزات الجديدة أو التحديثات أو أي شيء آخر مرتبط بـ "أدوات مطوّري البرامج".