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

قد يشكّل ذلك مشكلة، لأنّ نوع الاتصال الفعلي بالشبكة الذي يستخدمه المستخدم قد لا يكون في الواقع شبكة الجيل الثالث أو شبكة الجيل الرابع أو شبكة Wi-Fi. يمكنك الاتصال بشبكة Wi-Fi في مقهى ولكنك متصل بنقطة اتصال خلوية بسرعات 2G.
يمكنك تقليل تكلفة نقل JavaScript عبر الشبكة من خلال:
- إرسال الرمز الذي يحتاجه المستخدم فقط:
- استخدِم تقسيم الرموز لتقسيم JavaScript إلى ما هو مهم وما هو غير مهم. تتيح حِزم الوحدات، مثل webpack، تقسيم الرموز البرمجية.
- التحميل الكسول في الرموز غير المهمة.
- إزالة البيانات غير الضرورية
- استخدِم UglifyJS لإزالة البيانات غير الضرورية من رمز ES5.
- استخدِم babel-minify أو uglify-es لتصغير ES2015+.
- الضغط
- إزالة الرموز غير المستخدَمة
- حدِّد الفرص المتاحة للرموز البرمجية التي يمكن إزالتها أو تحميلها بالتحميل الكسول باستخدام نسبة استخدام رموز الصفحة في أدوات مطوّري البرامج.
- استخدِم babel-preset-env وbrowserlist لتجنُّب ترجمة الميزات المتوفّرة في المتصفّحات الحديثة من مصدر إلى مصدر. قد يجد المطوّرون المتقدّمون أنّ التحليل الدقيق لحِزم webpack يساعد في تحديد الفرص المتاحة لتقليل التبعيات غير الضرورية.
- لإزالة الرموز البرمجية، يمكنك الاطّلاع على تقنية tree-shaking وClosure Compiler والتحسينات المتقدّمة والمكوّنات الإضافية لاقتطاع المكتبات مثل lodash-babel-plugin أو ContextReplacementPlugin من webpack للمكتبات مثل Moment.js.
- تخزين الرمز مؤقتًا لتقليل رحلات الشبكة
- استخدِم التخزين المؤقت لبروتوكول HTTP لضمان تخزين المتصفّحات للردود مؤقتًا بشكل فعّال. حدِّد العمر الأمثل للنصوص البرمجية (max-age) وقدِّم الرموز المميزة للتحقق (ETag) لتجنُّب نقل وحدات البايت التي لم يتم تغييرها.
- يمكن أن يؤدي التخزين المؤقت لمشغّل الخدمات إلى جعل شبكة تطبيقك مرنة ومنحك إمكانية الوصول السريع إلى ميزات مثل ذاكرة التخزين المؤقت للرموز البرمجية في V8.
- استخدِم التخزين المؤقت الطويل الأجل لتجنُّب إعادة جلب الموارد التي لم تتغيّر. في حال استخدام Webpack، يُرجى الاطّلاع على تجزئة اسم الملف.
التحليل/التجميع
بعد تنزيل JavaScript، تكون إحدى أكبر التكاليف هي الوقت الذي يستغرقه محرّك JS في تحليل/تجميع هذا الرمز. في أدوات مطوّري البرامج في Chrome، يشكّل التحليل اللغوي والتجميع جزءًا من وقت "البرمجة" الأصفر في لوحة "الأداء".

تعرض علامتا التبويب "من الأسفل إلى الأعلى" (Bottom-Up) و"شجرة الاستدعاء" (Call Tree) أوقات التحليل/التجميع الدقيقة:
ولكن، ما أهمية ذلك؟

إنّ قضاء وقت طويل في تحليل الرموز البرمجية أو تجميعها يمكن أن يؤدي إلى تأخير كبير في تفاعل المستخدم مع موقعك الإلكتروني. كلما زاد حجم JavaScript الذي ترسله، زاد الوقت الذي يستغرقه تحليلها وتجميعها قبل أن يصبح موقعك الإلكتروني تفاعليًا.
"بايت ببايت، تُعدّ معالجة JavaScript أكثر تكلفة للمتصفّح من معالجة صورة أو خط ويب بالحجم نفسه" - توم ديل
مقارنةً بلغة JavaScript، هناك العديد من التكاليف المرتبطة بمعالجة الصور ذات الحجم المماثل (لا يزال يتعين فك ترميزها!) ولكن في المتوسط على الأجهزة الجوّالة، من المرجح أن تؤثر لغة JS سلبًا في تفاعلية الصفحة.
عندما نتحدث عن بطء التحليل والتجميع، يكون السياق مهمًا، فنحن نتحدث هنا عن الهواتف الجوّالة المتوسطة. قد يمتلك المستخدمون العاديون هواتف ذات وحدات معالجة مركزية ووحدات معالجة رسومات بطيئة، ولا تحتوي على ذاكرة تخزين مؤقت L2/L3، وقد تكون مقيدة بالذاكرة.
لا تتطابق إمكانات الشبكة وإمكانات الجهاز دائمًا. فالمستخدم الذي لديه اتصال رائع عبر الألياف الضوئية لا يملك بالضرورة أفضل وحدة معالجة مركزية لتحليل وتقييم JavaScript المرسلة إلى جهازه. وينطبق هذا أيضًا على العكس… اتصال شبكة سيئ، ولكن وحدة معالجة مركزية فائقة السرعة. — "كريستوفر باكستر"، LinkedIn
في ما يلي، يمكننا الاطّلاع على تكلفة تحليل ملف JavaScript (بسيط) غير مضغوط بحجم 1 ميغابايت تقريبًا على أجهزة منخفضة وعالية المواصفات. هناك فرق يتراوح بين الضعفين و5 أضعاف في الوقت المستغرَق لتحليل/تجميع الرموز البرمجية بين أسرع الهواتف في السوق والهواتف العادية.
ماذا عن موقع إلكتروني حقيقي، مثل CNN.com؟
على هاتف iPhone 8 المتطوّر، يستغرق تحليل/تجميع ملفات JS في CNN حوالي 4 ثوانٍ مقارنةً بحوالي 13 ثانية على هاتف متوسط (Moto G4). يمكن أن يؤثر ذلك بشكل كبير على مدى سرعة تفاعل المستخدم بشكل كامل مع هذا الموقع.
يبرز ذلك أهمية الاختبار على أجهزة متوسطة الإمكانيات (مثل Moto G4) بدلاً من الهاتف الذي قد يكون في جيبك. ومع ذلك، السياق مهم: يجب تحسين المحتوى ليناسب الجهاز وظروف الشبكة لدى المستخدمين.
هل نرسل الكثير من JavaScript؟ ربما :)
باستخدام HTTP Archive (أهم المواقع الإلكترونية التي يبلغ عددها 500 ألف تقريبًا) لتحليل حالة JavaScript على الأجهزة الجوّالة، يمكننا أن نرى أنّ %50 من المواقع الإلكترونية تستغرق أكثر من 14 ثانية لتصبح تفاعلية. تستغرق هذه المواقع ما يصل إلى 4 ثوانٍ في تحليل لغة JavaScript وتجميعها.

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

إذا استغرق تنفيذ النص البرمجي أكثر من 50 ملي ثانية، يتأخر وقت التفاعل بمقدار الوقت الكامل الذي يستغرقه تنزيل ملف JS وتجميعه وتنفيذه. - أليكس راسل
لمعالجة هذه المشكلة، من الأفضل تقسيم JavaScript إلى أجزاء صغيرة لتجنُّب قفل سلسلة التعليمات الرئيسية. استكشِف ما إذا كان بإمكانك تقليل مقدار العمل الذي يتم إنجازه أثناء التنفيذ.
التكاليف الأخرى
يمكن أن تؤثر لغة JavaScript في أداء الصفحة بطرق أخرى:
- الذاكرة: قد تظهر الصفحات بشكل متقطّع أو تتوقف مؤقتًا بشكل متكرر بسبب GC (جمع المهملات). عندما يستعيد المتصفّح الذاكرة، يتم إيقاف تنفيذ JS مؤقتًا، لذا فإنّ المتصفّح الذي يجمع البيانات غير الصالحة بشكل متكرر يمكن أن يوقف التنفيذ مؤقتًا بمعدل أكبر مما نرغب فيه. تجنَّب تسرُّب الذاكرة والتوقُّفات المتكرّرة لجمع المهملات للحفاظ على الصفحات خالية من التقطُّع.
- أثناء وقت التشغيل، يمكن أن يحظر رمز JavaScript الطويل سلسلة التعليمات الرئيسية، ما يؤدي إلى عدم استجابة الصفحات. يمكن أن يؤدي تقسيم العمل إلى أجزاء أصغر (باستخدام
requestAnimationFrame()أوrequestIdleCallback()للجدولة) إلى تقليل مشاكل الاستجابة، ما يساعد في تحسين مدى استجابة الصفحة لتفاعلات المستخدم (INP).
أنماط لخفض تكلفة عرض JavaScript
عند محاولة تقليل أوقات التحليل/الترجمة ونقل الشبكة لـ JavaScript، هناك أنماط يمكن أن تساعدك، مثل التقسيم المستند إلى المسار أو PRPL.
PRPL
PRPL (الدفع والعرض والتخزين المؤقت المسبق والتحميل الكسول) هو نمط يحسّن التفاعل من خلال تقسيم الرموز البرمجية والتخزين المؤقت بشكل مكثّف:

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

يستخدم موقع Wego نمط PRPL، ويحافظ على وقت تحليل منخفض لمساراته، ما يتيح له التفاعل بسرعة كبيرة. وقد اعتمدت العديد من المواقع الإلكترونية الأخرى المذكورة أعلاه ميزانيات قائمة على الأداء وتقسيم الرموز البرمجية لمحاولة خفض تكاليف JS.
التمهيد التدريجي
تعمل العديد من المواقع الإلكترونية على تحسين مستوى ظهور المحتوى على حساب التفاعلية. للحصول على عرض أولي سريع عند استخدام حِزم JavaScript كبيرة، يستخدم المطوّرون أحيانًا العرض من جهة الخادم، ثم "يرقّونه" لإرفاق معالِجات الأحداث عند جلب JavaScript في النهاية.
يُرجى توخي الحذر، لأنّ هذا الإجراء له تكاليفه الخاصة. أولاً، يتم إرسال استجابة HTML أكبر بشكل عام، ما قد يؤدي إلى تأخير التفاعل، وثانيًا، قد يواجه المستخدم تجربة غير مألوفة حيث لا يمكنه التفاعل مع نصف المحتوى حتى ينتهي JavaScript من المعالجة.
قد يكون "التشغيل التدريجي" (Progressive Bootstrapping) نهجًا أفضل. أرسِل صفحة تتضمّن الحد الأدنى من الوظائف (تتكوّن فقط من HTML/JS/CSS اللازمة للمسار الحالي). ومع وصول المزيد من الموارد، يمكن للتطبيق تحميل المزيد من الميزات وإتاحتها.
إنّ تحميل الرموز البرمجية بما يتناسب مع المحتوى المعروض هو الحل الأمثل. ويُعدّ PRPL و"التشغيل التدريجي" من الأنماط التي يمكن أن تساعد في تحقيق ذلك.
الاستنتاجات
حجم الإرسال مهم جدًا للشبكات المنخفضة الجودة. يُعدّ وقت التحليل مهمًا للأجهزة المرتبطة بوحدة المعالجة المركزية. لذا، من المهم الحفاظ على انخفاض هذه المعدلات.
حقّقت الفِرق نجاحًا من خلال اعتماد ميزانيات صارمة قائمة على الأداء للحفاظ على انخفاض أوقات نقل JavaScript وتحليلها/تجميعها. يمكنك الاطّلاع على مقالة "هل يمكنك تحمّل التكلفة؟: Real-world Web Performance Budgets" للحصول على إرشادات حول الميزانيات للأجهزة الجوّالة.
إذا كنت بصدد إنشاء موقع إلكتروني يستهدف الأجهزة الجوّالة، ابذل قصارى جهدك لتطويره على أجهزة تمثيلية، وحافظ على انخفاض أوقات تحليل/تجميع JavaScript، واعتمد ميزانية قائمة على الأداء لضمان قدرة فريقك على مراقبة تكاليف JavaScript.
مزيد من المعلومات
- مؤتمر Chrome Dev Summit لعام 2017: أفضل الممارسات الحديثة لتحميل المحتوى
- أداء بدء تشغيل JavaScript
- حلّ أزمة أداء الويب - نولان لوسون
- هل يمكنك تحمّل تكلفة ذلك؟ ميزانيات الأداء في العالم الحقيقي — أليكس راسل
- تقييم أُطر عمل الويب والمكتبات — "كريستوفر باكستر"
- نتائج تجربة Cloudflare مع Brotli للضغط (يُرجى ملاحظة أنّ Brotli الديناميكي بجودة أعلى يمكن أن يؤخر عرض الصفحة الأولي، لذا يجب تقييمه بعناية. لذلك، من الأفضل استخدام الضغط الثابت بدلاً من ذلك.)
- Performance Futures — سام ساكون