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 — 1 ชั่วโมง
s-maxagemax-age สำหรับแคชร่วม (โพรกซี, 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 ต้องตรวจสอบกับแหล่งต้นทาง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 เก็บสำเนาไว้ 1 วัน, เบราว์เซอร์เก็บไว้ 1 ชั่วโมง

no-cache vs no-store

คำสั่งสองนี้มักถูกสับสน no-cache ไม่ได้ห้ามแคช — มันต้องการ ตรวจสอบ สำเนาที่เก็บไว้ในแคชทุกครั้งที่ใช้ผ่านคำขอแบบมีเงื่อนไข (If-Modified-Since หรือ If-None-Match) หากเซิร์ฟเวอร์ตอบด้วย 304 — ไคลเอ็นต์ใช้แคช หาก 200 — มันอัปเดต no-store ในทางกลับกัน ห้ามไม่ให้เก็บคำตอบในแคชใดๆ รวมถึงแผ่นดิสก์และหน่วยความจำ ใช้ no-store เฉพาะสำหรับข้อมูลที่อ่อนไหว — โทเคน, ข้อมูลการชำระเงิน, เอกสารส่วนบุคคล

Cache-Control vs 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: คำสั่งควบคุมแคชสำหรับไฟล์คงที่
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 MB และแทนที่ 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 — 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 นาทีที่ล้าสมัย
API: ข้อมูลผู้ใช้private, max-age=601 นาที, เฉพาะสำหรับผู้ใช้รายใดรายหนึ่ง
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) บอกเบราว์เซอร์ว่าทรัพยากร จะไม่เปลี่ยนแปลงเลย ที่ 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'}) สำหรับเส้นทางไฮนามิก — แยกต่างหากใน แต่ละตัวจัดการ

สรุป

  • Cache-Control — ส่วนหัว HTTP หลักสำหรับการจัดการแคชด้วยระบบคำสั่งที่ยืดหยุ่น
  • max-age — อายุเป็นวินาทีนับตั้งแต่ช่วงที่ได้รับคำตอบ; คำสั่งหลักสำหรับทุกสถานการณ์แคชวิง
  • private vs public — private เฉพาะสำหรับไคลเอ็นต์, public สำหรับโพรกซีและ CDN; ส่งผลต่อความปลอดภัยของข้อมูล
  • no-cache ต้องการตรวจสอบ, no-store ห้ามแคชโดยสิ้นเชิง; วัตถุประสงค์ต่างกัน อย่าสับสน
  • s-maxage — แทนที่ max-age สำหรับแคชร่วม, มีประโยชน์สำหรับแบ่งนโยบายเบราว์เซอร์/CDN
  • stale-while-revalidate — แสดงแคชที่ล้าสมัยพร้อมรีเฟรชในพื้นหลังสำหรับ UX ทันที
  • คำแนะนำ — กำหนดค่า Cache-Control สำหรับทรัพยากรแต่ละประเภทบนเซิร์ฟเวอร์และในไคลเอ็นต์ HTTP มือถือ

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม