تحسين أداء الويب - إصدار Google I/O 2018

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

Addy Osmani
Addy Osmani
Ewa Gasperowicz

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

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

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

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

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

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

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

Lighthouse: قاعدة لعملية سير العمل المتعلقة بالأداء

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

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

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

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

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

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

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

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

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

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

إزالة الموارد غير الضرورية

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

المزايا التي تحقّقها إزالة البيانات غير الضرورية
الشكل 4. تصغير وضغط JavaScript وCSS

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

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

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

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

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

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

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

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

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

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

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

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

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

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

يمكنك الاطّلاع على إحصاءات تغطية الرمز في DevTools، سواءً لفترة التشغيل أو وقت تحميل تطبيقك. يمكنك رؤية الشريطَين الأحمرَين الكبيرَين في لقطة الشاشة في أسفل الصفحة. كان لدينا أكثر من %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، التي أبلغتنا بأنّنا نضمّن ملفًا تابعًا يُسمى unicode يبلغ حجمه 1.6 ميغابايت من JavaScript تم تحليله، أي أنّه كبير جدًا.

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

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

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

لقد شهدنا تحسينات بنسبة %65 بشكل عام، بعد احتساب حجم هذه الحِزم المضغوطة والمُكثّفة. وتبيّن لنا أنّ هذه العملية جديرة بالاهتمام.

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

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

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

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

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

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

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

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

لمساعدتك في اكتشاف هذه المشاكل في تطبيقك، أضفنا تدقيقًا جديدًا في وقت بدء تشغيل JavaScript إلى Lighthouse.

وقت بدء تشغيل 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 repo للحصول على بعض الأفكار حول كيفية تقليل حجم مكتبتك إذا كنت تستخدم 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 API إجراء عملية التحويل هذه نيابةً عنك.

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

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

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

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

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

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

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

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

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

لا يتوفّر تحميل المحتوى بشكل تدريجي في المتصفح بعد، لذا علينا استخدام JavaScript لإتاحة هذه الميزة. استخدمنا مكتبة الحجم الكسول لإضافة سلوك التحميل الكسول إلى أغلفة 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". عند إسقاط جدول ملف stylesheet لخط Google Font في صفحتك، سيتم ربط ما يصل إلى نطاقَين فرعيَّين. وتشير أدوات Lighthouse إلى أنّه إذا تمكّنا من تهيئة هذا الاتصال، يمكننا توفير up to 300 milliseconds في وقت الاتصال الأولي.

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

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

تقترح أداة Lighthouse إجراء التحميل المُسبَق لطلبات المفاتيح.

التحميل المُسبَق لطلبات المفاتيح
الشكل 18. التحميل المُسبَق لطلبات المفاتيح

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

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

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

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

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

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

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

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

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

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

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

ميزة تجريبية: نصائح بشأن الأولوية

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

ضبط الأولوية للمحتوى المرئي في البداية
الشكل 20. نصائح حول الأولوية

هذه ميزة جديدة تتيح لك إخبار المتصفّح بمدى أهمية المورد. ويُظهر سمة جديدة - importance (الأهمية) - بالقيم low (منخفض) أو high (مرتفع) أو auto (تلقائي).

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

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

ضبط الأولوية للمحتوى المرئي في البداية
الشكل 21. تحديد الأولوية للمحتوى الذي يظهر في البداية

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

ونأمل إتاحة هذه الميزة في إصدار 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');
    }

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

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

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

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

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

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

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

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

في شريط مخطط الوقت في Lighthouse، يمكنك ملاحظة أنّه خلال هذه الثواني القليلة الأولى التي يتم فيها تحميل كل الموارد، لا يمكن للمستخدم رؤية أي محتوى.

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

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

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

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

في حالتنا، استخدمنا وحدة NPM تُسمى الحرجة لتضمين المحتوى المهم الخاص بنا في index.html أثناء خطوة التصميم.

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

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

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

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

النتيجة

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

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

الأداء التنبؤي - تجارب المستخدمين المستندة إلى البيانات

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

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

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

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

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

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

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

Guess.js هو مشروع يركز على تجارب المستخدم المستندة إلى البيانات على الويب. نأمل أن يؤدي ذلك إلى الاستكشاف واستخدام البيانات لتحسين أداء الويب وغير ذلك. إنها كلها مفتوحة المصدر ومتاحة على GitHub اليوم. تم إنشاء هذه الميزة بالتعاون مع منتدى المحتوى المفتوح من خلال Minko Gechev وKyle Matthews من Gatsby وKatie Hempenius وعدد من الآخرين.

اطلع على Guess.js، وأخبرنا برأيك.

ملخّص

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

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

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

مع جزيل الشكر إلى: "وارد بييتر" و"مينكو غيفتش" و"كايل ماثيوز" و"كاتي هيمبينيوس" و"دوم فارولينو"، و"يوآف ويس" و"سوسي لو" و"يوسوكي أوتسونوميا" و"توم أنكرز" و"مصباح الهداية" و"صور Google المتحركة".