Web performance - الجزء الثالث

بسم الله الرحمن الرحيم

الحمد لله ربّ العالمين، يُحب من دعاه خفياً، ويُجيب من ناداه نجيّاً، ويزيدُ من كان منه حيِيّاً، ويكرم من كان له وفيّاً، ويهدي من كان صادق الوعد رضيّاً، الحمد لله ربّ العالمين.

 

Web performance - 3

(كيف يعمل المتصفح، دورة حياة ال Request من وإلى المستخدم)

 

في الجزء الثاني من هذه السلسلة تحدثنا عن مجموعة من العناوين والأجزاء المهمة والتي تقع ضمن دائرة ال Web Performance، والتي تؤثر بشكل مباشر وحقيقي أو بشكل تخيلي على الأداء، وكيف يمكن معالجة بعض المشاكل المتعلقة بالأداء…

 

لكن، كيف يمكن أن نفهم ما تحدثنا عنه من مصطلحات ومواضيع دون أن ندرك كيف يتعامل المتصفح مع ال content؟، إن إدراك ما يحدث من عمليات مهم لفهم ما يحدث عند ال content render، وبناء على ذلك يمكنك فهم المشاكل المتعلقة بالأداء بشكل أفضل، وهذا يشمل ما يلي:

 How the browser works: عند قيامك بوضع رابط الموقع الذي ترغب في الذهاب إليه في المتصفح ومن ثم ضغط Enter، فإن ما يحدث هو أن المتصفح سيقوم بالبحث عن ال server الذي يملك الملفات الخاصة بالموقع المطلوب، ثم سيقوم بفتح connection مع هذا ال server، ثم يقوم بطلب ال files التي يحتاجها لعرض الموقع على المتصفح، وهذا يقودنا لبعض التفاصيل المهمة والتي ينبغي لنا أن ندركها، أولا المتصفحات عبارة عن تطبيق single threaded (ونقصد بهذا العمليات التي تحدث حتى إنشاء المحتوى في الصفحة أو العمليات التي تتم على ال frontend)، وهذه نقطة مهمة جدا للتعامل مع مشاكل الأداء، فمشاكل الأداء الرئيسية تنقسم إلى جزئين، الأول متعلق بال Latency والثاني المشاكل المتعلقة بطريقة تنفيذ العمليات على المتصفح من خلال النظر إلى المتصفح وطريقة تعامله مع الأوامر والفعاليات على frontend باعتباره single threaded، وكما تحدثنا في الجزء السابق عن ل latency، فإننا يجب أن نهتم بتقليل وقت ال latency قدر الإمكان لتحسين الأداء، ويكون الهدف عن المطور هو إرسال information request أسرع ما يمكن، ويكون دور المطور في التعامل مع المتصفح باعتباره single thread وهدفه ضمان جودة التفاعل وكفاءتها مع الموقع الإلكتروني، وهذا يشمل عدة أجزاء أهمها التأكد من أن ال main thread ستقوم بإنجاز جميع الأعمال المطلوبة منها ومستعدة دومًا للتجاوب مع العمليات التي يقوم بها المستخدم، وتكمن النقطة الجميلة هنا في فهم هذه الجزئية، هو القدرة على تقليل عدد العمليات والمسؤوليات الموجودة على ال main thread إن أمكن ذلك، وذلك سيضمن تحسين الأداء من خلال التأكد من أن ال render سيكون سلس والوقت اللازم للتفاعل أفضل مما يوفر سرعة تجاوب فورية…، والآن بعد هذه النظرة العامة على طريقة عمل المتصفح، لندخل ببعض التفاصيل أكثر: 

  1. أول عملية تتم أثناء تعاملك مع المتصفح ورغبتك في زيارة موقع الكتروني هو عمل Navigation للموقع المطلوب، أكان ذلك من خلال ال url أو من خلال رابط موجود في صفحة ما أو من خلال form…إلى آخره، عادة هذه العملية سريعة ولا تستغرق وقتا كبيرا، والتأثير السلبي عليها غالبا يتم من خلال مشاكل ال bandwidth وال latency.

  2. DNS Lookup: ال DNS هي اختصار ل Domain Name System، وهو أحد البروتوكولات المهمة الخاصة بالبنية التحتية للويب، وبشكل مبسط فإن هذا البروتوكول يقوم بوظيفة دفتر الهاتف (الدفتر الذي كنا نكتب فيه الإسم ورقم الهاتف)، يقوم المتصفح بطلب موقع معين والذي نحاول الذهاب إليه، هذا الموقع له عنوان على شبكة الإنترنت، هذا العنوان يسمى IP address، هذا ال IP لنحصل عليه يتم التواصل مع ال DNS، ويقوم ال DNS بدوره بإرجاع العنوان الخاص بهذا الموقع، هذا ال request هو ال initial request، بعد ذلك يتم تخزين ال ip address لبعض الوقت، وذلك يحسن من الأداء، فلا داعي لطلب العنوان مرة أخرى، بل يكفي جلبه من ال cache…

  3. TCP Handshake: يعد ال TCP بروتوكول واحد من أهم البروتوكولات الموجودة على الشبكة، لأنه يمكن جهازين أو مضيفين من الاتصال مع بعضهما وتبادل البيانات فيما بينهم، ويحترم ال TCP الترتيب الخاص بالبيانات التي يتم إرسالها، لذلك فهو يضمن أن تكون ال packets دائما بنفس الترتيب الذي أرسلت به، لكنك تتسائل الآن، ما هو ال handshake؟، والجواب هو أنها عملية يستخدمها ال TCP كوسيلة تفاوض بين الجهازين أو المضيفين على ال parameters الخاصة بالإتصال، بحيث يعرف ويمرر كل واحد منهما المعلومات إلى الآخر ذهابا وإيابا قبل إرسال البيانات، وتسمى هذه العملية  three-way handshake، ويتم تبادل ال messages من خلال ثلاث عمليات، ويشار إليها ب SYN, SYN-ACK, ACK، بحيث تشير ال SYN إلى Synchronize، وتشير ال SYN-ACK إلى Synchronize-ACKnowledgement وتشير ال ACK إلى ACKnowledge…، وكمثال عملي على ما سبق، فإن ما يحدث هو أن المتصفح سيقوم بإرسال رسالة SYN إلى ال server، ثم سيقوم ال server بعد استقباله للرسالة بالرد برسالة SYN-ACK إلى المتصفح، ثم سيستقبل المتصفح ما أرسله السيرفر ومن ثم سيقوم بإخبار السيرفر مجددا بأنه قد استلم ACK، وعند استقبال السيرفر لهذه الرسالة الأخيرة من المتصفح، سيكون الاتصال قد أُنشئ بالفعل…، هذه العملية تحدث قبل ال TLS handshake وبعد ال DNS، وهذا أمر مهم يجب أن تتذكره…

  4. TLS handshake: ال TLS هو اختصار ل Transport Layer Security، وحل مكان ال SSL الإصدار الثالث -آخر إصدار تم إطلاقه لل SSL من قبل netscape عام 1996-، وال TLS بروتوكول مهم على الشبكة، فهو يستخدم للتواصل بشكل آمن بين التطبيقات من خلال ال network، وهو يمنع محاولات العبث والتخريب على ال email والمتصفحات والرسائل المرسلة بين الأجهزة ونحو ذلك، وهو بروتوكول يقوم على مبدأ وجود client / server ليضمن الاتصال الآمن لهما من خلال تشفير الاتصال فيما بينهم من خلال بروتوكول مصمم لهذه العملية، وبكل بساطة فإن ما يحصل هو تبادل digital certificates فيما بينهم ومن ثم التحقق من هذه ال certificates فيما بعد، لذلك، لو حاول شخص ثالث الدخول، سيكون لديه certificate مختلفة وبهذا لن يستطيع البعث بما يتم تبادله لأن ذلك سيكون مفضوحا لدى الطرفين، والآن نعود للجزئية المهمة في هذه النقطة، handshake (ويطلق عليها أيضا TLS negotiation)، إن ما يحدث هنا بكل بساطة هو إضافة خطوة جديدة بعد ال SYN-SYN-ACK-ACK، وهي أن ال client سيقوم بإرسال إلى ال server، وسيقوم السيرفر بالرد عليها مضافا لها ال Certificate الخاصة به، ثم يقوم ال client بعد أن يستقبل ال certificate بإرسال ال key الخاص به، وبهذا تكون العملية قد اكتملت…، وهذا يعني 8 خطوات تقريبا ليصبح المتصفح جاهزا للقيام بأي request على الموقع، ونشير هنا إلى نقطة مهمة، وهي أن إضافة ال TLS handshake ستقوم بإضافة بعض من الوقت إلى الزمن الخاص بتحميل الصفحة، لكن هذا أمر يجب أن نقبل به لأن الأمان في الاتصال بين الأطراف له أهمية بالغة مقارنة بالوقت المضاف إلى الوقت الكلي لزمن تحميل الصفحة،… والآن شاهد الصورة لتتضح لك الصورة كاملة:

  5. Response: في هذه الخطوة، الاتصال يكون قد بدأ بالفعل بين ال web server وال client، وما يقوم به المتصفح في هذه الخطوة هو إرسال Initial HTTP GET Request، ومن ثم يقوم ال server بالرد على هذا ال request مع معلومات مفيدة في ال response header..أي أن ال response يحتوي Header & Body…، وهنا نأتي إلى نقطة مهمة، وهي أن الوقت المستغرق من لحظة إنشاء ال request (يشمل ال DNS, TCP, TLS) واستقبال أول packet يطلق عليه TTFB، وهي اختصار ل Time to First Byte، ويتم حسابها بال milliseconds، والمعادلة الخاصة بها بناء على المعطيات التي طرحناها بالأعلى هي: TTFB = responseStart - navigationStart، ومن المعلومات الجميلة التي يمكنك معرفتها هي أن هناك خوارزمية يطلق عليها TCP slow start، هذه الخوارزمية تقوم على زيادة وضبط سرعة نقل البيانات بناء على ال bandwidth الخاص بالشبكة وسرعة نقل البيانات، والفكرة ببساطة أنك لست بحاجة لمعرفة القدرة الخاصة بالشبكة، وإنما تقوم هذه الخوارزمية بدلا من ذلك بإرسال packet تبدأ بحجم صغير ومن ثم تبدأ المضاعفة للحجم مع كل packet، مثلا 14KB أول packet، الثانية ستكون 28KB والثالثة 56KB…وهكذا حتى يتم تحديد أكبر حجم يمكن إرساله، الجميل في هذه الخوارزمية أنها تتيح للشبكة التحكم بمعدل البيانات التي يمكن نقلها مع اختلاف الأوقات وانشغال ال server مثلا…إلى آخره

  6. Parsing: بمجرد أن يستلم المتصفح أول حزمة من البيانات، فإن عملية ال Parsing للمعلومات التي تم استقبالها تبدأ، وال Parsing هي عملية تحليل وتحويل البرنامج إلى format تستطيع من خلاله ال runtime environment عمل run له، بشكل مبسط، تحليل وتحويل البيانات من شكل إلى شكل آخر تستطيع بيئة العمل التي تتعامل معها من فهمه ومن ثم عمل run لما تم فهمه، وأوضح مثال هو JS engine الموجود داخل المتصفح…، والآن عودة لهذه النقطة، فإن ما سيحدث هنا بعد استقبال البيانات هو تحويلها إلى DOM و CSSOM، واللذان يستخدمان لرسم ووصف البيانات على الشاشة!، وال DOM هو التمثيل أو الوصف الخاص بالمعلومات التي تبتغي عرضها، ويمكن التعديل عليه باستخدام الجافا سكربت بأكثر من شكل وبأكثر من وقت، بشكل أدق، هي API تقوم بعمل represents أو interacts مع أي ملفHTML أو XML، لهذا، فإن المتصفح يعرض ال node tree، بحيث تمثل كل node عنصر معين في ال document، وال CSSOM هي اختصار لل CSS Object Model، وهي مجموعة من ال APIs التي تستخدم لقراءة وتعديل التنسيق الخاص بال documents، وهي مشابهة أو قريبة لما كان في DOM من ناحية المبدأ، فال CSSOM يعطي القدرة والقابلية للتعديل على ال document من خلال الجافا سكربت، ومن هذه الأمثلة CSSStyleSheet…، والآن تأتي النقطة المهمة، ففهم النقاط بهذا التسلسل كان لغرض مهم، وهو معرفة أهمية وخطورة ما سيحصل هنا على الأداء، لاحظ أن في هذه العملية سيقوم المتصفح بعمل parsing للمعلومات التي يحتاجها حتى يستطيع إظهار النتائج أو رسمها على الشاشة، وهذا يعني أننا يجب أن نحرص أن تكون أول البيانات هي ما يساعد المتصفح للتجهيز لأول render للشاشة، على الأقل يجب أن تضمن أن يكون ال css وال html جاهزين للاستخدام في أول render، لاحظ أهمية الفهم لما يحدث هنا، فما تحدثنا عنه في المقالات السابقة، ستجده مفهوما الآن، أو على الأقل، ستكون مدركا لماذا قمنا باستخدام أسلوب معين لتحسين الأداء بدلا من أسلوب آخر…

  7. Render: في هذه الخطوة يتم تضمين ما تم إنتاجه من الخطوات السابقة، أي أن ال parse الخاص بال DOM وال CSSOM سيتم دمجها داخل ال render tree، وذلك لمشاهدة النتائج من خلال ال style وال layout وال paint وال compositing، وال style هي الخطوة الثالثة من ال CRP، بحيث يتم بناء ال render tree والتي ستقوم بدورها بإخفاء أي عنصر غير ظاهر (display none)، يلي ذلك ال Layout وهو الخطوة الرابعة، بحيث يقوم ببناء ال layout الخاص بال render tree، ويشمل ال layout ال size وال position الخاص بأي node، يلي ذلك الخطوة الخامسة والأخيرة لل CRP وهي ال Paint، وهي عملية رسم ال nodes على الشاشة، ويجب أن يتم هذا كله من قبل المتصفح في زمن أقل من 16.67ms، يأتي بعد هذا ال Compositing، وهي تأتي في حال وجود أكثر من layer على عدة مستويات وهناك تداخلات فيما بينها، وهناك حاجة للرسم عليهم، فيكون من الضروري هنا ضمان ترتيب هذه المستويات بشكلها الصحيح، وهذه وظيفة ال compositing.

  8. Interactivity: بعد أن يتم رسم ال blocks على الشاشة في الخطوة السابقة، يبقى هناك نقطة أخيرة، وهي هل الصفحة قابلة للتفاعل والتعامل مع ال events الخاصة بالمستخدم؟ كم كانت المدة الزمنية ليستطيع المستخدم التعامل مع الموقع؟، لو كان تحميل الموقع سريع فعلا، لكن استغرق وقتا طويلا حتى يستطيع المستخدم عمل scroll، فهل تظن أن هذه good UX؟، بكل تأكيد هذه الأسئلة مهمة، خصوصا أن وقت التفاعل إذا تأخر فهو سيعطي تجربة سيئة وإن كان تحميل الموقع سريع جدا!، لذلك هناك مفهوم لقياس هذا الزمن يطلق عليه TTI، وهي اختصار ل Time to Interactive، وقد تحدثنا عنه سابقا…، وهناك مفهوم آخر للقياس ويرمز له ب FCP، وهي اختصار ل First Contentful Paint، وهو الوقت المستغرق حتى لحظة render أول bit من المحتوى الموجود بال DOM…

 

ملاحظات:

  • هناك مفهوم يسمى ب (Critical rendering path (CRP، هذا المفهوم غالبا قد رأيته سابقا، لكن إن كنت تتسائل ما هو، فيمكن القول بأنه مجموعة من الخطوات التي تمر من خلال المتصفح لتحويل ال HTML وال CSS وال JS  إلى pixels على الشاشة، إن تحسين الأداء يرتبط بقوة مع سلسلة الخطوات وطولها، إذا قمت بتحسين السلسلة، فبكل تأكيد سيعكس ذلك أداء ممتازا…، وبكل تأكيد، هذا المفهوم يشمل DOM, CSSOM وال render tree وال layout، لكن، احذر، إذا كان البناء سيئا، فإنك ستقع فيما يطلق عليه Jank، وال Jank مصطلح يشير إلى البطء في ال user interface، وعادة ما ينتج ذلك من خلال تنفيذ long task على ال main thread، أو بسبب وجود block rendering…إلى آخره، إن الخطوات المستخدمة لتحسين الأداء الخاص بال CRP يمكن تلخيصها  بتقليل عدد ال resource التي يمكن أن توقف من تسلسل الخطوات، مثل استخدام ال async للملفات التي لن تحتاجها مباشرة، وتقليل عدد ال requests وتصغير حجم الملفات قدر الإمكان، والاهتمام بترتيب ال assets التي نحتاجها، وتقليل عدد الخطوات في السلسلة قدر الإمكان…

  • يقصد بال render tree هي النسخة الناتجة من عملية دمج ال DOM وال CSSOM معا، بمعنى آخر عملية دمل المحتوى والتنسيق معا ليتشكل لدينا render tree، وتتم هذه العملية فقط للمحتوى ال visible، مثلا أي شيء display: none لن يكون موجودا بال render tree لا هو ولا ما يحتويه…

  • Preload scanner: لفهم ما يحصل بشكل أكثر تفصيلا، اعلم أن المتصفح وهو يقوم ببناء ال DOM tree سيكون مسيطرا على ال main thread، لذلك يأتي دور مهم لل Preload scanner، فهو يقوم على عمل parse لل content الذي أصبح متاحا مباشرة، ويقوم بجلب أكثر ال resource أولوية مثل ال css, web font…إلى آخره، وهذا أمر جميل جدا، لأنك لن تكون مضطرا للانتظار ال parser ليبحث عن ال reference الخاصة بال external resource، بطريقة أخرى، ال HTML يبنى وال resource تُجلب!، بفهمك لهذا ستفهم الدور الكبير ل async وال defer عند استخدامها، وكيف تحسن من الأداء بشكل كبير!

  • لتقليل التعقيد في المقال، قمت بوضع الخطوات الخاصة بآلية عمل المتصفح على شكل نقاط منفصلة، لكن اعلم أن Navigation موضوع يشمل كل من ال DNS, TCP, TLS، وكذلك المواضيع التالية…، هذا التبسيط لن يغير شيء، سوى ضبط العناوين…

 

يتبع في الجزء الرابع بإذن الله…

أو مشاهدة مباشرة: