Cache-Control — ما هو، التوجيهات وإدارة التخزين المؤقت

المؤلف: IT Sectr نُشر: 2026-03-09 وقت القراءة: 9 دق

Cache-Control هو ترويس HTTP يحدد قواعد التخزين المؤقت للموارد على جانب العميل وخوادم الوكيل وشبكات CDN باستخدام مجموعة من التوجيهات. على عكس الترويس المتقادم Expires، يدعم Cache-Control عشرات التوليفات: يحدد max-age عمر المورد بالثواني، ويتحكمان private و public في توفر الذاكرة المؤقتة، و no-cache و no-store — التحقق الإجباري. وفقًا لـ Google Web Dev (2025)، يمكن للتكوين الصحيح لـ Cache-Control تقليص وقت تحميل الصفحات بنسبة 50-80% للزيارات المتكررة. وهذا يجعل هذا الترويس حاسمًا لأداء تطبيقات الويب والهواتف المحمولة.

النقاط الرئيسية

  • Cache-Control — ترويس HTTP مع توجيهات تتحكم في التخزين المؤقت على العميل والوكيل و CDN
  • max-age — توجيه رئيسي يحدد عمر المورد بالثواني دون إعادة التحقق
  • private vs public — private يسمح بالتخزين المؤقت على العميل فقط، public كذلك على الوكلاء و CDN
  • no-cache vs no-store — no-cache يتطلب التحقق قبل الاستخدام، no-store يمنع التخزين المؤقت بالكامل
  • s-maxage — يلغي max-age للذاكرات المؤقتة المشتركة دون التأثير على المتصفحات

ما هو Cache-Control؟

Cache-Control هو ترويس HTTP، موحد في HTTP/1.1 (RFC 7234)، يسمح للخادم بتحديد كيفية ومدة الزمن التي يمكن للعملاء والوكلاء و CDN تخزين الاستجابة مؤقتًا. على عكس Expires (HTTP/1.0)، يستخدم Cache-Control التوجيهات — أوامر نصية مدمجة بفواصل: Cache-Control: public, max-age=3600, must-revalidate. يوفر الترويس تحكمًا دقيقًا في كل حلقة في سلسلة التخزين المؤقت.

التخزين المؤقت هو آلية أساسية لأداء تطبيقات الويب والهواتف المحمولة. بدونه، كان كل طلب مستخدم يذهب مباشرة إلى الخادم، مما يسبب حملاً زائدًا وزمن استجابة طويلاً. يحدد Cache-Control ثلاثة مستويات للتخزين المؤقت: المتصفح/التطبيق (ذاكرة مؤقتة خاصة)، خوادم الوكيل (ذاكرة مؤقتة مشتركة) و CDN (ذاكرة مؤقتة موزعة). يقوم كل مستوى بتفسير التوجيهات بشكل مختلف.

تكوين Cache-Control غير الصحيح هو واحد من أكثر الأسباب شيوعًا لمشاكل الأداء. يؤدي التخزين المؤقت العدواني الزائد إلى رؤية المستخدمين لبيانات قديمة. يؤدي التخزين المؤقت الضعيف جدًا إلى طلبات زائدة للخادم وتحميل بطيء. وفقًا لـ Akamai (2025)، يقلل تحسين Cache-Control للمحتوى الثابت حمل الخادم بنسبة 70-90% ويحسن وقت التحميل بنسبة 40-60% لمستخدمي الهواتف المحمولة.

تاريخ الترويس

ظهر Cache-Control في HTTP/1.1 (RFC 2616, 1999) كبديل لـ Expires. كان لدى Expires مشكلة أساسية: كان يستخدم تاريخًا مطلقًا يعتمد على المناطق الزمنية للخادم والعميل. حل Cache-Control هذه المشكلة بالانتقال إلى الوقت النسبي (max-age بالثواني من لحظة استلام الاستجابة). لاحقًا، في RFC 7234 (2014)، تمت إضافة توجيهات جديدة: immutable للأصول الثابتة، stale-while-revalidate و stale-if-error للتحقق المؤجل.

توجيهات Cache-Control

يتضمن Cache-Control أكثر من 10 توجيهات مقسمة إلى ثلاث مجموعات: توجيهات الطلب (عميل → خادم)، توجيهات الاستجابة (خادم → عميل) والإمتدادات. في الممارسة، يستخدم تطوير الهواتف المحمولة 6-7 توجيهات استجابة رئيسية تغطي 95% من سيناريوهات التخزين المؤقت. دعنا ننظر إلى كل واحد مع أمثلة وتوصيات.

التوجيهالمعنىمثال
max-ageعمر المورد بالثواني من لحظة الاستجابةmax-age=3600 — ساعة واحدة
s-maxagemax-age للذاكرة المؤقتة المشتركة (وكيل، CDN)s-maxage=86400 — يوم واحد لـ CDN
publicيسمح بالتخزين المؤقت للجميع (بما في ذلك الوكلاء)public, max-age=3600
privateيسمح بالتخزين المؤقت فقط للمتصفح/التطبيقprivate, max-age=600
no-cacheلا تستخدم دون تحقق (304 مطلوب)no-cache
no-storeمنع التخزين المؤقت بالكاملno-store
must-revalidateبعد max-age، يجب إعادة التحقق مع الخادم الأصليmax-age=3600, must-revalidate
immutableلن يتغير المورد (للأصول الثابتة ذات الإصدار)max-age=31536000, immutable

max-age هو أهم توجيه. يمنع العميل من إرسال طلب إلى الخادم لمدة زمنية محددة. بالنسبة للأصول الثابتة (CSS، JS، صور)، يتم تعيين max-age عادة من يوم واحد إلى سنة واحدة. لاستجابات API — من 0 ثانية (بيانات جديدة دائمًا) إلى 5-10 دقائق (بيانات مرجعية). s-maxage يسمح بتعيين أعمار مختلفة لـ CDN والمتصفح: تخزن CDN نسخة لمدة يوم واحد، والمتصفح لمدة ساعة واحدة.

no-cache مقابل no-store

كثيرًا ما يتم الخلط بين هذين التوجيهين. no-cache لا يمنع التخزين المؤقت — يتطلب التحقق من النسخة المخزنة مؤقتًا عند كل استخدام من خلال طلب شرطي (If-Modified-Since أو If-None-Match). إذا استجاب الخادم بـ 304 — يستخدم العميل الذاكرة المؤقتة. إذا 200 — يقوم بتحديثها. no-store، من ناحية أخرى، يمنع تمامًا حفظ الاستجابة في أي ذاكرة مؤقتة، بما في ذلك القرص والذاكرة المؤقتة. استخدم no-store فقط للبيانات الحساسة — الرموز، بيانات الدفع، الوثائق الشخصية.

Cache-Control مقابل Expires

يحدد ترويس Expires (HTTP/1.0) أيضًا عمر المورد ولكنه يستخدم تاريخًا مطلقًا: Expires: Thu, 03 Jul 2026 12:00:00 GMT. يستخدم Cache-Control max-age وقتًا نسبيًا من لحظة الاستجابة. الفرق حاسم للأنظمة الموزعة: إذا كان الخادم والعميل في مناطق زمنية مختلفة، فقد يتم تفسير Expires بشكل غير صحيح. Cache-Control ليس لديه هذه المشكلة — 3600 ثانية هي دائمًا 3600 ثانية.

عندما يكون كلا الترويسين موجودين، يحظى Cache-Control بالأولوية على Expires. هذا محدد في RFC 7234: “إذا كانت الاستجابة تتضمن حقل Cache-Control مع توجيه max-age، فإن المستلم يجب أن يتجاهل حقل Expires.” في الممارسة، يوصى بعدم إرجاع Expires بالنسبة للعملاء الحديثين، لأن Cache-Control يغطي جميع سيناريوهات Expires. ومع ذلك، للتوافق مع الوكلاء والمتصفحات القديمة، يمكن إرجاع كلا الترويسين.

بقي Expires بشكل أساسي للمحتوى الثابت على Nginx و Apache — تقوم هذه الخوادم بإضافة كلا الترويسين تلقائيًا. إذا واجه مشروعك Expires دون Cache-Control، استبدله بـ Cache-Control مع max-age: تتحسن دقة التحكم في التخزين المؤقت، وتتلاشى الاعتمادية على المنطقة الزمنية. للترحيل، يكفي تكوين الخادم لإضافة Cache-Control بدلاً من Expires.

nginx
# Nginx: Cache-Control للملفات الثابتة
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    expires 30d;
    add_header Cache-Control "public, immutable, max-age=2592000";
}

# سياسات مختلفة لأنواع مختلفة من المحتوى
location /api/config {
    expires -1;
    add_header Cache-Control "no-cache, must-revalidate";
}

location /api/static-data {
    expires 5m;
    add_header Cache-Control "public, max-age=300";
}

في تكوين Nginx، يتم تعيين الملفات الثابتة (CSS، JS، صور) مع Cache-Control لمدة 30 يومًا باستخدام سمة immutable — تخبر هذه السمة المتصفح أن المورد لا يتغير أبدًا في هذا العنوان (إصدار عبر التجزئة في اسم الملف). تستخدم نقاط نهاية API no-cache للبيانات الديناميكية و public مع max-age قصير للبيانات المرجعية — القوائم التي يتم طلبها بشكل متكرر ونادراً ما تتغير.

التخزين المؤقت في تطبيقات الهواتف المحمولة

في تطبيقات الهواتف المحمولة، يلعب Cache-Control دورًا خاصًا بسبب قيود شبكات الهواتف المحمولة: زمن استجابة عال، اتصال غير مستقر، حدود البيانات. يسمح التخزين المؤقت الصحيح بعرض البيانات للمستخدم فورًا، حتى خارج الاتصال، وتحديثها في الخلفية. يحتوي OkHttp على Android و URLSession على iOS على أنظمة تخزين مؤقت مضمنة تحترم Cache-Control.

OkHttp يستخدم CacheInterceptor، الذي يقرأ Cache-Control من الاستجابة ويدير التخزين المؤقت تلقائيًا. إذا أرجع الخادم Cache-Control: max-age=3600، فلن يرسل OkHttp طلبًا إلى الخادم لمدة ساعة. بعد انتهاء max-age، يرسل OkHttp طلبًا شرطيًا مع If-Modified-Since و If-None-Match. تكوين الذاكرة المؤقتة في OkHttp: OkHttpClient.Builder().cache(Cache(directory, maxSize)).

kotlin
fun createCachedClient(cacheDir: File): OkHttpClient {
    return OkHttpClient.Builder()
        .cache(Cache(cacheDir, 10L * 1024 * 1024))
        .addNetworkInterceptor { chain ->
            val response = chain.proceed(chain.request())
            response.newBuilder()
                .header("Cache-Control",
                    "public, max-age=300")
                .removeHeader("Pragma")
                .build()
        }
        .build()
}

يقوم الكود بإنشاء OkHttpClient بذاكرة مؤقتة سعتها 10 ميغابايت ويلغي Cache-Control من خلال NetworkInterceptor. إذا لم يرجع الخادم Cache-Control أو يستخدم Expires، يضيف المعاوض public, max-age=300 (5 دقائق). يقوم المعاوض بإزالة الترويس القديم Pragma (HTTP/1.0) للتوافق. يعمل التخزين المؤقت على iOS بشكل مماثل من خلال URLCache.shared مع إعدادات memoryCapacity و diskCapacity.

الوضع غير المتصل و stale-while-revalidate

يسمح التوجيه stale-while-revalidate بعرض ذاكرة مؤقتة قديمة للمستخدم بينما يقوم التطبيق بتحميل بيانات جديدة في الخلفية. يوفر هذا تأثير استجابة فورية: يرى المستخدم المحتوى فورًا، وبعد ثانية يتحدث إلى الإصدار الحالي. مدعوم في OkHttp منذ الإصدار 3.10 و URLCache على iOS 14+. مثال: Cache-Control: max-age=3600, stale-while-revalidate=300 — ساعة واحدة من الذاكرة المؤقتة الحديثة، ثم 5 دقائق من عرض البيانات القديمة مع تحديث خلفية.

أمثلة تكوين Cache-Control

تتطلب أنواع الموارد المختلفة استراتيجيات مختلفة للتخزين المؤقت. دعنا ننظر إلى التكوينات المثلى للسيناريوهات النموذجية في تطوير الهواتف المحمولة. بالنسبة للمحتوى الثابت باستخدام تجزئة في اسم الملف (bundle.abc123.js)، يمكنك تعيين max-age حتى سنة واحدة مع immutable. لقوائم API التي نادرًا ما يتم تحديثها (الأدلة، الفئات) — max-age من 5 دقائق إلى ساعة واحدة مع stale-while-revalidate.

نوع الموردCache-Controlشرح
أصول ثابتة مزودة بإصدارpublic, max-age=31536000, immutableسنة واحدة، الملفات لا تتغير (تجزئة في URL)
أصول ثابتة غير مزودة بإصدارpublic, max-age=86400, must-revalidateيوم واحد مع إعادة تحقق إجبارية بعدها
API: بيانات مرجعيةpublic, max-age=600, stale-while-revalidate=6010 دقائق ذاكرة مؤقتة + دقيقة قديمة
API: بيانات المستخدمprivate, max-age=60دقيقة واحدة، فقط لمستخدم محدد
API: بيانات حساسةno-storeمنع كامل للتخزين المؤقت
صفحات HTMLno-cache, must-revalidateالتحقق عند كل طلب، 304 إذا لم يتغير

