غالبًا ما تكون لغة JavaScript هي المحفِّز للتغييرات المرئية. في بعض الأحيان يكون ذلك بشكل مباشر من خلال معالجة الأنماط، وأحيانًا تكون عمليات حسابية ستؤدي إلى تغييرات مرئية، مثل البحث عن بعض البيانات أو فرزها. يمكن أن تكون لغة JavaScript التي يتم تشغيلها بشكل سيئ أو لفترة طويلة من الأسباب الشائعة لمشاكل الأداء، ويجب أن تسعى إلى تقليل تأثيرها قدر الإمكان.
إنّ تغيير DOM، من خلال إضافة العناصر وإزالتها أو تغيير السمات أو الفئات أو من خلال الرسوم المتحركة، سيعيد المتصفّح احتساب أنماط العناصر، وفي كثير من الحالات، تنسيق (أو إعادة تدفق) الصفحة أو أجزاء منها. وتُسمى هذه العملية حساب النمط المحسوب.
الجزء الأول من أنماط الحوسبة هو إنشاء مجموعة من محدّدات المطابقة، وهي في الأساس المتصفح الذي يكتشف الفئات والمحددات الزائفة والمعرفات التي تنطبق على أي عنصر معين.
يتضمن الجزء الثاني من العملية أخذ جميع قواعد النمط من محددات المطابقة ومعرفة الأنماط النهائية التي يحتوي عليها العنصر.
ملخّص
- كيف يمكن أن يؤدي تقليل تكاليف احتساب الأنماط إلى تقليل وقت استجابة التفاعل.
- قلِّل من تعقيد أدوات الاختيار، استخدِم منهجية تركّز على الفئة العمرية (BEM، على سبيل المثال).
- تقليل عدد العناصر التي يجب حساب النمط عليها.
وقت إعادة احتساب النمط ووقت استجابة التفاعل
مدى استجابة الصفحة لتفاعلات المستخدم (INP) هو مقياس لأداء وقت التشغيل يركّز على المستخدم ويقيّم مدى استجابة الصفحة بشكل عام لإدخالات المستخدم. عند تقييم وقت استجابة التفاعل باستخدام هذا المقياس، فإنّه يقيس الوقت بدءًا من تفاعل المستخدِم مع الصفحة، وحتى عرض المتصفّح للإطار التالي الذي يعرض التعديلات المرئية المقابلة التي تم إجراؤها على واجهة المستخدِم.
مكون مهم في التفاعل هو الوقت الذي يستغرقه رسم الإطار التالي. يتكون عمل العرض المنجز لعرض الإطار التالي من العديد من الأجزاء، بما في ذلك حساب أنماط الصفحة التي تحدث قبل أعمال التخطيط والطلاء والإنشاء مباشرةً. تركّز هذه المقالة على تكاليف احتساب النمط فقط، إلا أنّه من المهم التأكيد على أنّ تقليل أي جزء من مرحلة العرض المتأصلة في التفاعل سيؤدي إلى تقليل إجمالي وقت الاستجابة، بما في ذلك العمليات الحسابية لأسلوب الاستجابة.
التقليل من تعقيد أدوات الاختيار
في أبسط الحالات، يمكنك الإشارة إلى عنصر في CSS باستخدام فئة فقط:
.title {
/* styles */
}
ومع تطوّر أي مشروع، من المرجّح أن يؤدي إلى إنشاء لغة CSS أكثر تعقيدًا حيث قد ينتهي بك الأمر باستخدام أدوات اختيار تشبه ما يلي:
.box:nth-last-child(-n+1) .title {
/* styles */
}
لمعرفة طريقة تطبيق هذه الأنماط على الصفحة، على المتصفّح أن يسأل: "هل هذا العنصر يحتوي على فئة title
التي تصادف عنصرًا رئيسيًا هو العنصر الفرعي ناقص n وعنصر واحد بفئة box
؟" يمكن أن يستغرق ذلك الكثير من الوقت، بناءً على أداة الاختيار المستخدمة والمتصفّح المعنيّ. ويمكن بدلاً من ذلك تغيير السلوك المقصود لأداة الاختيار إلى فئة:
.final-box-title {
/* styles */
}
قد تكون هناك مشكلة في اسم الفصل الدراسي، ولكن الوظيفة أصبحت أسهل بكثير بالنسبة إلى المتصفح. في الإصدار السابق، لكي نعرف على سبيل المثال أنّ العنصر هو الأخير من نوعه، يجب أن يعرف المتصفّح أولاً كل شيء عن جميع العناصر الأخرى وما إذا كانت أي عناصر تليه تلك العناصر nth-last-child
التي قد تكون أكثر تكلفة من مجرد مطابقة المُحدِّد مع العنصر بسبب تطابق فئته.
تقليل عدد العناصر المراد تصميمها
يُعدّ حجم العمل الهائل الذي يجب تنفيذه عند تغيّر أحد العناصر من الاعتبارات الأخرى المتعلّقة بالأداء، وهي العامل الأكثر أهمية في العديد من تعديلات الأنماط.
وبصفة عامة، فإن أسوأ تكلفة لحالة الأحرف لحساب النمط المحسوب للعناصر هي عدد العناصر مضروبًا في عدد المحدِّد، لأنه يجب التحقق من كل عنصر مرة واحدة على الأقل مقابل كل نمط لمعرفة ما إذا كان مطابقًا أم لا.
يمكن أن تستهدف العمليات الحسابية للأنماط غالبًا بضعة عناصر بشكل مباشر بدلاً من إلغاء الصفحة ككل. وفي المتصفحات الحديثة، لا يمثل ذلك مشكلةً كبيرةً لأن المتصفح لا يحتاج بالضرورة إلى فحص جميع العناصر التي ربما تأثرت بالتغيير. من ناحية أخرى، ليست المتصفحات القديمة بالضرورة محسنة لمثل هذه المهام. وعليك تقليل عدد العناصر التي تم إبطال صلاحيتها، حيثما أمكن.
قياس تكلفة إعادة احتساب النمط
ولقياس تكلفة عمليات إعادة احتساب الأنماط، يمكنك استخدام لوحة الأداء في "أدوات مطوري البرامج في Chrome". للبدء، افتح "أدوات مطوري البرامج" وانتقِل إلى علامة التبويب الأداء وانقر على "تسجيل" وتفاعَل مع الصفحة. عند إيقاف التسجيل، ستظهر لك الصورة أدناه:
الشريط في الجزء العلوي هو مخطط لهب مصغر يرسم أيضًا الإطارات في الثانية. كلما اقترب النشاط من أسفل الشريط، يرسم المتصفح الإطارات الأسرع. إذا رأيت أن مخطط اللهب يتحوّل إلى الأعلى مع وجود خطوط حمراء فوقه، فهذا يعني أن لديك عملاً يتسبب في حدوث إطارات طويلة المدى.
إذا كان لديك إطار طويل المدى أثناء تفاعل مثل التمرير، فإن ذلك يحتاج إلى مزيد من التدقيق. إذا كانت لديك كتلة أرجوانية كبيرة، يمكنك تكبير النشاط واختيار أي عمل يحمل اسم إعادة احتساب النمط للحصول على مزيد من المعلومات حول عمليات إعادة احتساب الأنماط المكلفة المحتملة.
وفي هذه اللقطة، تظهر عمليات إعادة حساب على المدى الطويل تستغرق ما يزيد عن 25 ملي ثانية.
إذا نقرت على الحدث نفسه، سيتم منحك حزمة مكالمات. إذا كانت عملية العرض ناتجة من تفاعل المستخدم، سيتم استدعاء المكان في JavaScript المسؤول عن التسبب في تغيير النمط. بالإضافة إلى ذلك، تحصل أيضًا على عدد العناصر التي تأثرت بالتغيير - أكثر من 900 عنصر فقط في هذه الحالة - والمدة التي استغرقتها لإجراء عملية حساب النمط. يمكنك استخدام هذه المعلومات لبدء محاولة العثور على إصلاح في التعليمات البرمجية.
استخدام سياسة الحظر والعنصر والمعدِّل
إنّ الأساليب المتَّبعة في الترميز مثل BEM (Block, Element, Modifier) تدخل في أداة الاختيار المطابقة لمزايا الأداء المذكورة أعلاه، لأنّها تقترح أن يكون لكل عنصر فئة واحدة، وحيث تحتاج إلى التسلسل الهرمي، يتم دمجه في اسم الفئة أيضًا:
.list {
/* Styles */
}
.list__list-item {
/* Styles */
}
إذا كنت بحاجة إلى بعض أدوات التعديل، مثل ما ورد أعلاه، حيث نريد أن نفعل إجراءً خاصًا لآخر طفل، يمكنك إضافة ذلك على النحو التالي:
.list__list-item--last-child {
/* Styles */
}
إذا كنت تبحث عن طريقة جيدة لتنظيم محتوى CSS، يمكنك اعتبار BEM نقطة انطلاق جيدة، سواء من حيث البنية أو بسبب تبسيط البحث عن النمط الذي تروّج له المنهجية.
أما إذا كنت لا تحب BEM، فهناك طرق أخرى للتعامل مع CSS، ولكن يجب تقييم الاعتبارات المتعلقة بالأداء إلى جانب الجوانب الهندسية لهذا النهج.
المراجِع
صورة رئيسية من UnLaunch، للفنان ماركوس سبيسك.