تحليل أداء مسار العرض الحرج

تاريخ النشر: 31 آذار (مارس) 2014

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

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

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

ركّزنا حتى الآن بشكل حصري على ما يحدث في المتصفح بعد أن تتم معالجة المورد (CSS أو JS أو HTML). لقد تجاهلنا الوقت الذي يستغرقه جلب المورد من ذاكرة التخزين المؤقت أو من الشبكة. سنفترض ما يلي:

  • تبلغ تكلفة إرسال الشبكة ذهابًا وإيابًا (وقت استجابة النشر) إلى الخادم 100 ملي ثانية.
  • يبلغ وقت استجابة الخادم 100 ملي ثانية لمستند HTML و10 ملي ثانية لجميع الملفات الأخرى.

تجربة hello world

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <title>Critical Path: No Style</title>
  </head>
  <body>
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg" /></div>
  </body>
</html>

التجربة الآن

ابدأ بترميز HTML الأساسي وصورة واحدة؛ لا تتوفر أي لغة CSS أو JavaScript. بعد ذلك، افتح لوحة "الشبكة" في "أدوات مطوّري البرامج في Chrome" وتحقّق من تدفق الموارد الناتج:

CRP

كما هو متوقّع، استغرق تنزيل ملف HTML حوالي 200 ملي ثانية. يُرجى العِلم أنّ الجزء الشفاف من الخطّ الأزرق يمثّل المدة التي ينتظر فيها المتصفّح على الشبكة بدون تلقّي أي وحدات بايت من الاستجابة، في حين يعرض الجزء المُكتَمِل الوقت الذي يستغرقه إكمال عملية التنزيل بعد تلقّي وحدات البايت الأولى من الاستجابة. حجم تنزيل HTML صغير (أقل من 4K)، لذا كل ما نحتاج إليه هو جولة ذهاب وعودة واحدة لجلب الملف بالكامل. ونتيجة لذلك، يستغرق جلب مستند HTML حوالي 200 ملّي ثانية، وينتظر نصف الوقت الآخر في انتظار استجابة الخادم.

عندما يصبح محتوى HTML متاحًا، يحلّل المتصفح وحدات البايت ويحوّلها إلى رموز مميزة، وينشئ شجرة نموذج العناصر في المستند. لاحِظ أنّ أدوات مطوّري البرامج تُبلغ بسهولة عن وقت الحدث DOMContentLoaded في الأسفل (216 ملي ثانية)، وهو ما يقابل الخط العمودي الأزرق أيضًا. الفجوة بين نهاية تنزيل HTML والخط العمودي الأزرق (DOMContentLoaded) هي الوقت الذي يستغرقه المتصفّح لإنشاء شجرة DOM، وفي هذه الحالة، لا تتجاوز بضع مللي ثانية.

يُرجى ملاحظة أنّ "الصورة الرائعة" لم تحظر الحدث domContentLoaded. تبيّن لنا أنّه يمكننا إنشاء شجرة العرض وحتى عرض الصفحة بدون انتظار كل مادة عرض على الصفحة: ليست كل الموارد مهمة لتقديم سرعة عرض الصفحة الأولى. في الواقع، عندما نتحدث عن مسار العرض المهم، نقصد عادةً ترميز HTML وCSS وJavaScript. لا تحظر الصور العرض الأولي للصفحة، ولكن يجب أن نحاول عرض الصور في أسرع وقت ممكن.

ومع ذلك، تم حظر حدث load (المعروف أيضًا باسم onload) في الصورة: تُبلغ "أدوات مطوّري البرامج" عن حدث onload بعد 335 ملي ثانية. تذكَّر أنّ حدث onload يحدّد النقطة التي تم عندها تنزيل ومعالجة جميع الموارد التي تتطلّبها الصفحة. عند هذه النقطة، يمكن أن يتوقف دوّار التحميل عن الدوران في المتصفح (الخط الرأسي الأحمر في الشلال).

إضافة JavaScript وCSS إلى المزيج

"تجربة Hello World" صفحة أساسية، ولكن هناك الكثير من الأمور. في الواقع، سنحتاج إلى أكثر من صفحات HTML فقط: من المحتمل أن يكون لدينا ورقة أنماط CSS ونص برمجي واحد أو أكثر لإضافة بعض التفاعل إلى صفحتنا. أضف كليهما إلى المزيج لمعرفة ما يحدث:

<!DOCTYPE html>
<html>
  <head>
    <title>Critical Path: Measure Script</title>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link href="style.css" rel="stylesheet" />
  </head>
  <body onload="measureCRP()">
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg" /></div>
    <script src="timing.js"></script>
  </body>
</html>

التجربة الآن

قبل إضافة JavaScript وCSS:

نموذج العناصر في المستند (DOM) CRP

باستخدام JavaScript وCSS:

DOM وCSSOM وJS

تؤدي إضافة ملفات CSS وJavaScript خارجية إلى إضافة طلبين إضافيين إلى العرض الإعلاني بدون انقطاع، ويتم إرسالهما جميعًا في الوقت نفسه تقريبًا. مع ذلك، يُرجى العلم أنّ هناك الآن فرقًا أصغر بكثير في التوقيت بين الحدثَين domContentLoaded وonload.

ما السبب؟

  • على عكس مثال HTML العادي، نحتاج أيضًا إلى جلب ملف CSS وتحليله لإنشاء CSSOM، ونحتاج إلى كلّ من DOM وCSSOM لإنشاء شجرة العرض.
  • بما أنّ الصفحة تحتوي أيضًا على محلل بيانات يحظر ملف JavaScript، يتم حظر الحدث domContentLoaded إلى أن يتم تنزيل ملف CSS وتحليله: ولأنّ JavaScript قد تستعلم عن CSSOM، يجب أن نحظر ملف CSS إلى أن يتم تنزيله قبل أن نتمكّن من تنفيذ JavaScript.

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

ومع ذلك، على الرغم من الحظر على CSS، هل يؤدي تضمين النص البرمجي إلى عرض الصفحة بشكل أسرع؟ جرِّب ذلك وشاهِد ما سيحدث.

JavaScript الخارجية:

DOM وCSSOM وJS

محتوى JavaScript المضمّن:

نموذج DOM وCSSOM وJavaScript المضمّن

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

أولاً، تذكَّر أنّ جميع النصوص البرمجية المضمّنة تحظر المُحلِّل، ولكن بالنسبة إلى النصوص البرمجية الخارجية، يمكننا إضافة السمة async لإزالة حظر المُحلِّل. التراجع عن التضمين وتجربته:

<!DOCTYPE html>
<html>
  <head>
    <title>Critical Path: Measure Async</title>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link href="style.css" rel="stylesheet" />
  </head>
  <body onload="measureCRP()">
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg" /></div>
    <script async src="timing.js"></script>
  </body>
</html>

التجربة الآن

حظر المحلل اللغوي (الخارجي) من JavaScript:

DOM وCSSOM وJS

JavaScript غير المتزامنة (الخارجية):

DOM، CSSOM، JS غير المتزامن

أفضل بكثير. يتم تنشيط حدث domContentLoaded بعد وقت قصير من تحليل HTML. يعرف المتصفح عدم الحظر على JavaScript ونظرًا لعدم وجود محلل لغوي آخر يحظر النصوص البرمجية، يمكن أيضًا متابعة إنشاء CSSOM بالتوازي.

بدلاً من ذلك، يمكننا تضمين كلّ من CSS وJavaScript:

<!DOCTYPE html>
<html>
  <head>
    <title>Critical Path: Measure Inlined</title>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <style>
      p {
        font-weight: bold;
      }
      span {
        color: red;
      }
      p span {
        display: none;
      }
      img {
        float: right;
      }
    </style>
  </head>
  <body>
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg" /></div>
    <script>
      var span = document.getElementsByTagName('span')[0];
      span.textContent = 'interactive'; // change DOM text content
      span.style.display = 'inline'; // change CSSOM property
      // create a new element, style it, and append it to the DOM
      var loadTime = document.createElement('div');
      loadTime.textContent = 'You loaded this page on: ' + new Date();
      loadTime.style.color = 'blue';
      document.body.appendChild(loadTime);
    </script>
  </body>
</html>

التجربة

نموذج DOM وCSS المضمّن وJavaScript المضمّن

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

فكما ترى، حتى مع الصفحات الأساسية، يُعد تحسين مسار العرض الحرج تمرينًا غير تافه: فنحن بحاجة إلى فهم الرسم البياني للتبعية بين الموارد المختلفة، ونحتاج إلى تحديد الموارد "الحرجة"، وعلينا الاختيار من بين استراتيجيات مختلفة حول كيفية تضمين هذه الموارد في الصفحة. لا يوجد حل واحد لهذه المشكلة، لأنّ كل صفحة مختلفة. عليك اتّباع عملية مماثلة بنفسك لمعرفة الاستراتيجية المثلى.

مع ذلك، لنلقِ نظرة على بعض أنماط الأداء العامة.

أنماط الأداء

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

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <title>Critical Path: No Style</title>
  </head>
  <body>
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg" /></div>
  </body>
</html>

التجربة

مرحبًا بالعالم CRP

يُسجِّل الوقت بين T0 وT1 أوقات معالجة الشبكة والخادم. في أفضل الأحوال (إذا كان ملف HTML صغيرًا)، يمكن جلب المستند بأكمله من خلال رحلة واحدة فقط على الشبكة. نظرًا للطريقة التي تعمل بها بروتوكولات النقل TCP، قد تتطلب الملفات الأكبر حجمًا المزيد من عمليات نقل البيانات ذهابًا وإيابًا. نتيجةً لذلك، تحتوي الصفحة أعلاه، في أفضل الحالات، على مسار عرض مهم واحد ذهابًا وإيابًا (الحد الأدنى).

ضع في اعتبارك الآن الصفحة نفسها، ولكن باستخدام ملف CSS خارجي:

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link href="style.css" rel="stylesheet" />
  </head>
  <body>
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg" /></div>
  </body>
</html>

التجربة الآن

DOM + CSSOM CRP

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

في ما يلي بعض المصطلحات التي نستخدمها لوصف مسار التقديم الحرج:

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

قارن الآن ذلك بخصائص المسار الحرج لمثال HTML وCSS السابق:

DOM + CSSOM CRP

  • موردَان مهمّان
  • عمليتان أو أكثر من تنقّلات ذهاباً وإيابًا للحد الأدنى لطول المسار الحرج
  • 9 كيلوبايت من البايتات المهمة

نحتاج إلى كل من HTML وCSS لإنشاء شجرة العرض. ونتيجةً لذلك، يُعد كل من HTML وCSS موردين مهمين: لا يتم جلب CSS إلا بعد حصول المتصفح على مستند HTML، وبالتالي يكون طول المسار الحرج هو رحلتا ذهاب وعودة على الأقل. يضيف كلا الموردَين ما مجموعه 9 كيلوبايت من البايتات المهمة.

والآن، أضِف ملف JavaScript إضافيًا إلى المزيج.

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link href="style.css" rel="stylesheet" />
  </head>
  <body>
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg" /></div>
    <script src="app.js"></script>
  </body>
</html>

التجربة الآن

أضفنا app.js، وهي مادة عرض JavaScript خارجية على الصفحة ومورد حظر (أي مهم) للمحلِّل. والأسوأ من ذلك، أنّه لتنفيذ ملف JavaScript، علينا حظر CSSOM والانتظار إلى أن يتم تنزيل style.css وإنشاء CSSOM. يُرجى تذكُّر أنّ JavaScript يمكنه طلب بيانات من CSSOM، وبالتالي يتوقف المتصفّح مؤقتًا إلى أن يتم تنزيل style.css وإنشاء CSSOM.

DOM، CSSOM، JavaScript CRP

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

  • 3 موارد مهمة
  • عمليتان أو أكثر من تنقّلات ذهاباً وإيابًا للحد الأدنى لطول المسار الحرج
  • 11 كيلوبايت من وحدات البايت الحرجة

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

بعد التواصل مع مطوّري الموقع الإلكتروني، تبيّن لنا أنّه ليس من الضروري حظر JavaScript الذي أدرجناه في صفحتنا، لأنّنا نستخدم بعض الإحصاءات والرموز البرمجية الأخرى التي لا تحتاج إلى حظر عرض صفحتنا. بعد معرفة ذلك، يمكننا إضافة السمة async إلى العنصر <script> لإزالة حظر المُحلِّل:

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link href="style.css" rel="stylesheet" />
  </head>
  <body>
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg" /></div>
    <script src="app.js" async></script>
  </body>
</html>

التجربة

تحليل DOM وCSSOM وJavaScript غير المتزامن

النصوص البرمجية غير المتزامنة لها عدة مزايا:

  • لم يعُد النص البرمجي يعرقل عمل المُحلِّل، كما أنّه ليس جزءًا من مسار المعالجة الحرج.
  • بسبب عدم توفّر نصوص برمجية مهمة أخرى، لا تحتاج خدمة CSS إلى حظر حدث domContentLoaded.
  • كلما أسرعت في تنشيط حدث domContentLoaded، أصبح تنفيذ منطق التطبيق الآخر أسرع.

ونتيجةً لذلك، عادت الصفحة المحسّنة الآن إلى موردَين مهمَّين (HTML وCSS)، بحدّ أدنى لطول المسار الحرج من رحلتَي ذهاب وعودة، وإجمالي 9 كيلوبايت من وحدات البايت الحرجة.

أخيرًا، إذا كانت ورقة أنماط CSS مطلوبة للطباعة فقط، كيف ستبدو؟

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link href="style.css" rel="stylesheet" media="print" />
  </head>
  <body>
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg" /></div>
    <script src="app.js" async></script>
  </body>
</html>

التجربة

نموذج العناصر في المستند (DOM) وCSS غير المحظورة وبرنامج JavaScript CRP غير المتزامن

بما أنّ مورد style.css يُستخدم للطباعة فقط، لا يحتاج المتصفّح إلى حظره لعرض الصفحة. وبالتالي، فور اكتمال إنشاء نموذج العناصر في المستند (DOM)، تكون لدى المتصفّح معلومات كافية لعرض الصفحة. ونتيجةً لذلك، تحتوي هذه الصفحة على مورد مهم واحد فقط (مستند HTML)، ويكون الحد الأدنى لطول مسار العرض الحرج هو رحلة ذهاب وعودة واحدة.

ملاحظات