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

لا أحد يحب الانتظار. يغادر أكثر من% 50 من المستخدِمين موقع إلكتروني إذا استغرق تحميله أكثر من 3 ثوانٍ.

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

لماذا يُعد تقسيم الرمز مفيدًا؟

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

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

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

القياس

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

تدقيق فاشل في Lighthouse يُظهر نصوصًا برمجية يستغرق تنفيذها وقتًا طويلاً جدًا.

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

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

import moduleA from "library";

form.addEventListener("submit", e => {
  e.preventDefault();
  someFunction();
});

const someFunction = () => {
  // uses moduleA
}

هنا، يستخدم someFunction وحدة تم استيرادها من مكتبة معيّنة. في حال حذف لم يتم استخدام هذه الوحدة في أي مكان آخر، فيمكن تعديل كتلة الرموز لاستخدام الاستيراد الديناميكي لجلبه فقط عندما يرسل المستخدم النموذج.

form.addEventListener("submit", e => {
  e.preventDefault();
  import('library.moduleA')
    .then(module => module.default) // using the default export
    .then(() => someFunction())
    .catch(handleError());
});

const someFunction = () => {
    // uses moduleA
}

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

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

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