لو الزائر فتح موقعك الصبح وفتحه تاني بعد الضهر، المتصفح بيحمّل كل ملف CSS و JS و صورة من الأول. الزيارة الأولى 1.8 ثانية، والتانية نفسها 1.8 ثانية. سطرين بس في الـ response headers بيخلّوا التانية 180ms.
HTTP Cache Headers: السطر اللي بيوفّر 90% من زمن التحميل
المشكلة باختصار
كل ما المتصفح بيطلب ملف من السيرفر، بيدفع ضريبة. الضريبة دي اسمها round-trip: طلب رايح، رد جاي، DNS، TLS، اللي تيجي. حتى لو الملف 5KB بيتاخد 200ms على شبكة 4G عادية. لو صفحتك فيها 35 ملف (CSS + JS + صور + خطوط)، ده 7 ثواني انتظار شبكة بس.
السؤال البديهي: ليه المتصفح يطلب ملف انت متأكد إنه مش بيتغيّر؟ HTTP Cache Headers هي الإجابة الرسمية على السؤال ده.
مثال للمبتدئ: شنطة المدرسة
تخيّل إنك بتروح المدرسة كل يوم. اليوم الأول مكنش معاك ولا حاجة، فاشتريت الكتب والأقلام والكشاكيل. كلّفك ساعتين في المكتبة. بكره الصبح، هل هتشتري كل حاجة تاني؟ طبعًا لأ. الكتب في الشنطة عندك من امبارح، بس هتشوف لو الأستاذ غيّر الكتاب أصلاً ولا لأ.
المتصفح بيشتغل بنفس الفكرة. أول زيارة بياخد كل الملفات وبيحطها في كاش (الشنطة). الزيارة التانية بيبص في الكاش الأول. لو الـ headers اللي السيرفر بعتها بتقول "الكتاب ده ساري لمدة سنة"، بياخده من الكاش طوالي بدون ما يسأل السيرفر أصلاً.
التعريف العلمي بدقة
الـ HTTP Caching معرّف رسميًا في RFC 9111 (الإصدار الحالي من الـ HTTP Caching Specification الصادر سنة 2022). الـ RFC بيحدد طبقتين:
- Freshness (الطزاجة): متى يعتبر المتصفح إن النسخة المحلية لسه صالحة. ده بيتحدد بـ
Cache-Control: max-age. - Validation (التحقق): لما الـ freshness تنتهي، المتصفح بيسأل السيرفر "النسخة دي لسه نفسها؟" بدون ما يحمّلها كاملة. ده بيتم عبر
ETagأوLast-Modified.
الفرق المهم: في الحالة الأولى المتصفح ميتصلش بالسيرفر أصلًا. في الحالة التانية بيتصل لكن بيستلم رد فاضي حجمه ~200 بايت بدل ما يحمّل الملف بالكامل.
الـ headers الثلاثة اللي محتاج تعرفهم
1) Cache-Control: max-age
بيقول للمتصفح: "خد الملف ده وحطه في الكاش لـ X ثانية، وميسألنيش خلال المدة دي". مثال:
Cache-Control: public, max-age=31536000, immutableالرقم 31536000 = سنة بالثواني. immutable بيقول إن الملف مش هيتغيّر أبدًا تحت نفس الـ URL. ده مناسب للملفات اللي اسمها فيه hash زي app.a3f9b2.js.