ماذا تفعل عندما يحظر CSS تحليل الصفحة؟

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





حول loadCSS


أنا من أشد المعجبين بمجموعة Filament Group - لقد أطلقوا كمية لا تصدق من المشاريع الرائعة. بالإضافة إلى ذلك ، يقومون باستمرار بإنشاء أدوات لا تقدر بثمن ومشاركتها من أجل تحسين الويب. واحدة من هذه الأدوات هي loadCSS ، والتي كانت لفترة طويلة الأداة التي أوصيت الجميع باستخدامها لتحميل موارد CSS غير الهامة.

على الرغم من أن هذا قد تغير الآن (ومجموعة خيوط نشرت ممتازة المادة حول ما يفضله موظفيها لاستخدام هذه الأيام)، وما زلت، وعندما تدقيق مواقع، كثيرا ما نرى كيف loadCSSاستخدامه في الإنتاج.

أحد الأنماط التي صادفتها هو النمطpreload/polyfill. باستخدام هذا الأسلوب ، يتم تحميل أي ملفات ذات أنماط في وضع التحميل المسبق (يتم تعيين سمة relالارتباطات المقابلة على preload). بعد ذلك ، عندما يكونون جاهزين للاستخدام ، قم بتطبيق أحداثهم onloadلربطهم بالصفحة.

<link rel="preload" href="path/to/mystylesheet.css" as="style" onload="this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="path/to/mystylesheet.css"></noscript>

نظرًا لعدم دعم جميع المتصفحات للتصميم <a href="https://caniuse.com/#feat=link-rel-preload"><link rel="preload"></a>، فإن المشروع loadCSSيمنح المطورين ملفًا ملائمًا ، يتم إضافته إلى الصفحة بعد وصف الروابط ذات الصلة:

<link rel="preload" href="path/to/mystylesheet.css" as="style" onload="this.rel='stylesheet'">
<noscript>
    <link rel="stylesheet" href="path/to/mystylesheet.css">
</noscript>
<script>
/*! loadCSS rel=preload polyfill. [c]2017 Filament Group, Inc. MIT License */
(function(){ ... }());
</script>

اضطراب في أولويات الشبكة


لم أكن أبدًا من أشد المعجبين بهذا النمط. التحميل المسبق هو أداة وقحة. rel="preload"تحارب المواد التي تم تنزيلها باستخدام روابط السمات بنجاح مع مواد أخرى لموارد الشبكة. preloadيفترض الاستخدام أن أوراق الأنماط التي يتم تحميلها بشكل غير متزامن نظرًا لأنها لا تلعب دورًا مهمًا في إخراج الصفحة تحظى بأولوية عالية جدًا من المتصفحات.

توضح الصورة التالية ، المأخوذة من WebPageTest ، هذه المشكلة بشكل جيد للغاية. في السطور 3-6 ، يمكنك مشاهدة التحميل غير المتزامن لملفات CSS باستخدام نمط preload. ولكن ، في حين أن المطورين يعتبرون أن هذه الملفات ليست مهمة جدًا بحيث يؤدي تنزيلها إلى حظر العرض والاستخدامpreload يعني أنه سيتم تحميلها قبل أن يتلقى المتصفح الموارد المتبقية.


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

قفل محلل HTML


المشاكل المرتبطة بأولوية تحميل الموارد كافية بالفعل لتجنب استخدام النمط في معظم الحالات preload. ولكن في هذه الحالة ، يتفاقم الوضع بسبب وجود ورقة أنماط أخرى ، والتي يتم تحميلها بالطريقة المعتادة.

<link rel="stylesheet" href="path/to/main.css" />
<link rel="preload" href="path/to/mystylesheet.css" as="style" onload="this.rel='stylesheet'">
<noscript>
    <link rel="stylesheet" href="path/to/mystylesheet.css">
</noscript>
<script>
/*! loadCSS rel=preload polyfill. [c]2017 Filament Group, Inc. MIT License */
(function(){ ... }());
</script>

هناك نفس المشاكل عند استخدام preloadالعملاء المحتملين لحقيقة أنه لا تحظى الملفات الأكثر أهمية بأولوية عالية. ولكن لا تقل أهمية تأثير ذلك على قدرة المتصفح على تحليل الصفحة بنفس الأهمية ، وربما أقل وضوحًا.

مرة أخرى، هذا وقد تم بالفعل مكتوبة بالتفصيل ، لذلك أنصح قراءة هذه المادة من أجل فهم أفضل لما يحدث. هنا سأتحدث عن هذا باختصار.

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

من ناحية أخرى ، تمنع البرامج النصية المحلل اللغوي إذا لم يتم وضع علامة عليها كـ deferأو async.

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

ينطبق هذا السلوك على كل من النصوص البرمجية والنصوص البرمجية الخارجية المضمنة في الصفحة. إذا تم تحميل CSS ، فلا تعمل النصوص البرمجية المضمنة حتى تصل CSS إلى المتصفح.

دراسة مشكلة


الطريقة الأكثر مفهومة لتصور هذه المشكلة هي استخدام أدوات مطوري Chrome (أحب حقًا المستوى الذي نمت فيه هذه الأدوات).

من بين أدوات Chrome هناك علامة تبويب Performanceيمكنك من خلالها تسجيل الملف الشخصي لتحميل الصفحة. أوصي بإبطاء اتصال الشبكة بشكل مصطنع بحيث تظهر المشكلة أكثر إشراقًا.

في هذه الحالة ، اختبرت باستخدام إعداد شبكة 3G السريع. إذا نظرت عن كثب إلى ما يحدث لمؤشر الترابط الرئيسي ، يمكنك أن تفهم أن طلب تحميل ملف CSS يحدث في بداية تحليل HTML (حوالي 1.7 ثانية بعد بدء تحميل الصفحة).


يمثل مستطيل صغير أسفل كتلة تحليل HTML طلبًا لملف CSS.

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


إذا نظرت إلى الصورة الكبيرة ، اتضح أنه بعد بدء تحميل CSS ، يكون الخيط الرئيسي خاملاً لأكثر من 1.1 ثانية.

لذا ، مرت 2.8 ثانية ، تم تحميل النمط ، المتصفح يعالجها. عندها فقط نرى معالجة البرنامج النصي المدمج ، وبعد ذلك يعود المتصفح أخيرًا إلى تحليل HTML.


تصل CSS في حوالي 2.8 ثانية ، وبعد ذلك نرى أن المتصفح يواصل تحليل HTML

فايرفوكس استثناء جميل


السلوك أعلاه شائع في Chrome و Edge و Safari. Firefox هو استثناء لطيف لقائمة المتصفحات الشائعة.

تقوم جميع المتصفحات الأخرى بتعليق تحليل HTML ، ولكنها تستخدم محللًا استباقيًا (وسيلة للتحميل المسبق للمواد) لعرض التعليمات البرمجية للروابط إلى الموارد الخارجية ولتنفيذ طلبات تحميل هذه الموارد. ومع ذلك ، فإن Firefox يخطو خطوة أبعد في هذا العمل: فهو يبني شجرة DOM بشكل تخميني ، على الرغم من أنه يتوقع تنفيذ البرنامج النصي.

ما لم يتلاعب البرنامج النصي بـ DOM ، مما يؤدي إلى الحاجة إلى تجاهل نتائج التحليل التخميني ، فإن هذا النهج يسمح لـ Firefox بالاستفادة. بالطبع ، إذا اضطر المتصفح إلى إسقاط شجرة DOM التي تم إنشاؤها بشكل تخميني ، فهذا يعني أنه لم يفعل شيئًا مفيدًا من خلال بناء هذه الشجرة.

هذا هو نهج مثير للاهتمام. كنت أشعر بالفضول الشديد لمعرفة مدى فعاليتها. الآن ، ومع ذلك ، لا توجد معلومات حول هذا في ملف تعريف أداء Firefox. هناك لا يمكنك معرفة ما إذا كان المحلل اللغوي المضارب يعمل ، وما إذا كان من الضروري إعادة العمل الذي قام به ، وإذا كان لا يزال بحاجة إلى إعادة بنائه ، فكيف سيؤثر ذلك على الأداء.

لقد تحدثت مع أولئك المسؤولين عن أدوات مطوري Firefox ، ويمكنني القول إن لديهم أفكارًا مثيرة للاهتمام حول كيفية تقديم هذه المعلومات في ملف التعريف في المستقبل. آمل أن ينجحوا.

حل للمشكلة


في حالة العميل ، الذي ذكرته في البداية ، بدت الخطوة الأولى في حل هذه المشكلة بسيطة للغاية: تخلص من النمط preload/polyfill. التحميل المسبق CSS غير الحرج لا طائل منه. هنا تحتاج إلى التبديل إلى استخدام rel="preload"سمة بدلاً من media="print". هذا بالضبط ما يوصي به الخبراء من مجموعة Filament Group. هذا النهج ، بالإضافة إلى ذلك ، يسمح لك بالتخلص تمامًا من البولي فايل.

<link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'">

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

في هذه الحالة ، لا يزال هناك نص برمجي مضمن آخر موجود في رأس المستند ، أسفل السطر الذي يبدأ طلب تحميل CSS. إذا قمت بنقل هذا النص البرمجي بحيث يكون أمام السطر الذي يقوم بتحميل CSS ، فسيؤدي ذلك إلى إزالة قفل المحلل اللغوي. إذا قمت بتحليل الصفحة مرة أخرى باستخدام أدوات مطوري Chrome ، فسيكون الفرق واضحًا تمامًا.


قبل إجراء تغييرات على رمز الصفحة ، توقف محلل HTML عند السطر 1939 ، بعد أن واجه نصًا برمجيًا مدمجًا ، وبقي هنا لمدة ثانية تقريبًا. بعد التحسين ، تمكن من الوصول إلى السطر 5281

سابقًا ، توقف المحلل اللغوي عند السطر 1939 وانتظر تحميل CSS ، ولكنه الآن يصل إلى السطر 5281. هناك ، في نهاية الصفحة ، هناك نص برمجي مدمج آخر يوقف المحلل اللغوي مرة أخرى.

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

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

ملخص


  • إذا كنت تستخدم loadCSSنمطًا preload/polyfill، فانتقل إلى نمط تحميل النمط print.
  • إذا كانت لديك أنماط خارجية يتم تحميلها بالطريقة المعتادة (أي باستخدام روابط منتظمة لملفات هذه الأنماط) ، فقم بنقل جميع النصوص البرمجية المضمنة التي يمكن نقلها فوق الارتباطات إلى أنماط التحميل.
  • قم بتضمين أنماط حرجة في الصفحة لضمان أسرع بداية ممكنة للعرض.

القراء الأعزاء! هل واجهت مشاكل في إبطاء عرض الصفحة بسبب CSS؟

PS
RUVDS تهنئ جميع محترفي تكنولوجيا المعلومات في 8 مارس!
هذا العام ، قررنا عدم إعطاء الزنبق وعدم اختيار مجموعة من الهدايا المهوس. لقد اتخذنا مسارًا مختلفًا وأنشأنا صفحة IT لتكنولوجيا المعلومات لإظهار وجود متخصصات في تكنولوجيا المعلومات.


All Articles