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

Sérgio Gomes

تاريخ النشر: 23 تشرين الثاني (نوفمبر) 2024

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

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

<link rel="preload"> هي طريقة لطلب الموارد بشكل صريح مسبقًا، قبل أن يحتاج إليها المتصفّح.

<head>
  <link rel="preload" as="style" href="critical-styles.css">
  <link rel="preload" as="font" crossorigin type="font/woff2" href="myfont.woff2">
</head>

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

توفّر عملية إعادة التوجيه <link rel="preload"> وما يعادلها من HTTP طريقة بسيطة وواضحة للإعلام بالملفات المهمة التي ستحتاج إليها التصفّح مباشرةً كجزء من التنقّل الحالي. عندما يرصد المتصفّح عملية التحميل المُسبَق، يبدأ تنزيل المورد بأولوية عالية، بحيث يكون قد تم جلبه بالكامل أو جزئيًا بحلول الوقت الذي يكون فيه مطلوبًا. ومع ذلك، لا يعمل هذا الإجراء مع الوحدات.

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

بالنسبة إلى علامتَي <script> و<link>، يمكنك ضبط وضع بيانات الاعتماد باستخدام السمة crossorigin. ومع ذلك، تبيّن أنّ <script type="module"> الذي لا يحتوي على سمة crossorigin يشير إلى وضع بيانات الاعتماد omit، وهو غير متوفّر لـ <link rel="preload">. وهذا يعني أنّه عليك تغيير سمة crossorigin في كلّ من <script> و<link> إلى إحدى القيم الأخرى، وقد لا تتوفّر لك طريقة سهلة لإجراء ذلك إذا كان ما تحاولتحميله مسبقًا يعتمد على وحدات أخرى.

بالإضافة إلى ذلك، لا يشكّل جلب الملف سوى الخطوة الأولى في تشغيل الرمز البرمجي. أولاً، على المتصفّح تحليله وتجميعه. من الأفضل أن يتم تنفيذ ذلك مسبقًا أيضًا، لكي يكون الرمز جاهزًا للتنفيذ عندما تكون الوحدة مطلوبة. ومع ذلك، فإنّ V8 (محرك JavaScript في Chrome) يُحلِّل الوحدات ويُجمِّعها بطريقة مختلفة عن JavaScript الأخرى. لا يقدّم <link rel="preload"> أي طريقة للإشارة إلى أنّ الملف الذي يتم تحميله هو وحدة، لذا كل ما يمكن للمتصفّح فعله هو تحميل الملف ووضعه في ذاكرة التخزين المؤقت. بعد تحميل النص البرمجي باستخدام علامة <script type="module"> (أو تحميله بواسطة وحدة أخرى)، يُحلّل المتصفّح الرمز البرمجي ويُجمِّعه كوحدة JavaScript.

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

<head>
  <link rel="modulepreload" href="super-critical-stuff.mjs">
</head>
[...]
<script type="module" src="super-critical-stuff.mjs">

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

توافق المتصفّح

  • Chrome: 66
  • ‫Edge: الإصدار 79 أو الإصدارات الأقدم
  • Firefox: 115
  • ‫Safari: 17

المصدر

ولكن ماذا عن تبعيات الوحدات؟

يسرّنا أن نجيب عن سؤالك. هناك شيء لم تتناوله هذه المقالة، وهو التكرار.

تسمح مواصفات <link rel="modulepreload"> في الواقع بتحميل الوحدات المطلوبة فقط، ولكن ليس بتحميل شجرة التبعيات بالكامل أيضًا. ولا يُشترط أن تُجري المتصفحات هذا الإجراء، ولكن يمكنها إجراءه.

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

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

<head>
  <!-- dog.js imports dog-head.js, which in turn imports
       dog-head-mouth.js, which imports dog-head-mouth-tongue.js. -->
  <link rel="modulepreload" href="dog-head-mouth-tongue.mjs">
  <link rel="modulepreload" href="dog-head-mouth.mjs">
  <link rel="modulepreload" href="dog-head.mjs">
  <link rel="modulepreload" href="dog.mjs">
</head>

هل يساعد التحميل المُسبَق للوحدات في تحسين الأداء؟

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

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