Developer Tools

คู่มือ HTTP Caching: เร่งความเร็วเว็บไซต์โดยไม่ต้องเพิ่มโครงสร้างพื้นฐาน

เรียนรู้การใช้ Cache-Control headers, ETags, กลยุทธ์ CDN caching และพฤติกรรม browser cache เพื่อปรับปรุงเวลาโหลดเว็บไซต์และลดค่าใช้จ่ายเซิร์ฟเวอร์อย่างมีนัยสำคัญ

7 นาทีในการอ่าน

Server racks in a data center

Caching คือการปรับแต่งประสิทธิภาพที่คุ้มค่าที่สุดที่คุณสามารถทำได้ การตอบสนองจาก cache จะเสร็จสิ้นภายในไม่กี่ไมโครวินาที ไม่มีต้นทุน และไม่ต้องใช้ทรัพยากรเซิร์ฟเวอร์เลย แต่แอปพลิเคชันส่วนใหญ่มักจะ cache มากเกินไป (ส่งเนื้อหาที่ล้าสมัย) หรือไม่ cache เลย (สิ้นเปลืองแบนด์วิดธ์และทรัพยากร) การเข้าใจ HTTP caching จะเปลี่ยนมันจากต้นเหตุของบั๊กให้กลายเป็นเครื่องมืออันทรงพลัง

HTTP caching ทำงานอย่างไร

เมื่อ browser หรือ CDN ได้รับการตอบสนอง ระบบจะตรวจสอบ headers เพื่อตัดสินใจว่าจะ cache หรือไม่ และจะ cache ไว้นานแค่ไหน เมื่อมีการร้องขอทรัพยากรเดิมครั้งต่อไป ระบบสามารถให้บริการสำเนาที่ cache ไว้ได้ทันที โดยไม่ต้องติดต่อเซิร์ฟเวอร์เลย

วงจรชีวิตของ cache มีสองช่วง:

  1. Freshness — สำเนาที่ cache ไว้ยังใช้งานได้อยู่ไหม? กำหนดโดย Cache-Control: max-age หรือ Expires
  2. Validation — หากหมดอายุ เราสามารถยืนยันกับเซิร์ฟเวอร์ว่าเนื้อหายังไม่เปลี่ยนแปลงได้ไหม? กำหนดโดย ETag หรือ Last-Modified

Cache-Control: directive หลักสำหรับการ caching

Cache-Control คือ caching header ที่ทรงพลังที่สุด เป็นรายการ directives คั่นด้วยเครื่องหมายจุลภาค:

Cache-Control: public, max-age=31536000, immutable

Directives สำคัญ

Directive ความหมาย
public Cache ใดก็ได้ (browser, CDN, proxy) สามารถเก็บข้อมูลนี้ได้
private เฉพาะ browser ของผู้ใช้เท่านั้นที่ cache ได้ (ไม่ใช่ CDN)
no-cache ต้องยืนยันกับเซิร์ฟเวอร์ก่อนใช้งานทุกครั้ง (ไม่ได้หมายความว่า "ห้าม cache")
no-store ห้าม cache เด็ดขาด — สำหรับข้อมูลที่ละเอียดอ่อน
max-age=N Cache เป็นเวลา N วินาที
s-maxage=N max age เฉพาะ CDN (แทนที่ max-age สำหรับ shared caches)
immutable เนื้อหาจะไม่มีการเปลี่ยนแปลง — ข้ามการ revalidation ทั้งหมด
must-revalidate เมื่อหมดอายุ ต้อง revalidate ก่อนให้บริการ
stale-while-revalidate=N ให้บริการข้อมูลเก่าเป็นเวลา N วินาที ขณะดึงข้อมูลใหม่ในเบื้องหลัง

⚠️ no-cache ไม่ได้หมายความว่า "ห้าม cache" แต่หมายความว่า "cache ไว้ แต่ตรวจสอบเสมอว่ายังใช้งานได้อยู่ไหม" ใช้ no-store หากคุณไม่ต้องการให้ cache จริงๆ

กลยุทธ์การ caching ตามประเภทของทรัพยากร

ทรัพยากรแต่ละประเภทต้องการกลยุทธ์ที่แตกต่างกัน:

Static assets ที่ใช้ content hashing (CSS, JS, รูปภาพ)

Cache-Control: public, max-age=31536000, immutable

หาก build tool ของคุณเพิ่ม hash ไว้ในชื่อไฟล์ (main.a3f9b2c.js) URL จะเปลี่ยนเมื่อเนื้อหาเปลี่ยน สามารถ cache ไว้ตลอดไปได้ เพราะเวอร์ชันใหม่จะมี URL ใหม่เสมอ

HTML pages

Cache-Control: no-cache

หรือจะกำหนด TTL สั้นๆ:

Cache-Control: public, max-age=60, stale-while-revalidate=3600

HTML มีการเปลี่ยนแปลงบ่อยและลิงก์ไปยัง assets ที่มี hash ควร cache ไว้ช่วงสั้นๆ หรือบังคับให้ revalidate

API responses

# ข้อมูลสาธารณะ (เช่น แคตาล็อกสินค้า)
Cache-Control: public, max-age=300, stale-while-revalidate=600

# ข้อมูลเฉพาะผู้ใช้
Cache-Control: private, max-age=60

# ข้อมูลเรียลไทม์ (ราคาหุ้น, คะแนนสด)
Cache-Control: no-store

ข้อมูลที่ละเอียดอ่อน (การยืนยันตัวตน, การชำระเงิน)

Cache-Control: no-store

ห้าม cache ทุกกรณี

ETags และ conditional requests

เมื่อ cached response หมดอายุ browser ไม่ได้ทิ้งมันไปทันที แต่จะถามเซิร์ฟเวอร์ว่ายังใช้งานได้อยู่ไหม นี่คือ revalidation

ETags

ETag คือลายนิ้วมือของเนื้อหาที่ตอบสนอง:

# เซิร์ฟเวอร์ส่ง:
ETag: "a3f9b2c8d4e1"

# คำขอครั้งต่อไปของ browser:
If-None-Match: "a3f9b2c8d4e1"

# หากไม่มีการเปลี่ยนแปลง เซิร์ฟเวอร์ตอบสนองด้วย:
HTTP/1.1 304 Not Modified
(ไม่มี body — ประหยัดแบนด์วิดธ์)

# หากมีการเปลี่ยนแปลง เซิร์ฟเวอร์ตอบสนองด้วย:
HTTP/1.1 200 OK
ETag: "b7c2d4e9a1f3"
(การตอบสนองใหม่เต็มรูปแบบ)

การตอบสนอง 304 Not Modified ไม่มี body — มีเพียง headers เท่านั้น ซึ่งช่วยประหยัดแบนด์วิดธ์ในการดาวน์โหลดเนื้อหาซ้ำได้ทั้งหมด

Last-Modified

คล้ายกันแต่ใช้ timestamp แทน hash:

Last-Modified: Tue, 01 Apr 2026 10:00:00 GMT

# Browser ส่ง:
If-Modified-Since: Tue, 01 Apr 2026 10:00:00 GMT

ETags มีความน่าเชื่อถือมากกว่า (timestamps อาจไม่แม่นยำเมื่อใช้ load-balanced servers)

Vary header: cache แยกตามตัวแปรของคำขอ

Vary header บอก caches ว่า request headers ใดที่ส่งผลต่อการตอบสนอง:

Vary: Accept-Encoding

นี่จะ cache สำเนาแยกกันสำหรับการตอบสนองแบบ gzip และ br การใช้งานทั่วไป:

Vary: Accept-Encoding          # Cache แยกสำหรับแบบบีบอัดและไม่บีบอัด
Vary: Accept-Language          # Cache แยกตามภาษา
Vary: Accept                   # Cache แยกสำหรับการตอบสนองแบบ JSON และ HTML

⚠️ Vary: Cookie หรือ Vary: Authorization จะปิดการใช้งาน CDN caching โดยพฤตินัย เนื่องจาก CDN ไม่สามารถ cache การตอบสนองที่เฉพาะเจาะจงต่อผู้ใช้ได้

stale-while-revalidate: การรีเฟรชในเบื้องหลัง

หนึ่งในรูปแบบ caching สมัยใหม่ที่มีประโยชน์มากที่สุด:

Cache-Control: max-age=60, stale-while-revalidate=600
  • ให้บริการจาก cache ทันทีใน 60 วินาทีแรก (fresh)
  • สำหรับคำขอระหว่าง 60–660 วินาที: ให้บริการสำเนาที่หมดอายุทันที แต่ดึงเวอร์ชันใหม่ในเบื้องหลัง
  • หลัง 660 วินาที: ต้อง revalidate ก่อนให้บริการ

ผู้ใช้จะได้รับการตอบสนองที่รวดเร็วเสมอ และ cache ก็ยังคงความสดใหม่โดยไม่บังคับให้ใครต้องรอการเชื่อมต่อเครือข่าย

ข้อควรพิจารณาสำหรับ CDN caching

CDN (Cloudflare, CloudFront, Fastly) เคารพ Cache-Control headers แต่เพิ่มความซับซ้อนอีกชั้น:

  • s-maxage ช่วยให้คุณกำหนด TTL ที่แตกต่างกันสำหรับ CDN กับ browser:

    Cache-Control: public, max-age=60, s-maxage=86400
    

    Browser cache ไว้ 1 นาที; CDN cache ไว้ 24 ชั่วโมง

  • Cache purging — เมื่อคุณ deploy ให้ purge CDN cache สำหรับ assets ที่อัปเดตแล้ว CDN ส่วนใหญ่รองรับการ purging ผ่าน API

  • Cache keys — CDN จะ cache ตาม URL + Vary headers โดย query strings มักถูกรวมอยู่ใน cache key ด้วย

การทดสอบพฤติกรรมของ cache

ใช้ API Request Builder ของเราเพื่อตรวจสอบ response headers และยืนยันว่าการตั้งค่า caching ของคุณทำงานได้ถูกต้อง:

  1. ส่งคำขอและตรวจสอบ headers Cache-Control, ETag และ Last-Modified
  2. ส่งคำขอเดิมอีกครั้ง — ตรวจสอบ Age header (วินาทีนับตั้งแต่ cache) และ X-Cache: HIT
  3. ตรวจสอบ CF-Cache-Status (Cloudflare) หรือ X-Cache (CloudFront) เพื่อยืนยัน CDN caching

ใน Chrome DevTools → แท็บ Network → คลิกทรัพยากร → แท็บ Headers — ดูหา from disk cache หรือ from memory cache ในการตอบสนอง

การกำหนดค่า Nginx caching

กำหนดค่า caching headers ที่ระดับ Nginx เพื่อให้มีพฤติกรรมที่สอดคล้องกัน:

# Static assets — cache ตลอดไป
location ~* \.(js|css|woff2|png|jpg|webp|svg)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

# HTML — revalidate เสมอ
location ~* \.html$ {
    add_header Cache-Control "no-cache";
}

# API — cache สั้นพร้อม stale-while-revalidate
location /api/ {
    add_header Cache-Control "public, max-age=60, stale-while-revalidate=600";
}

ใช้ Nginx Config Generator ของเราเพื่อสร้างการกำหนดค่า Nginx ที่สมบูรณ์และเหมาะสมที่สุดสำหรับกรณีการใช้งานของคุณ

Caching checklist

  • Static assets (CSS/JS) ใช้ชื่อไฟล์แบบ content-hashed + max-age=31536000, immutable
  • HTML ให้บริการด้วย no-cache หรือ max-age ที่สั้นมาก
  • API responses ถูก cache ตามความถี่ในการอัปเดต
  • ข้อมูลที่ละเอียดอ่อนใช้ no-store
  • เปิดใช้งาน ETags หรือ Last-Modified สำหรับ conditional requests
  • ใช้ stale-while-revalidate กับ API endpoints ที่เหมาะสม
  • ยืนยันและทดสอบ CDN caching headers แล้ว

การทำ HTTP caching อย่างถูกต้องจะทำให้เว็บไซต์ของคุณรู้สึกเร็วทันทีสำหรับผู้เยี่ยมชมที่กลับมา ลดค่าใช้จ่ายด้านแบนด์วิดธ์ และลดภาระเซิร์ฟเวอร์ — ทั้งหมดนี้โดยไม่ต้องเพิ่มโครงสร้างพื้นฐานใดๆ