درس تطبيقي حول الترميز: تحميل مواد العرض المهمة مسبقًا لتحسين سرعة التحميل

في هذا الدليل التعليمي حول رموز البرامج، تم تحسين أداء صفحة الويب التالية من خلال تحميل بعض الموارد مسبقًا وجلبها مسبقًا:

لقطة شاشة التطبيق

القياس

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

  • لمعاينة الموقع الإلكتروني، اضغط على عرض التطبيق. ثم اضغط على ملء الشاشة ملء الشاشة.

يمكنك إجراء تدقيق أداء Lighthouse (Lighthouse > الخيارات > الأداء) على الإصدار المباشر من Glitch (راجِع أيضًا اكتشاف فرص التحسين في الأداء باستخدام Lighthouse).

يعرض Lighthouse عملية التدقيق التالية التي تعذّر إكمالها لمورد تم استرجاعه متأخّرًا:

Lighthouse: تدقيق التحميل المُسبَق لطلبات المفاتيح
  • اضغط على Ctrl ‏+ Shift ‏+ J (أو Command ‏+ Option ‏+ J على نظام التشغيل Mac) لفتح DevTools.
  • انقر على علامة التبويب الشبكة.
لوحة الشبكة التي تتضمّن موردًا تم اكتشافه لاحقًا

لا يتم جلب ملف main.css بواسطة عنصر رابط (<link>) تم وضعه في مستند HTML، ولكن ملف JavaScript منفصل، وهو fetch-css.js، يُرفِق عنصر الرابط بـ DOM بعد حدث window.onLoad. وهذا يعني أنّه لا يتم جلب ملف JS سوى بعد انتهاء المتصفّح من تحليل ملف JS وتنفيذه. وبالمثل، لا تتم عملية جلب خط الويب (K2D.woff2) المحدّد ضمن main.css إلا بعد انتهاء تنزيل ملف CSS.

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

├─┬ / (initial HTML file)
  └── fetch-css.js
    └── main.css
      └── K2D.woff2

بما أنّ ملف CSS يقع في المستوى الثالث من سلسلة الطلبات، رصده Lighthouse كمورد تم اكتشافه في وقت متأخر.

تحميل الموارد المهمة مسبقًا

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

أضِف علامة التحميل المُسبَق لهذا التطبيق:

<head>
  <!-- ... -->
  <link rel="preload" href="main.css" as="style">
</head>

تُستخدَم سمة as لتحديد نوع المرجع الذي يتم retrievingه، وتُستخدَم سمة as="style" لتحميل ملفات أوراق الأنماط مسبقًا.

أعِد تحميل التطبيق واطّلِع على لوحة الشبكة في أدوات مطوّري البرامج.

لوحة الشبكة التي تتضمّن موردًا محمَّلاً مسبقًا

لاحظ كيف يُجلب المتصفّح ملف CSS قبل أن ينتهي تحليل JavaScript المُستخدَم لجلبه. من خلال التحميل المُسبَق، يعرف المتصفّح أنّه يجب إجراء عملية جلب وقائية للمورد بافتراض أنّه مهم لصفحة الويب.

في حال عدم استخدامه بشكل صحيح، يمكن أن يضرّ التحميل المُسبَق بالأداء من خلال إرسال طلبات غير ضرورية للموارد التي لا يتم استخدامها. في هذا التطبيق، details.css هو ملف CSS آخر يقع في جذر المشروع، ولكن يتم استخدامه لملف /details route منفصل. لعرض مثال على كيفية استخدام التحميل المُسبَق بشكلٍ غير صحيح، أضِف تلميحًا للتحميل المُسبَق لهذا المورد أيضًا.

<head>
  <!-- ... -->
  <link rel="preload" href="main.css" as="style">
  <link rel="preload" href="details.css" as="style">
</head>

أعِد تحميل التطبيق واطّلِع على لوحة الشبكة. يتم تقديم طلب لاسترداد details.css على الرغم من أنّه لا يتم استخدامه من خلال صفحة الويب.

لوحة الشبكة التي تتضمّن تحميلًا مسبقًا غير ضروري

يعرض Chrome تحذيرًا في لوحة وحدة التحكّم عندما لا تستخدم الصفحة أحد الموارد المحمَّلة مسبقًا في غضون بضع ثوانٍ من تحميله.

