في الوحدة السابقة، تم استكشاف بعض النظريات المتعلقة بمسار العرض الحرج، وكيف يمكن للموارد التي تحظر العرض وتحظر المحلّل أن تؤخّر العرض الأوّلي للصفحة. بعد أن تعرّفت على بعض الأسس النظرية لهذا الموضوع، أصبحت جاهزًا للتعرّف على بعض الأساليب لتحسين مسار العرض الحرج.
أثناء تحميل الصفحة، تتم الإشارة إلى العديد من الموارد ضمن HTML، ما يمنح الصفحة مظهرها وتصميمها من خلال CSS، فضلاً عن تفاعلها من خلال JavaScript. في هذه الوحدة، سنتناول عددًا من المفاهيم المهمة المتعلقة بهذه الموارد وتأثيرها في وقت تحميل الصفحة.
حظر العرض
كما تم توضيحه في الوحدة السابقة، فإنّ CSS هو مورد يحظر العرض، لأنّه يمنع المتصفّح من عرض أي محتوى إلى أن يتم إنشاء نموذج كائن CSS (CSSOM). يحظر المتصفّح العرض لمنع حدوث وميض المحتوى غير المنسّق (FOUC)، وهو أمر غير مرغوب فيه من منظور تجربة المستخدم.
في الفيديو السابق، يظهر وميض قصير من المحتوى غير المنسَّق حيث يمكنك رؤية الصفحة بدون أي تنسيق. بعد ذلك، يتم تطبيق جميع الأنماط بعد انتهاء تحميل محتوى CSS الخاص بالصفحة من الشبكة، ويتم استبدال النسخة غير المصمَّمة من الصفحة على الفور بالنسخة المصمَّمة.
بشكل عام، لا يظهر FOUC عادةً، ولكن من المهم فهم هذا المفهوم لكي تعرف سبب حظر المتصفّح لعرض الصفحة إلى أن يتم تنزيل CSS وتطبيقه على الصفحة. لا يُعدّ حظر العرض أمرًا غير مرغوب فيه بالضرورة، ولكن عليك تقليل مدة الحظر إلى الحدّ الأدنى من خلال الحفاظ على تحسين CSS.
حظر المُحلّل اللغوي
يؤدي المورد المانع للتحليل إلى مقاطعة محلّل HTML، مثل العنصر <script> بدون السمتَين async أو defer. عندما يصادف المحلّل عنصر <script>، يحتاج المتصفّح إلى تقييم النص البرمجي وتنفيذه قبل المتابعة في تحليل بقية رمز HTML. هذا السلوك مقصود، لأنّ النصوص البرمجية قد تعدّل أو تصل إلى نموذج DOM أثناء إنشائه.
<!-- This is a parser-blocking script: -->
<script src="/script.js"></script>
عند استخدام ملفات JavaScript خارجية (بدون async أو defer أو type=module التي تكون defer تلقائيًا)، يتم حظر المحلّل اللغوي منذ اكتشاف الملف إلى أن يتم تنزيله وتحليله وتنفيذه. عند استخدام JavaScript المضمّن، يتم حظر المحلّل بالطريقة نفسها إلى أن يتم تحليل النص البرمجي المضمّن وتنفيذه.
أداة الفحص المسبق للتحميل
ماسح التحميل المُسبق هو أداة لتحسين أداء المتصفّح، وتتضمّن محلّل HTML ثانويًا يمسح استجابة HTML الأولية للعثور على الموارد وجلبها بشكل تخميني قبل أن يكتشفها محلّل HTML الأساسي. على سبيل المثال، سيسمح فاحص التحميل المسبق للمتصفّح ببدء تنزيل مورد محدّد في عنصر <img>، حتى عندما يكون محلّل HTML محظورًا أثناء جلب الموارد ومعالجتها، مثل CSS وJavaScript.
للاستفادة من أداة الفحص المسبق للتحميل المُسبق، يجب تضمين الموارد المهمة في ترميز HTML الذي يرسله الخادم. لا يمكن أن يرصد ماسح التحميل المُسبَق أنماط تحميل الموارد التالية:
- الصور التي يتم تحميلها بواسطة CSS باستخدام السمة
background-imageتكون مراجع الصور هذه مضمّنة في CSS، ولا يمكن أن يرصدها برنامج الفحص المسبق للتحميل. - النصوص البرمجية التي يتم تحميلها بشكل ديناميكي في شكل ترميز عنصر
<script>يتم إدخاله في نموذج العناصر في المستند (DOM) باستخدام JavaScript أو الوحدات التي يتم تحميلها باستخدام dynamicimport(). - يتم عرض HTML على العميل باستخدام JavaScript. يتم تضمين هذا الترميز ضمن سلاسل في موارد JavaScript، ولا يمكن أن يرصده برنامج الفحص المسبق للتحميل.
- تعريفات
@importفي CSS
جميع أنماط تحميل الموارد هذه هي موارد يتم اكتشافها في وقت لاحق، وبالتالي لا تستفيد من أداة فحص التحميل المُسبَق. تجنَّبها قدر الإمكان. إذا تعذّر تجنُّب هذه الأنماط، يمكنك استخدام تلميح preload لتجنُّب التأخير في اكتشاف الموارد.
CSS
تحدّد لغة CSS طريقة عرض الصفحة وتنسيقها. كما ذكرنا سابقًا، CSS هو مصدر يحظر العرض، لذا يمكن أن يؤدي تحسين CSS إلى تأثير كبير في وقت تحميل الصفحة الإجمالي.
إزالة البيانات غير الضرورية
يؤدي تصغير ملفات CSS إلى تقليل حجم ملف أحد موارد CSS، ما يتيح تنزيلها بشكل أسرع. ويتم ذلك بشكل أساسي عن طريق إزالة المحتوى من ملف CSS المصدر، مثل المسافات والأحرف الأخرى غير المرئية، وإخراج النتيجة إلى ملف جديد محسّن:
/* Unminified CSS: */
/* Heading 1 */
h1 {
font-size: 2em;
color: #000000;
}
/* Heading 2 */
h2 {
font-size: 1.5em;
color: #000000;
}
/* Minified CSS: */
h1,h2{color:#000}h1{font-size:2em}h2{font-size:1.5em}
في أبسط أشكالها، عملية تصغير ملفات CSS هي عملية تحسين فعّالة يمكن أن تؤدي إلى تحسين مقياس FCP لموقعك الإلكتروني، وربما مقياس LCP أيضًا في بعض الحالات. يمكن لأدوات، مثل حزم التطبيقات، إجراء عملية التحسين هذه تلقائيًا في إصدارات الإنتاج.
إزالة خدمة CSS غير المُستخدَمة
قبل عرض أي محتوى، يحتاج المتصفّح إلى تنزيل جميع أوراق الأنماط وتحليلها. يشمل الوقت المطلوب لإكمال عملية التحليل أيضًا الأنماط غير المستخدَمة في الصفحة الحالية. إذا كنت تستخدم أداة تجميع تدمج جميع موارد CSS في ملف واحد، من المحتمل أن ينزّل المستخدمون كمية أكبر من CSS مما هو مطلوب لعرض الصفحة الحالية.
للعثور على CSS غير مستخدَمة في الصفحة الحالية، استخدِم أداة "نسبة استخدام رموز الصفحة" في "أدوات مطوّري البرامج في Chrome".
تؤدي إزالة محتوى CSS غير المستخدَم إلى تحقيق فائدتَين: بالإضافة إلى تقليل وقت التنزيل، يمكنك تحسين عملية إنشاء شجرة العرض، لأنّ المتصفّح يحتاج إلى معالجة عدد أقل من قواعد CSS.
تجنُّب تعريفات @import في CSS
على الرغم من أنّها قد تبدو ملائمة، عليك تجنُّب تعريفات @import في CSS:
/* Don't do this: */
@import url('style.css');
على غرار طريقة عمل العنصر <link> في HTML، يتيح لك تعريف @import في CSS استيراد مصدر CSS خارجي من داخل ورقة أنماط. ويكمن الاختلاف الرئيسي بين هذين الأسلوبين في أنّ العنصر <link> في HTML يشكّل جزءًا من استجابة HTML، وبالتالي يتم اكتشافه بشكل أسرع بكثير من ملف CSS الذي يتم تنزيله من خلال تعريف @import.
والسبب في ذلك هو أنّه لكي يتم اكتشاف بيان @import، يجب أولاً تنزيل ملف CSS الذي يحتوي عليه. يؤدي ذلك إلى ما يُعرف باسم سلسلة الطلبات التي تؤخّر، في حالة CSS، المدة التي تستغرقها الصفحة في العرض الأوّلي. من العيوب الأخرى أنّ أوراق الأنماط التي يتم تحميلها باستخدام تصريح @import لا يمكن أن يكتشفها برنامج الفحص المسبق للتحميل، وبالتالي تصبح موارد تحظر العرض ويتم اكتشافها متأخرًا.
<!-- Do this instead: -->
<link rel="stylesheet" href="style.css">
في معظم الحالات، يمكنك استبدال @import باستخدام عنصر <link rel="stylesheet">. تسمح عناصر <link> بتنزيل أوراق الأنماط في الوقت نفسه، ما يقلّل من مدّة التحميل الإجمالي، وذلك على عكس تصريحات @import التي تنزّل أوراق الأنماط على التوالي.
تضمين CSS المهم في الصفحة
يمكن أن يؤدي الوقت المستغرَق في تنزيل ملفات CSS إلى زيادة سرعة عرض أول محتوى مرئي على الصفحة. يؤدي تضمين الأنماط المهمة في المستند إلى <head> إلغاء طلب الشبكة لمورد CSS، ويمكن أن يؤدي ذلك إلى تحسين أوقات التحميل الأولية عندما لا يكون مخزن مؤقت للمتصفح لدى المستخدم جاهزًا. يمكن تحميل باقي CSS بشكل غير متزامن أو إلحاقه في نهاية العنصر <body>.
<head>
<title>Page Title</title>
<!-- ... -->
<style>h1,h2{color:#000}h1{font-size:2em}h2{font-size:1.5em}</style>
</head>
<body>
<!-- Other page markup... -->
<link rel="stylesheet" href="non-critical.css">
</body>
من ناحية أخرى، يؤدي تضمين كمية كبيرة من CSS إلى إضافة المزيد من وحدات البايت إلى استجابة HTML الأولية. بما أنّه لا يمكن غالبًا تخزين موارد HTML مؤقتًا لفترة طويلة أو على الإطلاق، هذا يعني أنّه لا يتم تخزين CSS المضمّن مؤقتًا للصفحات اللاحقة التي قد تستخدم CSS نفسه في أوراق الأنماط الخارجية. اختبِر أداء صفحتك وقيّمه للتأكّد من أنّ التنازلات تستحق الجهد.
العروض التوضيحية لخدمة مقارنة الأسعار (CSS)
JavaScript
توفّر JavaScript معظم التفاعلات على الويب، ولكنّها تتطلّب تكلفة. قد يؤدي إرسال كمية كبيرة جدًا من JavaScript إلى بطء استجابة صفحة الويب أثناء تحميلها، وقد يتسبب أيضًا في حدوث مشاكل في الاستجابة تؤدي إلى بطء التفاعلات، وكلتا المشكلتين قد تكونان مزعجتين للمستخدمين.
حظر عرض JavaScript
عند تحميل عناصر <script> بدون السمتَين defer أو async، يحظر المتصفّح تحليل المحتوى وعرضه إلى أن يتم تنزيل النص البرمجي وتحليله وتنفيذه. وبالمثل، تحظر النصوص البرمجية المضمّنة المحلّل إلى أن يتم تحليل النص البرمجي وتنفيذه.
async مقارنةً بـ defer
يسمح async وdefer بتحميل النصوص البرمجية الخارجية بدون حظر محلّل HTML، بينما يتم تلقائيًا تأجيل النصوص البرمجية (بما في ذلك النصوص البرمجية المضمّنة) التي تتضمّن type="module". ومع ذلك، هناك بعض الاختلافات بين async وdefer التي من المهم فهمها.
يتم تحليل النصوص البرمجية التي يتم تحميلها باستخدام async وتنفيذها فور تنزيلها، بينما يتم تنفيذ النصوص البرمجية التي يتم تحميلها باستخدام defer عند الانتهاء من تحليل مستند HTML، ويحدث ذلك في الوقت نفسه الذي يحدث فيه حدث DOMContentLoaded في المتصفح.
بالإضافة إلى ذلك، قد يتم تنفيذ نصوص async البرمجية بترتيب مختلف عن ترتيب ظهورها، بينما يتم تنفيذ نصوص defer البرمجية بالترتيب الذي تظهر به في الترميز.
العرض من جهة العميل
بشكل عام، يجب تجنُّب استخدام JavaScript لعرض أي محتوى مهم أو عنصر LCP في الصفحة. يُعرف ذلك باسم العرض من جهة العميل، وهو أسلوب يُستخدم على نطاق واسع في تطبيقات الصفحة الواحدة (SPA).
يتجنّب الترميز الذي يتم عرضه باستخدام JavaScript أداة فحص التحميل المُسبَق، لأنّ الموارد المضمّنة في الترميز المعروض من جهة العميل لا يمكن لأداة الفحص اكتشافها. وقد يؤدي ذلك إلى تأخير تنزيل الموارد المهمة، مثل صورة أكبر محتوى مرئي على الصفحة. لا يبدأ المتصفّح في تنزيل صورة LCP إلا بعد تنفيذ النص البرمجي وإضافة العنصر إلى DOM. وبالتالي، لا يمكن تنفيذ النص البرمجي إلا بعد العثور عليه وتنزيله وتحليله. يُعرف ذلك باسم تسلسل الطلبات المهمة ويجب تجنُّبه.
بالإضافة إلى ذلك، من المرجّح أن يؤدي عرض الترميز باستخدام JavaScript إلى إنشاء مهام طويلة أكثر من الترميز الذي يتم تنزيله من الخادم استجابةً لطلب انتقال. يمكن أن يؤثّر الاستخدام المكثّف للعرض من جهة العميل لملفات HTML سلبًا في وقت استجابة التفاعل. ويكون ذلك صحيحًا بشكل خاص في الحالات التي يكون فيها حجم DOM الخاص بالصفحة كبيرًا جدًا، ما يؤدي إلى تنفيذ عملية عرض كبيرة عندما تعدّل JavaScript عناصر DOM.
إزالة البيانات غير الضرورية
على غرار CSS، يؤدي تصغير JavaScript إلى تقليل حجم ملف أحد موارد النصوص البرمجية. يمكن أن يؤدي ذلك إلى تسريع عمليات التنزيل، ما يتيح للمتصفّح الانتقال إلى عملية تحليل وتجميع JavaScript بشكل أسرع.
بالإضافة إلى ذلك، يذهب تصغير JavaScript إلى أبعد من تصغير مواد العرض الأخرى، مثل CSS. عند تصغير حجم JavaScript، لا تتم إزالة المساحات الفارغة وعلامات التبويب والتعليقات فقط، بل يتم أيضًا تقصير الرموز في مصدر JavaScript. يُشار إلى هذه العملية أحيانًا باسم التشويه. للاطّلاع على الفرق، استخدِم رمز المصدر التالي في JavaScript:
// Unuglified JavaScript source code:
export function injectScript () {
const scriptElement = document.createElement('script');
scriptElement.src = '/js/scripts.js';
scriptElement.type = 'module';
document.body.appendChild(scriptElement);
}
عندما يتم تصغير الرمز المصدر JavaScript السابق، قد تبدو النتيجة على النحو التالي: مقتطف الرمز التالي:
// Uglified JavaScript production code:
export function injectScript(){const t=document.createElement("script");t.src="/js/scripts.js",t.type="module",document.body.appendChild(t)}
في المقتطف السابق، يمكنك ملاحظة أنّ المتغيّر القابل للقراءة
scriptElement في المصدر تم اختصاره إلى t. وعند تطبيق هذه الطريقة على مجموعة كبيرة من النصوص البرمجية، يمكن تحقيق توفير كبير في المساحة بدون التأثير في الميزات التي يوفّرها JavaScript الخاص بالإنتاج على الموقع الإلكتروني.
إذا كنت تستخدم أداة تجميع لمعالجة الرمز المصدر لموقعك الإلكتروني، يتم غالبًا تنفيذ عملية التصغير تلقائيًا في إصدارات الإنتاج. يمكن أيضًا ضبط أدوات التشويه، مثل Terser، بشكل كبير، ما يتيح لك تعديل مدى فعالية خوارزمية التشويه لتحقيق أقصى قدر من التوفير. ومع ذلك، تكون الإعدادات التلقائية لأي أداة تصغير كافية عادةً لتحقيق التوازن الصحيح بين حجم الناتج والحفاظ على الإمكانات.
العروض التوضيحية لـ JavaScript
اختبِر معلوماتك
ما هي أفضل طريقة لتحميل ملفات CSS متعددة في المتصفّح؟
@import في CSS<link> متعدّدةما هي وظيفة فاحص التحميل المُسبَق في المتصفّح؟
<link rel="preload"> في مصدر HTML.
لماذا يحظر المتصفّح مؤقتًا تحليل HTML تلقائيًا عند تنزيل موارد JavaScript؟
التالي: مساعدة المتصفّح في استخدام تلميحات الموارد
بعد أن أصبحت على دراية بكيفية تأثير الموارد التي يتم تحميلها في العنصر <head> على التحميل الأولي للصفحة والمقاييس المختلفة، حان الوقت للانتقال إلى الخطوة التالية. في الوحدة التالية، سنتعرّف على تلميحات الموارد وكيف يمكنها تقديم تلميحات قيّمة إلى المتصفّح لبدء تحميل الموارد وفتح الاتصالات مع الخوادم الخارجية في وقت أقرب من الوقت الذي كان سيستغرقه المتصفّح بدون هذه التلميحات.