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

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

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

القياس

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

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

يمكنك إجراء تدقيق أداء 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 وتنفيذه. وبالمثل، لا تتم عملية retrieving سوى بعد انتهاء تنزيل ملف CSS لخط الويب (K2D.woff2) المحدّد ضمن main.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 لتحديد نوع المرجع الذي يتم جلبه، وتُستخدَم سمة 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')

الخاتمة

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

في ما يلي ملخّص:

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

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

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