من المهم تذكر الأمان: للاستجابات التي تحتوي على بيانات شخصية للمستخدم، قم دائمًا بتعيين private. بدون هذا التوجيه، يمكن لوكيل عام (على سبيل المثال، مؤسسي) تخزين الاستجابة مؤقتًا وتسليمها لمستخدم آخر. لرموز المصادقة ومعلومات الدفع، استخدم no-store — حتى الذاكرة المؤقتة الخاصة لا يجب أن تخزن هذه البيانات على القرص.

تصحيح التخزين المؤقت

للتحقق من صحة Cache-Control، استخدم الترويس Age (ما مدة تخزين الذاكرة المؤقتة بالثواني) و X-Cache (hit/miss على CDN). في المتصفح — علامة التبويب Network، يظهر العمود Size “from disk cache” أو “304 Not Modified”. إذا كان يجب تخزين المورد مؤقتًا ولكنه يتم تحميله في كل مرة، تحقق مما إذا كان الخادم يضيف Cache-Control: no-cache أو Pragma: no-cache مع توجيهاتك.

الأسئلة الشائعة

ما الفرق بين max-age و s-maxage؟

يطبق max-age على جميع الذاكرات المؤقتة (بما في ذلك المتصفحات)، ويطبق s-maxage فقط على الذاكرات المؤقتة المشتركة (الوكلاء، CDN). إذا تم تحديد s-maxage، فإن CDN تتجاهل max-age وتستخدم s-maxage. يسمح هذا بتعيين أعمار مختلفة للمتصفح و CDN.

هل يمكن إلغاء التخزين المؤقت بعد إرسال Cache-Control؟

لا، بعد إرسال استجابة مع max-age، لن يقوم العميل بإرسال طلب حتى ينتهي المؤقت. لإبطال الذاكرة المؤقتة فورًا، تحتاج إلى تغيير URL المورد (إضافة إصدار/تجزئة) وإرسال إشعارات push أو رسائل WebSocket للإعادة التعيين الإجباري.

ما هي توجيه immutable؟

تخبر توجيه immutable (RFC 8246) المتصفح أن المورد لن يتغير أبدًا في هذا العنوان. لا يحاول المتصفح حتى إرسال طلب شرطي عند تحديث الصفحة — يستخدم الذاكرة المؤقتة حتى انتهاء max-age. تعمل فقط مع الملفات ذات الإصدار.

كيف يؤثر Cache-Control على تحسين محركات البحث SEO؟

يأخذ Googlebot في الاعتبار Cache-Control: يسرع التخزين المؤقت الطويل الزحف المتكرر. noindex مع ذاكرة مؤقتة سريعة لا بأس به. يمكن لـ no-store أن يبطئ الفهرسة لأن Googlebot سيقوم بتحميل الصفحة من البداية في كل مرة. يزيد max-age القصير جدًا من حمل الخادم أثناء الزحف.

كيف يتم تكوين Cache-Control في Express.js؟

من خلال helmet أو middleware: res.set('Cache-Control', 'public, max-age=3600'). للملفات الثابتة، استخدم express.static مع وسيط maxAge: express.static('public', {maxAge: '1y'}). للمسارات الديناميكية — فرديًا في كل معالج.

الملخص

  • Cache-Control — ترويس HTTP الرئيسي لإدارة التخزين المؤقت بنظام توجيهات مرن
  • max-age — عمر المورد بالثواني من لحظة الاستجابة؛ توجيه رئيسي لجميع سيناريوهات التخزين المؤقت
  • private vs public — private فقط للعميل، public للوكلاء و CDN؛ يؤثر على أمان البيانات
  • no-cache يتطلب التحقق، no-store يمنع التخزين المؤقت بالكامل؛ أغراض مختلفة، لا تخلط بينهما
  • s-maxage — يلغي max-age للذاكرات المؤقتة المشتركة، مفيد لتقسيم سياسات المتصفح/CDN
  • stale-while-revalidate — عرض ذاكرة مؤقتة قديمة مع تحديث خلفي لتجربة فورية
  • توصية — قم بتكوين Cache-Control لكل نوع مورد على الخادم وفي عميل HTTP المحمول

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا