تبسيط أداء الويب - نسخة مؤتمر Google I/O لعام 2018

في مؤتمر Google IO لعام 2018، قدّمنا مجموعة من الأدوات والمكتبات وأساليب التحسين التي تسهّل تحسين أداء الويب. نوضّح هنا هذه التقنيات باستخدام تطبيق Oodles Theater، كما نتناول تجاربنا في التحميل التوقّعي ومبادرة Guess.js الجديدة.

Ewa Gasperowicz

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

الحاجة إلى الأداء

يزداد حجم الإنترنت عامًا بعد عام. إذا ألقينا نظرة على حالة الويب، يمكننا أن نرى أنّ متوسط حجم الصفحة على الأجهزة الجوّالة يبلغ حوالي 1.5 ميغابايت، ومعظم هذا الحجم هو JavaScript وصور.

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

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

هرم التسلسل الهرمي لتجربة المستخدم
الشكل 1: ما مدى أهمية السرعة للمستخدمين؟ (Speed Matters, Vol. 3)

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

‫Lighthouse: أساس لسير عمل الأداء

Lighthouse هي جزء من "أدوات مطوّري البرامج في Chrome" تتيح لك إجراء تدقيق لموقعك الإلكتروني وتقدّم لك تلميحات حول كيفية تحسينه.

أطلقنا مؤخرًا مجموعة من عمليات تدقيق الأداء الجديدة التي تُعدّ مفيدة حقًا في سير عمل التطوير اليومي.

عمليات التدقيق الجديدة في أداة Lighthouse
الشكل 2. عمليات تدقيق جديدة في Lighthouse

لنستكشف كيف يمكنك الاستفادة منها من خلال مثال عملي: تطبيق Oodles Theater، وهو تطبيق ويب تجريبي صغير يمكنك من خلاله تجربة بعض رسومات شعار Google التفاعلية المفضّلة لدينا وحتى لعب لعبة أو لعبتين.

أثناء إنشاء التطبيق، أردنا التأكّد من أنّه يعمل بأفضل أداء ممكن. كانت نقطة البداية للتحسين هي تقرير Lighthouse.

تقرير Lighthouse لتطبيق Oodles
الشكل 3. تقرير Lighthouse لتطبيق Oodles

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

كان حجم الصفحة يبلغ حوالي 3.4 ميغابايت، وكان علينا تقليص حجمها بشكل كبير.

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

فرص تحسين الأداء

إزالة المراجع غير الضرورية

هناك بعض العناصر الواضحة التي يمكن إزالتها بأمان: المسافات البيضاء والتعليقات.

المكاسب من إزالة البيانات غير الضرورية
الشكل 4. تصغير وضغط ملفات JavaScript وCSS

تُبرز أداة Lighthouse هذه الفرصة في تدقيق CSS وJavaScript غير المصغّرين. كنا نستخدم webpack لعملية الإنشاء، لذا للحصول على التصغير، استخدمنا ببساطة المكوّن الإضافي Uglify JS.

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

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

كنا نستخدم استضافة Firebase لاستضافة الرمز البرمجي، وتتيح Firebase ضغط gzipping تلقائيًا، لذا بفضل استضافة الرمز البرمجي على شبكة توصيل محتوى (CDN) معقولة، حصلنا على ذلك مجانًا.

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

استخدام سياسات ذاكرة تخزين مؤقت فعّالة

كانت خطوتنا التالية هي التأكّد من عدم إرسال الموارد مرتين إذا لم يكن ذلك ضروريًا.

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

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

إزالة الرموز غير المستخدَمة

حتى الآن، أزلنا الأجزاء الواضحة من عملية التنزيل غير الضرورية، ولكن ماذا عن الأجزاء الأقل وضوحًا؟ على سبيل المثال، الرموز غير المستخدَمة.

نسبة استخدام رموز الصفحة في "أدوات مطوّري البرامج"
الشكل 5: التحقّق من نسبة استخدام رموز الصفحة

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

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

يمكنك الاطّلاع على إحصاءات نسبة استخدام رموز الصفحة في "أدوات مطوري البرامج في Chrome"، لكل من وقت التشغيل ووقت تحميل تطبيقك. يمكنك رؤية الشريطين الأحمرَين الكبيرَين في لقطة الشاشة السفلية، فقد كان لدينا أكثر من %95 من CSS غير مستخدَم، ومجموعة كبيرة من JavaScript أيضًا.

رصدت أداة Lighthouse أيضًا هذه المشكلة في تدقيق قواعد CSS غير المستخدَمة. وأظهرت توفيرًا محتملاً يزيد عن 400 كيلوبايت. لذلك، عدنا إلى الرمز البرمجي وأزلنا كلاً من JavaScript وCSS من تلك المكتبة.

إذا أزلنا محوّل MVC، ستنخفض الأنماط إلى 10 كيلوبايت
الشكل 6: إذا أسقطنا محوّل MVC، ستنخفض الأنماط إلى 10 كيلوبايت.

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

بالطبع، أدى ذلك إلى ارتفاع نتيجة الأداء، كما تحسّنت سرعة الاستعداد للتفاعل بشكل كبير.

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

لم يتم استخدام الرمز في %95 من الحالات، ولكن لا تزال هناك نسبة %5 في مكان ما. يبدو أن أحد مكوناتنا كان لا يزال يستخدم الأنماط من تلك المكتبة - الأسهم الصغيرة في شريط تمرير رسومات الشعار المبتكرة. نظرًا لأنها كانت صغيرة جدًا، يمكننا فقط الرجوع ودمج هذه الأنماط يدويًا مرة أخرى في الأزرار.

تعطّلت الأزرار بسبب عدم توفّر المكتبة
الشكل 7: كان أحد المكوّنات لا يزال يستخدم المكتبة التي تمت إزالتها

لذا، إذا أزلت رمزًا، تأكَّد من توفّر سير عمل مناسب للاختبار لمساعدتك في الحماية من أي تراجعات مرئية محتملة.

تجنُّب حمولات الشبكة الضخمة

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

تمكّنت أداة Lighthouse من رصد مشكلة في بعض حمولات الشبكة باستخدام تدقيق حمولة الشبكة الهائلة.

رصد حمولات الشبكة الهائلة
الشكل 8: رصد حمولات الشبكة الهائلة

لاحظنا هنا أنّ حجم الرمز البرمجي الذي يتم إرساله يتجاوز 3 ميغابايت، وهو حجم كبير جدًا، لا سيما على الأجهزة الجوّالة.

في أعلى هذه القائمة، سلّطت Lighthouse الضوء على أنّ لدينا حزمة مورّد JavaScript كانت عبارة عن 2 ميغابايت من الرموز غير المضغوطة. وهذه أيضًا مشكلة تم تسليط الضوء عليها من خلال webpack.

كما يقول المثل: أسرع طلب هو الذي لم يتم تقديمه.

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

في حالتنا، لأنّنا نتعامل مع الكثير من حِزم JavaScript، كنّا محظوظين لأنّ منتدى JavaScript لديه مجموعة غنية من أدوات تدقيق حِزم JavaScript.

تدقيق حِزم JavaScript
الشكل 9: تدقيق حِزم JavaScript

بدأنا باستخدام أداة webpack bundle analyzer، والتي أبلغتنا بأننا كنا نضمّن تبعية تسمى unicode والتي كانت 1.6 ميغابايت من JavaScript الذي تم تحليله، وهو قدر كبير.

بعد ذلك، انتقلنا إلى المحرّر واستخدمنا المكوّن الإضافي Import Cost في Visual Studio Code وتمكّنا من عرض تكلفة كل وحدة كنا نستوردها. وقد سمح لنا ذلك باكتشاف المكوّن الذي كان يتضمّن رمزًا يشير إلى هذه الوحدة.

بعد ذلك، انتقلنا إلى أداة أخرى، وهي BundlePhobia. هذه أداة تتيح لك إدخال اسم أي حزمة NPM والاطّلاع على حجمها المقدَّر بعد إزالة البيانات غير الضرورية وضغطها بتنسيق gzip. وجدنا بديلاً جيدًا لوحدة slug التي كنا نستخدمها والتي تزن 2.2 كيلوبايت فقط، لذلك قمنا بتبديل ذلك.

وكان لذلك تأثير كبير في أدائنا. بين هذا التغيير واكتشاف فرص أخرى لتقليص حجم حزمة JavaScript، وفّرنا 2.1 ميغابايت من الرموز البرمجية.

لاحظنا تحسّنًا بنسبة %65 بشكل عام، بعد احتساب حجم هذه الحِزم المضغوطة باستخدام gzip والمصغّرة. ووجدنا أنّ هذه العملية تستحق العناء.

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

تقليل وقت تشغيل JavaScript من خلال تقسيم الرموز البرمجية

على الرغم من أنّ حمولات الشبكة الكبيرة يمكن أن تؤثر بشكل كبير في تطبيقنا، هناك عامل آخر يمكن أن يكون له تأثير كبير جدًا، وهو JavaScript.

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

هذه هي الطريقة التي يعالج بها المتصفّح JavaScript.

معالجة JavaScript
الشكل 10: معالجة JavaScript

علينا أولاً تنزيل هذا النص البرمجي، ولدينا محرّك JavaScript يحتاج بعد ذلك إلى تحليل هذا الرمز البرمجي وتجميعه وتنفيذه.

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

لمساعدتك في اكتشاف هذه المشاكل في تطبيقك، قدّمنا ميزة جديدة في Lighthouse، وهي تدقيق وقت تشغيل JavaScript.

وقت تشغيل JavaScript
الشكل 11 تدقيق وقت تشغيل JavaScript

وفي حالة تطبيق Oodle، أخبرنا أننا قضينا 1.8 ثانية في تشغيل JavaScript. ما كان يحدث هو أننا كنا نستورد بشكل ثابت جميع مساراتنا ومكوناتنا في حزمة JavaScript واحدة متجانسة.

ومن الأساليب التي يمكن استخدامها لتجنّب هذه المشكلة هي تقسيم الرموز البرمجية.

تقسيم الرموز يشبه البيتزا

تقسيم الرموز هو فكرة أنّه بدلاً من تقديم بيتزا كاملة من JavaScript للمستخدمين، ماذا لو قدّمت لهم شريحة واحدة في كل مرة حسب حاجتهم؟

يمكن تطبيق تقسيم الرموز على مستوى المسار أو على مستوى المكوّن. وتعمل هذه الأداة بشكل رائع مع React وReact Loadable وVue.js وAngular وPolymer وPreact والعديد من المكتبات الأخرى.

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

تقسيم الرموز البرمجية باستخدام عمليات الاستيراد الديناميكية
الشكل 13: تقسيم الرموز البرمجية باستخدام عمليات الاستيراد الديناميكية

وكان تأثير ذلك هو تقليص حجم الحِزم، وتقليل وقت تشغيل JavaScript. وأدى ذلك إلى خفض المدة إلى 0.78 ثانية، ما جعل التطبيق أسرع بنسبة %56.

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

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

تحسين الصور

نكتة عن أداء تحميل الصور

في تطبيق Oodle، نستخدم الكثير من الصور. للأسف، كان Lighthouse أقل حماسًا بشأن ذلك مما كنا عليه. في الواقع، فشلنا في جميع عمليات التدقيق الثلاث المتعلقة بالصور.

لقد نسينا تحسين صورنا، ولم نكن نحدد حجمها بشكل صحيح، ويمكننا أيضًا الحصول على بعض الاستفادة من استخدام تنسيقات الصور الأخرى.

عمليات تدقيق الصور
الشكل 14: عمليات تدقيق الصور في Lighthouse

بدأنا بتحسين صورنا.

لإجراء جولة تحسين لمرة واحدة، يمكنك استخدام أدوات مرئية مثل ImageOptim أو XNConvert.

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

بهذه الطريقة، يمكنك التأكّد من تحسين الصور التي تتم إضافتها في المستقبل تلقائيًا. توفّر بعض شبكات توصيل المحتوى (CDN)، مثل Akamai أو الحلول التابعة لجهات خارجية مثل Cloudinary أو Fastly أو Uploadcare، حلولاً شاملة لتحسين الصور، لذا يمكنك أيضًا استضافة صورك على هذه الخدمات.

إذا كنت لا تريد استخدام هذه الخدمات بسبب التكلفة أو مشاكل في وقت الاستجابة، يمكنك استخدام بدائل مستضافة ذاتيًا، مثل Thumbor أو Imageflow.

قبل التحسين وبعده
الشكل 15: قبل التحسين وبعده

تم وضع علامة على صورة PNG الخلفية في webpack على أنّها كبيرة، وهذا صحيح. بعد تغيير حجمها بشكل صحيح لتناسب إطار العرض وتشغيلها من خلال ImageOptim، انخفض حجمها إلى 100 كيلوبايت، وهو حجم مقبول.

وقد أتاح لنا تكرار هذه العملية لصور متعددة على موقعنا الإلكتروني تقليل حجم الصفحة الإجمالي بشكل كبير.

استخدام التنسيق المناسب للمحتوى المتحرّك

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

في تطبيق Oodle، كنا نستخدم ملف GIF كتسلسل تمهيدي على الصفحة الرئيسية. وفقًا لـ Lighthouse، يمكننا توفير أكثر من 7 ميغابايت من خلال التبديل إلى تنسيق فيديو أكثر كفاءة. كان حجم المقطع حوالي 7.3 ميغابايت، وهو حجم كبير جدًا لأي موقع إلكتروني معقول، لذا قمنا بتحويله إلى عنصر فيديو يحتوي على ملفي مصدر - mp4 وWebM لدعم أوسع للمتصفحات.

استبدال صور GIF المتحركة بالفيديو
الشكل 16: استبدال صور GIF المتحركة بفيديو

استخدمنا أداة FFmpeg لتحويل صورة GIF المتحركة إلى ملف mp4. ويوفّر لك تنسيق WebM توفيرًا أكبر في المساحة، ويمكن لواجهة برمجة التطبيقات ImageOptim إجراء هذا التحويل نيابةً عنك.

ffmpeg -i animation.gif -b:v 0 -crf 40 -vf scale=600:-1 video.mp4

تمكّنا من توفير أكثر من %80 من الوزن الإجمالي بفضل عملية التحويل هذه. أدى ذلك إلى خفض حجم الملف إلى حوالي 1 ميغابايت

ومع ذلك، فإنّ 1 ميغابايت هو مورد كبير يتم إرساله عبر السلك، خاصةً للمستخدم الذي لديه نطاق ترددي محدود. لحسن الحظ، يمكننا استخدام Effective Type API لمعرفة أنّهم يستخدمون نطاقًا تردديًا بطيئًا، ومنحهم صورة JPEG أصغر حجمًا بدلاً من ذلك.

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

if (navigator.connection.effectiveType) { ... }

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

استخدام أسلوب "التحميل الكسول" للصور خارج الشاشة

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

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

لا يتوفّر التحميل الكسول بعد في المتصفّح، لذا علينا استخدام JavaScript لإضافة هذه الإمكانية. استخدمنا مكتبة Lazysizes لإضافة سلوك التحميل الكسول إلى أغلفة Oodle.

<!-- Import library -->
import lazysizes from 'lazysizes'  <!-- or -->
<script src="lazysizes.min.js"></script>

<!-- Use it -->

<img data-src="image.jpg" class="lazyload"/>
<img class="lazyload"
    data-sizes="auto"
    data-src="image2.jpg"
    data-srcset="image1.jpg 300w,
    image2.jpg 600w,
    image3.jpg 900w"/>

تتسم Lazysizes بالذكاء لأنّها لا تقتصر على تتبُّع التغييرات في مستوى ظهور العنصر، بل تجلب أيضًا بشكل استباقي العناصر القريبة من العرض لتقديم أفضل تجربة للمستخدم. ويوفّر أيضًا دمجًا اختياريًا لـ IntersectionObserver، ما يمنحك عمليات بحث فعّالة للغاية عن مستوى العرض.

بعد هذا التغيير، يتم جلب صورنا عند الطلب. إذا أردت التعمّق أكثر في هذا الموضوع، يمكنك الاطّلاع على images.guide، وهو مرجع مفيد وشامل للغاية.

مساعدة المتصفّح في تقديم الموارد المهمة في وقت مبكر

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

من المفيد لنا، بصفتنا مؤلفي الصفحة، إبلاغ المتصفّح بما هو مهم بالنسبة إلينا. لحسن الحظ، أضاف مورّدو المتصفّحات خلال العامين الماضيين عددًا من الميزات لمساعدتنا في ذلك، مثل تلميحات الموارد مثل link rel=preconnect أو preload أو prefetch.

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

لِنرَ كيف تساعدنا أداة Lighthouse في استخدام بعض هذه الميزات بفعالية.

أول ما يخبرنا به Lighthouse هو تجنُّب رحلات الذهاب والعودة المتعددة والمكلفة إلى أي مصدر.

تجنُّب الرحلات المتعددة والمكلفة ذهابًا وعودةً إلى أي نقطة انطلاق
الشكل 17: تجنُّب رحلات الذهاب والعودة المتعددة والمكلفة إلى أي نقطة انطلاق

في تطبيق Oodle، نستخدم Google Fonts بشكل كبير. عندما تضع ورقة أنماط Google Font في صفحتك، سيتم ربطها بنطاقين فرعيين. وما تخبرنا به Lighthouse هو أنه إذا تمكنا من تسخين هذا الاتصال، فيمكننا توفير ما يصل إلى 300 مللي ثانية في وقت الاتصال الأولي.

من خلال الاستفادة من السمة rel=preconnect، يمكننا إخفاء وقت استجابة الاتصال بشكل فعّال.

يمكن أن يكون لهذا تأثير كبير، خاصةً مع خدمة مثل Google Fonts حيث تتم استضافة CSS لخطوطنا على googleapis.com، وتتم استضافة موارد الخطوط على Gstatic. لذلك طبقنا هذا التحسين وقمنا بتقليل بضع مئات من المللي ثانية.

الخطوة التالية التي تقترحها أداة Lighthouse هي التحميل المسبق للطلبات الرئيسية.

تحميل الطلبات الرئيسية مسبقًا
الشكل 18: التحميل المسبَق للطلبات الرئيسية

<link rel=preload> هي ميزة فعّالة جدًا، فهي تُعلم المتصفّح بأنّ هناك موردًا مطلوبًا كجزء من عملية التنقّل الحالية، وتحاول جعل المتصفّح يجلبه في أقرب وقت ممكن.

تخبرنا أداة Lighthouse هنا أنّه علينا تحميل موارد خطوط الويب الرئيسية مسبقًا، لأنّنا نحمّل خطَّين للويب.

يبدو التحميل المُسبق لخط ويب على النحو التالي: تحديد rel=preload، ثم تمرير as مع نوع الخط، ثم تحديد نوع الخط الذي تحاول تحميله، مثل woff2.

يمكن أن يكون التأثير الذي يمكن أن يحدثه ذلك على صفحتك صارخًا للغاية.

تأثير التحميل المُسبق للموارد
الشكل 19: تأثير التحميل المُسبق للموارد

في العادة، إذا لم تستخدم السمة rel="preload" في عنصر الرابط، وكانت خطوط الويب مهمة لصفحتك، على المتصفّح أولاً جلب رمز HTML وتحليل رمز CSS، وبعد ذلك بكثير، سيجلب أخيرًا خطوط الويب.

باستخدام السمة rel="preload"، يمكن للمتصفّح بدء جلب خطوط الويب في وقت مبكر جدًا بعد تحليل رمز HTML. في حالة تطبيقنا، تمكن هذا من تقليل ثانية من الوقت الذي استغرقناه لعرض النص باستخدام خطوط الويب الخاصة بنا.

الآن، ليس الأمر بهذه البساطة إذا كنت ستحاول التحميل المُسبق للخطوط باستخدام Google Fonts، هناك مشكلة واحدة.

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

في حالتنا، وجدنا أنّ أداة Google Web Fonts Helper مفيدة جدًا في مساعدتنا على استخدام بعض خطوط الويب هذه بلا إنترنت وإعدادها محليًا، لذا ننصحك بالاطّلاع على هذه الأداة.

سواء كنت تستخدم خطوط الويب كجزء من مواردك المهمة أو كنت تستخدم JavaScript، حاوِل مساعدة المتصفّح في عرض مواردك المهمة في أسرع وقت ممكن.

ميزة تجريبية: تلميحات الأولوية

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

تحديد أولوية المحتوى المرئي في البداية
الشكل 20: تلميحات الأولوية

هذه ميزة جديدة تتيح لك تلميح المتصفح إلى مدى أهمية المورد. إنه يكشف عن سمة جديدة - الأهمية - مع القيم منخفضة أو عالية أو تلقائية.

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

في حالة تطبيق Oodle، أدى ذلك في الواقع إلى مكان عملي واحد يمكننا تحسينه.

تحديد أولوية المحتوى المرئي في البداية
الشكل 21: تحديد الأولوية للمحتوى المرئي في البداية

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

نأمل أن نتيح هذه الميزة في إصدار Canary خلال بضعة أسابيع، لذا يُرجى ترقُّب ذلك.

وضع استراتيجية لتحميل خطوط الويب

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

نحن نبرز ذلك في Lighthouse الآن، من خلال عملية التدقيق تجنُّب النص غير المرئي أثناء تحميل خطوط الويب.

تجنُّب النص غير المرئي أثناء تحميل خطوط الويب
الشكل 22: تجنُّب النص غير المرئي أثناء تحميل خطوط الويب

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

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

    @font-face {
      font-family: 'Montserrat';
      font-style: normal;
      font-display: swap;
      font-weight: 400;
      src: local('Montserrat Regular'), local('Montserrat-Regular'),
          /* Chrome 26+, Opera 23+, Firefox 39+ */
          url('montserrat-v12-latin-regular.woff2') format('woff2'),
            /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
          url('montserrat-v12-latin-regular.woff') format('woff');
    }

تساعدك السمة font-display في تحديد كيفية عرض خطوط الويب أو استخدام خطوط بديلة استنادًا إلى الوقت الذي يستغرقه تبديلها.

في هذه الحالة، نستخدم السمة font-display: swap. يمنح Swap وجه الخط فترة حظر مدتها صفر ثانية، وفترة تبديل لا نهائية. هذا يعني أنّ المتصفّح سيعرض النص على الفور باستخدام خط احتياطي إذا استغرق تحميل الخط بعض الوقت. وسيتم تبديله بمجرد توفّر وجه الخط.

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

نتيجة عرض الخط
الشكل 23. نتيجة عرض الخط

بشكل عام، إذا كنت تستخدم خطوط الويب، كما تفعل نسبة كبيرة من المواقع الإلكترونية، يجب أن يكون لديك استراتيجية جيدة لتحميل خطوط الويب.

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

تقليل النصوص البرمجية التي تحظر العرض

هناك أجزاء أخرى من تطبيقنا يمكننا دفعها في وقت سابق في سلسلة التنزيل لتوفير على الأقل بعض تجربة المستخدم الأساسية في وقت سابق قليلاً.

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

فرصة تقليل أوراق الأنماط التي تحظر العرض
الشكل 24: فرصة تقليل أوراق الأنماط التي تحظر العرض

يؤدي تنزيل أوراق الأنماط الخارجية ومعالجتها إلى منع عملية العرض من إحراز أي تقدم.

يمكننا محاولة تحسين مسار العرض الحرج من خلال تقديم بعض الأنماط في وقت مبكر قليلاً.

إذا استخرجنا الأنماط المسؤولة عن هذا العرض الأولي وضمّناها في HTML، سيتمكّن المتصفّح من عرضها على الفور بدون انتظار وصول أوراق الأنماط الخارجية.

في حالتنا، استخدمنا وحدة NPM تُسمى Critical لتضمين المحتوى المهم في index.html أثناء خطوة الإنشاء.

على الرغم من أنّ هذه الوحدة نفّذت معظم المهام الصعبة، كان من الصعب بعض الشيء تشغيلها بسلاسة على مسارات مختلفة.

إذا لم تكن حذرًا أو إذا كانت بنية موقعك الإلكتروني معقّدة جدًا، قد يكون من الصعب جدًا تقديم هذا النوع من الأنماط إذا لم تكن قد خطّطت لاستخدام بنية هيكل التطبيق من البداية.

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

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

النتيجة

كانت هذه قائمة طويلة من تحسينات الأداء التي طبقناها على موقعنا. لنلقِ نظرة على النتيجة. هذه هي الطريقة التي تم بها تحميل تطبيقنا على جهاز محمول متوسط على شبكة 3G، قبل وبعد التحسين.

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

الأداء القائم على التوقّعات: تجارب مستخدمين مستندة إلى البيانات

نعتقد أنّ تعلُّم الآلة يمثّل فرصة رائعة للمستقبل في العديد من المجالات. من الأفكار التي نأمل أن تفتح المجال أمام المزيد من التجارب في المستقبل هي أنّ البيانات الحقيقية يمكن أن توجّه تجارب المستخدمين التي ننشئها.

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

لدينا في الواقع بيانات متاحة لإبلاغ تحسيناتنا بشكل أفضل اليوم. باستخدام Analytics Reporting API لإحصاءات Google، يمكننا الاطّلاع على الصفحة التالية الأكثر زيارة ونِسب الخروج لأي عنوان URL على موقعنا الإلكتروني، وبالتالي التوصّل إلى استنتاجات حول الموارد التي يجب أن نمنحها الأولوية.

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

تجميع تطبيقات الويب استنادًا إلى البيانات
الشكل 25: تجميع تطبيقات الويب استنادًا إلى البيانات

لتسهيل هذه التجارب، يسرّنا الإعلان عن مبادرة جديدة باسم Guess.js.

Guess.js
الشكل 26: ‫Guess.js

‫Guess.js هو مشروع يركّز على تجارب المستخدمين المستندة إلى البيانات على الويب. نأمل أن يشجّع ذلك على استكشاف استخدام البيانات لتحسين أداء الويب وتجاوز ذلك. كل هذه الميزات مفتوحة المصدر ومتاحة على GitHub اليوم تم إنشاء هذه الأداة بالتعاون مع منتدى البرامج المفتوحة المصدر من قِبل "مينكو غيتشيف" و"كايل ماثيوز" من Gatsby و"كاتي هيمبينيوس" وعدد من الأشخاص الآخرين.

يمكنك الاطّلاع على Guess.js وإعلامنا برأيك.

ملخّص

تساعد النتائج والمقاييس في تحسين سرعة الويب، ولكنّها مجرد وسائل وليست أهدافًا بحد ذاتها.

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

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

مع خالص الشكر لكل من: &quot;وارد بيترز&quot; و&quot;مينكو غيتشيف&quot; و&quot;كايل ماثيوز&quot; و&quot;كيتي هيمبينيوس&quot; و&quot;دوم فارولينو&quot; و&quot;يواف فايس&quot; و&quot;سوزي لو&quot; و&quot;يوسوكي أوتسونوميا&quot; و&quot;توم أنكرز&quot; وLighthouse ورسومات شعار Google المبتكرة.