تحسين وقت HTML حتى البايت الأول

بقلم باتريك مينان

الوقت إلى البايت الأول (TTFB) للموقع هو الوقت الذي يبدأ فيه المستخدم في التنقل حتى يبدأ وصول HTML للصفحة التي طلبها. لقد كان TTFB البطيء لعنة وجودي لأكثر من عشر سنوات كنت أقوم فيها بتشغيل WebPageTest.

هناك سبب لظهور TTFB كواحد من “الدرجات” القليلة التي يسجل WebPageTest موقعًا عليها ، وعلى وجه التحديد ، سبب كونه الدرجة الأولى في القائمة.

إذا كان البايت الأول بطيئًا ، فسيكون كل مقياس آخر بطيئًا أيضًا. يعد تحسينه أحد الحالات القليلة التي يمكنك فيها التنبؤ بما سيكون التأثير على كل قياس آخر. يُترجم كل تحسين بالمللي ثانية في TTFB مباشرةً إلى توفير ميلي ثانية في كل قياس آخر (أي أن الطلاء الأول سيكون أسرع بمقدار 500 مللي ثانية إذا تحسن TTFB بمقدار 500 مللي ثانية). ومع ذلك ، فإن ttfb السريع لا يضمن تجربة سريعة ولكن ttfb البطيء يضمن تجربة بطيئة. أقدر أن ما يقرب من 50٪ من جميع طلبات المساعدة في نتائج اختبار WebPageTest تأتي من مالكي المواقع الذين يعانون من مشكلة بطيئة في TTFB.

يمكن إدراج العديد من الأشياء في TTFB ، بما في ذلك عمليات إعادة التوجيه ونظام أسماء النطاقات وإعداد الاتصال ومفاوضات SSL ووقت استجابة الخادم الفعلي. يمكن إصلاح معظمها بسهولة نسبيًا باستخدام خدمة مثل Cloudflare ، لكن وقت استجابة الخادم لـ HTML نفسه غالبًا ما يكون المشكلة الأكبر والأصعب في الحل.

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

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

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

ذاكرة التخزين المؤقت لـ HTML

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

هناك حالات خاصة مثل تسجيل دخول المستخدم (كمسؤول أو غير ذلك) حيث يجب أن يختلف المحتوى ولكن الغالبية العظمى من الزيارات تكون لمستخدمين مجهولين. إذا كان من الممكن تخزين HTML مؤقتًا وعرضه مباشرة من الحافة ، فيمكن أن تكون مكاسب الأداء كبيرة (أكثر من 3 ثوانٍ أسرع على جميع المقاييس في هذه الحالة).

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

يدعم Cloudflare التخزين المؤقت بتنسيق HTML الثابت ، ويمكن لعملاء الشركات والمؤسسات تمكين المستخدمين المسجلين من تخطي ذاكرة التخزين المؤقت عن طريق تمكين “تجاوز ذاكرة التخزين المؤقت على ملفات تعريف الارتباط”. إنه يعمل جنبًا إلى جنب مع المكون الإضافي Cloudflare لبرنامج WordPress بحيث يمكن مسح ذاكرة التخزين المؤقت عند تحديث المحتوى. هناك أيضًا العديد من المكونات الإضافية الأخرى للتخزين المؤقت التي تتكامل مع العديد من شبكات CDN ولكن في جميع الحالات ، يجب تهيئتها باستخدام مفاتيح واجهة برمجة التطبيقات لشبكة CDN وعمليات التنفيذ محددة لكل CDN.

Zero-Config Edge Caching لـ HTML

للتبني على نطاق واسع ، نحتاج إلى جعل التخزين المؤقت لـ HTML يحدث تلقائيًا (أو أقرب ما يكون تلقائيًا قدر الإمكان). لتحقيق هذه الغاية ، نحتاج إلى طريقة للتواصل بين الأصل (مثل موقع WordPress) وذاكرة التخزين المؤقت للحافة (مثل عُقد الحافة في Cloudflare) لإدارة ذاكرة التخزين المؤقت عن بُعد التي يمكن إزالتها صراحة.

يجب أن يكون Origin قادرًا على:

بدلاً من مطالبة الأصل بالتكامل مع واجهة برمجة التطبيقات لتطهير التغييرات والمطالبة بتكوين يدوي لما يتم تخزينه مؤقتًا عندما يمكننا إنجاز كل شيء باستخدام رؤوس HTTP في الطلبات التي تنتقل ذهابًا وإيابًا بين الحواف والأصل:

1 – تتم إضافة رأس HTTP إلى الطلبات التي تنتقل من الحافة إلى الأصل للإعلان عن وجود ذاكرة تخزين مؤقت للحافة والإمكانيات التي يدعمها:

2 – عندما يستجيب الأصل بصفحة قابلة للتخزين المؤقت ، فإنه يضيف رأس HTTP على الاستجابة للإشارة إلى أنه يجب تخزينه مؤقتًا وأية قواعد تتعلق بوقت عدم استخدام النسخة المخبأة (للسماح بتجاوز ذاكرة التخزين المؤقت للملفات المسجلة -في المستخدمين):

في هذه الحالة ، سيتم تخزين HTML مؤقتًا ولكن أي طلبات تحتوي على ملفات تعريف ارتباط تبدأ بـ “wordpress” أو “wp-” لاسم ملف تعريف الارتباط ستتجاوز ذاكرة التخزين المؤقت وتنتقل إلى الأصل.

3 – عندما يقوم طلب بتعديل محتوى الموقع (تحديث منشور ، وتغيير سمة ، وإضافة تعليق) يضيف الأصل رأس استجابة HTTP يشير إلى ضرورة إزالة ذاكرة التخزين المؤقت:


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

4 – عندما يأتي طلب جديد لـ HTML الموجود في ذاكرة التخزين المؤقت للحافة ، يتم التحقق من ملفات تعريف الارتباط للطلب مقابل قواعد الاستجابة المخزنة مؤقتًا. إذا لم تكن ملفات تعريف الارتباط موجودة ، فسيتم تقديم النسخة المخبأة ؛ خلافًا لذلك ، يتم تمرير الطلب إلى الأصل.

باستخدام واجهة التحكم والأوامر البسيطة المبنية على الرأس ، يمكننا التخلص من الحاجة إلى أن يتحدث الأصل إلى واجهة برمجة التطبيقات وأي تكوين صريح. كما أنه يجعل المنطق المتعلق بالأصل أسهل في التنفيذ نظرًا لعدم وجود تكوين (أو واجهة مستخدم) ولا حاجة لتقديم أي طلبات صادرة إلى واجهة برمجة تطبيقات خاصة بالبائع. المثال الإضافي لبرنامج WordPress هو أقل من 50 سطرًا من التعليمات البرمجية والغالبية العظمى من ذلك هو ربط عمليات رد الاتصال لجميع الأحداث التي تغير المحتوى.

ابدأ التخزين المؤقت اليوم مع WordPress والعاملين

من أكثر الأشياء التي أحبها في “العمال” أنها تمنحك ميزة قابلة للبرمجة بالكامل لتجربة الأفكار وتنفيذ منطقك الخاص. لقد أنشأت برنامجًا نصيًا لـ Worker ينفذ البروتوكول المستند إلى الرأس والتخزين المؤقت للحافة على حواف Cloudflare ومكوِّن WordPress الإضافي الذي ينفذ منطق الأصل لـ WordPress.

كان الجزء الصعب الوحيد مع العامل هو إيجاد طريقة لإزالة العناصر من ذاكرة التخزين المؤقت بشكل عام. تكون ذاكرات التخزين المؤقت لـ Worker محلية لكل حافة ولا توفر واجهة للقيام بأي عمليات عالمية. تتمثل إحدى طرق القيام بذلك في استخدام Cloudflare API لتطهير ذاكرة التخزين المؤقت العالمية ، لكن هذا يعد بمثابة مطرقة ثقيلة (تطهير كل شيء من ذاكرة التخزين المؤقت بما في ذلك البرامج النصية والصور) ويتطلب بعض التكوين. إذا كنت تعرف عناوين URL المحددة التي سيتم تغييرها عن طريق تغيير المحتوى ، فمن المحتمل أن يكون إجراء مسح مستهدف من خلال واجهة برمجة التطبيقات لعناوين URL هذه فقط هو الحل الأفضل.

باستخدام متجر Workers KV الجديد ، يمكننا تطهير ذاكرة التخزين المؤقت بطريقة مختلفة. يستخدم البرنامج النصي العامل نظام إصدار لذاكرة التخزين المؤقت حيث يتم إلحاق رقم إصدار لكل عنوان URL به (على سبيل المثال ، http://www.example.com/؟cf_edge_cache_ver=32). يتم استخدام عنوان URL المعدل محليًا فقط من قبل العامل كمفتاح للاستجابات المخزنة مؤقتًا ويتم تخزين رقم الإصدار الحالي في KV وهو متجر عالمي. عندما يتم مسح ذاكرة التخزين المؤقت ، يتم زيادة رقم الإصدار مما يؤدي إلى تغيير عنوان URL لجميع الموارد. ستخرج الإدخالات القديمة من ذاكرة التخزين المؤقت بشكل طبيعي نظرًا لأنه لن يتم الوصول إليها بعد الآن. يتطلب الأمر تكوينًا بسيطًا لإعداد KV للعامل ولكن نأمل في وقت ما في المستقبل أن يكون ذلك تلقائيًا أيضًا.

ماذا بعد ذلك؟

أعتقد أن هناك قيمة كبيرة للويب في توحيد طريقة للتخزين المؤقت للمحتوى الديناميكي والأصول للتواصل من أجل التخزين المؤقت للمحتوى الديناميكي. من شأن ذلك أن يوفر حافزًا لأنظمة إدارة المحتوى لبناء الدعم مباشرةً في الأنظمة الأساسية وتوفير واجهة قياسية يمكن استخدامها عبر موفرين مختلفين (وحتى لذاكرة التخزين المؤقت المحلية في موازنات التحميل أو الوكلاء العكسيين الآخرين). بعد إجراء المزيد من الاختبارات مع أنواع مختلفة من المواقع ، أخطط لتقديم المفهوم إلى مجموعة عمل HTTP التابعة لـ IETF لمعرفة ما إذا كان بإمكاننا التوصل إلى معيار رسمي لرؤوس التحكم (باستخدام أسماء مختلفة). إذا كانت لديك آراء حول كيفية عملها أو الميزات التي تحتاج إلى كشفها ، فأنا أحب أن أسمع عنها (مثل إزالة عناوين URL معينة ، وتغيير المحتوى للجوال / سطح المكتب أو المنطقة ، وتوسيعه ليشمل جميع أنواع المحتوى ، إلخ) .

نُشرت في الأصل على blog.cloudflare.com في 24 كانون الأول (ديسمبر) 2018.