تحذير بشأن التحميل المُسبَق في وحدة التحكّم

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

<head>
  <!-- ... -->
  <link rel="preload" href="main.css" as="style">
  <link rel="preload" href="details.css" as="style">
</head>

للحصول على قائمة بجميع أنواع الموارد التي يمكن جلبها مع القيم الصحيحة التي يجب استخدامها لسمة as، يُرجى الرجوع إلى مقالة MDN حول التحميل المُسبَق.

جلب الموارد المستقبلية مسبقًا

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

في هذا الموقع الإلكتروني، ينقلك النقر على الصورة إلى details/ مسار منفصل.

تفاصيل المسار

يحتوي ملف CSS منفصل، وهو details.css، على جميع الأنماط المطلوبة لهذه الصفحة البسيطة. أضِف عنصر رابط إلى index.html لتحميل هذا المورد مسبقًا.

<head>
  <!-- ... -->
  <link rel="prefetch" href="details.css">
</head>

لفهم كيفية بدء طلب الملف، افتح لوحة الشبكة في "أدوات المطوّر"، وألغِ الاختيار من خيار إيقاف ذاكرة التخزين المؤقت.

إيقاف ذاكرة التخزين المؤقت في &quot;أدوات مطوّري البرامج في Chrome&quot;

أعِد تحميل التطبيق ولاحظ كيف يتم تقديم طلب بأولوية منخفضة جدًا لملف details.css بعد جلب جميع الملفات الأخرى.

لوحة الشبكة التي تتضمّن موردًا تم جلبه مسبقًا

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

طلبات الشبكة في صفحة التفاصيل

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

تم جلب طلب التفاصيل من ذاكرة التخزين المؤقت على القرص

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

التحميل المُسبَق والتحميل المُسبَق باستخدام webpack

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

تطبيق Magic Sorter الذي يعرض عملية تقسيم الرموز البرمجية

يمكنك الوصول إلى الخطأ في هذا التطبيق هنا.

مجموعة الرموز البرمجية التالية، التي تقع في src/index.js,، مسؤولة عن استيراد الطريقة ديناميكيًا عند النقر على الزر.

form.addEventListener("submit", e => {
  e.preventDefault()
  import('lodash.sortby')
    .then(module => module.default)
    .then(sortInput())
    .catch(err => { alert(err) });
});

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

استخدِم مَعلمة التعليق webpackPrefetch المحدّدة ضمن عملية استيراد ديناميكية لتحميل جزء معيّن مسبقًا. في ما يلي الشكل الذي سيظهر به هذا التطبيق تحديدًا.

form.addEventListener("submit", e => {
  e.preventDefault()
  import(/* webpackPrefetch: true */ 'lodash.sortby')
    .then(module => module.default)
    .then(sortInput())
    .catch(err => { alert(err) });
});

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

لوحة &quot;العناصر&quot; التي تتضمّن علامة prefetch

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

لوحة الشبكة التي تتضمّن طلبًا تم جلبه مسبقًا

على الرغم من أنّ ميزة "التحميل المُسبَق" أكثر منطقية لحالة الاستخدام هذه، يقدّم Webpack أيضًا إمكانية التحميل المُسبَق للشرائح التي يتم استيرادها ديناميكيًا.

import(/* webpackPreload: true */ 'module')

الخاتمة

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

باختصار:

  • استخدِم ميزة التحميل المُسبَق للموارد التي يتم اكتشافها في وقت متأخر ولكنها مهمة للصفحة الحالية.
  • استخدِم ميزة الجلب المُسبَق للموارد المطلوبة لمسار تنقّل مستقبلي أو إجراء مستقبلي للمستخدِم.

لا تتيح بعض المتصفّحات حاليًا ميزةَي "التحميل المُسبَق" و"التحميل المُسبَق للمحتوى التالي". وهذا يعني أنّه قد لا يلاحظ بعض مستخدمي تطبيقك تحسينات الأداء.

إذا أردت الحصول على مزيد من المعلومات حول جوانب معيّنة لكيفية تأثير التحميل المُسبَق وتحميل البيانات مسبقًا في صفحة الويب، يمكنك الرجوع إلى المقالتَين التاليتَين: