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 را برای کش‌های مشترک (shared) لغو می‌کند، بدون تأثیر بر مرورگرها

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 سه سطح کشینگ را تعیین می‌کند: مرورگر/برنامه (private cache)، پروکسی‌ها (shared cache) و CDN (distributed cache). هر سطح دستورات را به شکل خود تفسیر می‌کند.

تنظیم نادرست 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 — 1 ساعت
s-maxagemax-age برای shared cache (پروکسی، CDN)s-maxage=86400 — 1 روز برای CDN
publicاجازه کشینگ به همه (شامل پروکسی)public, max-age=3600
privateکش فقط برای مرورگر/برنامهprivate, max-age=600
no-cacheبدون بازرسی استفاده نکنید (304 اجباری)no-cache
no-storeممنوعیت کامل کشینگno-store
must-revalidateپس از max-age باید از origin بازرسی شودmax-age=3600, must-revalidate
immutableمنبع تغییر نمی‌کند (برای استاتیک نسخه‌بندی شده)max-age=31536000, immutable

max-age — مهم‌ترین دستور است. آن دسترسی کلینت را به سرور برای مدت زمان مشخصی ممنوع می‌کند. برای محتوای استاتیک (CSS، JS، تصاویر) max-age معمولاً از 1 روز تا 1 سال تنظیم می‌شود. برای پاسخ‌های 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 قرار داده می‌شود — این ویژگی به مرورگر اطلاع می‌دهد که منبع هرگز تحت این URL تغییر نمی‌کند (نسخه‌بندی از طریق هش در نام فایل). اندپوینت‌های 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 به کاربر اجازه می‌دهد کش کهنه (stale) را مشاهده کند در حالی که برنامه در پس‌زمینه داده‌های تازه را بارگیری می‌کند. این اثر پاسخ فوری را ایجاد می‌کند: کاربر محتوا را فوراً می‌بیند و پس از یک ثانیه به‌روز می‌شود. توسط OkHttp از نسخه 3.10 و URLCache در iOS 14+ پشتیبانی می‌شود. مثال: Cache-Control: max-age=3600, stale-while-revalidate=300 — 1 ساعت کش فعال، سپس 5 دقیقه نمایش کش کهنه با به‌روزرسانی پس‌زمینه.

نمونه‌های تنظیم Cache-Control

انواع مختلف منابع به راهبردهای کشینگ متفاوتی نیاز دارند. پیکربندی‌های بهینه را برای سناریوهای معمولی در توسعه موبایل بررسی می‌کنیم. برای محتوای استاتیک با هش در نام فایل (bundle.abc123.js) می‌توان max-age را تا 1 سال با immutable تنظیم کرد. برای لیست‌های API که به ندرت به‌روز می‌شوند (کاتالوگ‌ها، دسته‌بندی‌ها) — max-age از 5 دقیقه تا 1 ساعت با stale-while-revalidate.

نوع منبعCache-Controlتوضیح
استاتیک نسخه‌بندی‌شدهpublic, max-age=31536000, immutable1 سال، فایل‌ها تغییر نمی‌کنند (هش در URL)
استاتیک نسخه‌بندی نشدهpublic, max-age=86400, must-revalidate1 روز با بازرسی اجباری پس از
API: داده‌های مرجعpublic, max-age=600, stale-while-revalidate=6010 دقیقه کش + 1 دقیقه stale
API: داده‌های کاربریprivate, max-age=601 دقیقه، فقط برای کاربر مشخص
API: داده‌های حساسno-storeممنوعیت کامل کشینگ
صفحات HTMLno-cache, must-revalidateبازرسی در هر درخواست، 304 در صورت بدون تغییر

مهم است در مورد امنیت به یاد داشته باشید: برای پاسخ‌هایی که شامل داده‌های شخصی کاربر هستند، همیشه private تنظیم کنید. بدون این دستور، پروکسی عمومی (مثل سازمانی) می‌تواند پاسخ را کش کند و آن را به کاربر دیگری بدهد. برای توکن‌های احراز هویت و اطلاعات پرداخت از no-store استفاده کنید — حتی کش private هم نباید این داده‌ها را روی دیسک ذخیره کند.

اشکال‌زدایی کشینگ

برای بررسی صحت 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 فقط برای shared cache (پروکسی و CDN). اگر s-maxage مشخص شده باشد، CDN max-age را نادیده گرفته و از s-maxage استفاده می‌کند. این امکان را می‌دهد زمان عمر متفاوتی برای مرورگر و CDN تعیین کنید.

آیا می‌توان پس از ارسال Cache-Control کشینگ را لغو کرد؟

خیر، پس از ارسال پاسخ با max-age، کلینت تا پایان تایمر درخواستی ارسال نخواهد کرد. برای ابطال فوری کش باید URL منبع را تغییر دهید (نسخه/هش اضافه کنید) و اعلام‌های push یا پیام‌های WebSocket برای بازنشانی اجباری ارسال کنید.

دستور immutable چیست؟

دستور immutable (RFC 8246) به مرورگر اطلاع می‌دهد که منبع هرگز تحت این URL تغییر نخواهد کرد. مرورگر حتی در بازگشت صفحه درخواست شرطی نمی‌فرستد — تا پایان 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'}). برای مسیرهای دینامیک — به صورت جداگانه در هر handler.

نتایج

  • Cache-Control — هدر اصلی HTTP برای مدیریت کشینگ با سیستم دستور انعطاف‌پذیر
  • max-age — زمان عمر به ثانیه از لحظه پاسخ؛ دستور کلیدی برای همه سناریوهای کشینگ
  • private vs public — private فقط برای کلینت، public برای پروکسی و CDN؛ بر امنیت داده تأثیر می‌گذارد
  • no-cache بازرسی می‌خواهد، no-store کش را کاملاً ممنوع می‌کند؛ کاربردهای مختلف، اشتباه نگیرید
  • s-maxage — max-age را برای shared cache لغو می‌کند، برای جداسازی سیاست‌های مرورگر/CDN مفید است
  • stale-while-revalidate — نمایش کش کهنه با به‌روزرسانی پس‌زمینه برای UX فوری
  • توصیه — Cache-Control را برای هر نوع منبع در سرور و کلینت HTTP موبایل تنظیم کنید

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید