Cache-Control Header Generator: สร้าง Header แคชที่แม่นยำในไม่กี่นาที
เรียนรู้วิธีใช้ Cache-Control Header Generator ฟรี ประกอบ directive อย่าง max-age, s-maxage, immutable และ stale-while-revalidate พร้อมส่งออกสนิปเป็ต nginx, Apache และ Express.js ที่พร้อมใช้งานทันที
Table of Contents
Cache-Control Header Generator: สร้าง Header แคชที่แม่นยำในไม่กี่นาที
การแคช (caching) คือตัวเร่งประสิทธิภาพที่ทรงพลังที่สุดตัวหนึ่งที่คุณใช้ได้โดยไม่ต้องแตะโค้ดฝั่งแอปพลิเคชันแม้แต่บรรทัดเดียว Cache-Control header ที่ตั้งค่ามาอย่างดีสามารถเปลี่ยนการตอบกลับที่ใช้เวลา 300 มิลลิวินาทีจาก origin ให้กลายเป็นการตอบกลับแบบเกือบทันทีจากหน่วยความจำของเบราว์เซอร์ และยังช่วยลดค่า CDN egress ได้อย่างชัดเจนในเวลาเดียวกัน แต่ไวยากรณ์ของ directive นั้นผิดพลาดง่ายมาก เครื่องหมายจุลภาควางผิดที่ หรือสับสนระหว่าง no-cache กับ no-store แค่จุดเดียว ผลลัพธ์คือผู้ใช้เห็นคอนเทนต์เก่า หรือเซิร์ฟเวอร์ถูกยิงด้วย request ที่ไม่ควรออกจากเบราว์เซอร์เลย
Cache-Control Header Generator ช่วยขจัดการเดาทั้งหมด แทนที่จะต้องจำ semantics ของ RFC 7234 คุณเพียงสลับชุด toggle ที่ชัดเจน — public หรือ private, max-age, s-maxage, immutable, stale-while-revalidate, stale-if-error, must-revalidate และอื่น ๆ — แล้วดูสตริง header ถูกประกอบขึ้นแบบเรียลไทม์ เมื่อพอใจกับผลลัพธ์ เครื่องมือจะส่งมอบสนิปเป็ตคอนฟิกที่พร้อมวางทั้งสำหรับ nginx, Apache และ Express.js ทำให้พอลิซีที่คุณออกแบบคือพอลิซีที่ถูก deploy จริง ทุกอย่างทำงานฝั่งไคลเอนต์ 100% จึงไม่มีข้อมูลใด ๆ ของโครงสร้างพื้นฐานคุณออกจากเครื่อง
คู่มือนี้จะพาไล่วิธีใช้เครื่องมือ อธิบายว่า directive ตัวไหนสำคัญจริงใน production และมอบสูตรสำเร็จ 3 แบบสำหรับ hashed assets, เอกสาร HTML และ JSON API
ทำไมต้องใช้ Cache-Control Header Generator?
- ไม่มีข้อผิดพลาดด้านไวยากรณ์. ลำดับ directive ตำแหน่งจุลภาค และรูปแบบค่าถูกจัดการให้ทั้งหมด สตริงที่คัดลอกออกมาเป็น HTTP ที่ถูกต้องเสมอ
- เรียนรู้ไปพร้อมกับสร้าง. ทุก toggle แมปกับ directive จริงตาม RFC ทำให้เครื่องมือนี้เป็นวิธีเรียนรู้ caching semantics ที่ดีเยี่ยม แทนการคัดลอกคอนฟิกปริศนาจาก Stack Overflow
- รองรับทุกเซิร์ฟเวอร์. พอลิซีเดียวกันถูกเรนเดอร์เป็นบล็อก add_header ของ nginx, directive Header set ของ Apache และ middleware ของ Express.js — เลือกใช้ตามสแตกที่ทีมถนัด
- ครอบคลุม directive ยุคใหม่ครบชุด. นอกจากพื้นฐาน ยังมี s-maxage, immutable, stale-while-revalidate, stale-if-error, must-revalidate และ proxy-revalidate — ตัวที่แยกระหว่างการตั้งค่า CDN ระดับดีกับระดับยอดเยี่ยม
- ทดสอบ what-if ได้ทันที. สลับ toggle แล้วเห็น header เปลี่ยนทันที เปรียบเทียบพอลิซี 60 วินาทีกับพอลิซี immutable หนึ่งปีได้ในไม่กี่วินาที
- เป็นส่วนตัวและฟรี. ทุกการคำนวณเกิดขึ้นในเบราว์เซอร์ ไม่มีบัญชี ไม่มีการอัปโหลด และไม่จำกัดการใช้งาน
ฟีเจอร์หลัก
| ฟีเจอร์ | สิ่งที่ทำ |
|---|---|
| Toggle/directive builder | เปิดปิด public, private, no-cache, no-store, max-age, s-maxage, must-revalidate, proxy-revalidate, immutable, stale-while-revalidate และ stale-if-error ได้ |
| พรีวิว header แบบเรียลไทม์ | สตริง Cache-Control ที่ประกอบแล้วอัปเดตทุกครั้งที่สลับ พร้อมคัดลอกทันที |
| สนิปเป็ต nginx | ส่งออกบล็อก add_header ที่วางลง server หรือ location ได้เลย |
| สนิปเป็ต Apache | ส่งออกบรรทัด Header set สำหรับ .htaccess หรือคอนฟิก vhost |
| สนิปเป็ต Express.js | ส่งออก middleware ที่ตั้ง header ให้ทุก response ที่ตรงเงื่อนไข |
| ทำงานฝั่งไคลเอนต์ 100% | ไม่มีข้อมูลถูกส่งไปเซิร์ฟเวอร์ เครื่องมือใช้งานออฟไลน์ได้เมื่อโหลดแล้ว |
สามรายละเอียดที่ทำให้ผลลัพธ์ใช้งานได้จริงเป็นพิเศษ:
- สนิปเป็ตสะท้อน header ตรงเป๊ะ สิ่งที่พรีวิวคือสิ่งที่เซิร์ฟเวอร์จะส่งออก ไม่มีความต่างแอบแฝงระหว่างการออกแบบกับการ deploy
- ค่าตัวเลขแก้ไขได้ ตั้ง max-age=31536000 ให้ bundle ที่มี hash หรือ max-age=0 ให้ HTML ที่ต้อง revalidate เสมอ ด้วยอินเทอร์เฟซเดียวกัน
- ชุด directive ครอบคลุมทั้งเบราว์เซอร์และ CDN จึงได้พอลิซีที่สอดคล้องกันทั้งสองเลเยอร์ในรอบเดียว แทนที่จะได้สองพอลิซีที่ขัดแย้งกัน
วิธีใช้งานทีละขั้นตอน
- เปิดเครื่องมือ. เข้าไปที่ Cache-Control Header Generator — ไม่ต้องสมัครสมาชิก
- เลือกกลุ่มผู้รับ. เลือก public หาก CDN และพร็อกซีแคช response ได้ หรือ private หากเป็นข้อมูลเฉพาะผู้ใช้ และเลือก no-store แทนสำหรับ response ที่อ่อนไหวจนต้องไม่ถูกแคชที่ใดเลย
- ตั้งค่าความสดใหม่. กรอกค่า max-age สำหรับเบราว์เซอร์ และหากมี CDN อยู่หน้า origin ให้กรอก s-maxage สำหรับ shared cache ด้วย หน่วยเป็นวินาที: 60 คือหนึ่งนาที 86400 คือหนึ่งวัน 31536000 คือหนึ่งปี
- เพิ่ม directive ด้านความปลอดภัยและความทนทาน. เปิด must-revalidate เพื่อห้ามเสิร์ฟของเก่าหลังหมดอายุ immutable สำหรับ asset ที่มี hash และไม่มีวันเปลี่ยน และ stale-while-revalidate หรือ stale-if-error เพื่อให้แคชเสิร์ฟของเก่าได้ระหว่าง revalidate หรือช่วง origin ล่ม
- คัดลอกผลลัพธ์. ตรวจสตริง header แบบเรียลไทม์ แล้วคัดลอกสนิปเป็ต nginx, Apache หรือ Express.js ไปวางในคอนฟิกของคุณและ deploy
Directive ที่สำคัญและควรรู้จริง ๆ
การแคชเกิดขึ้นในสองที่ที่แตกต่างกัน และการเข้าใจจุดแบ่งนี้คือกุญแจของทุกพอลิซีที่ดี
แคชเบราว์เซอร์กับ Shared CDN Cache ต่างกันอย่างไร
แคชเบราว์เซอร์เป็นส่วนตัวของอุปกรณ์เครื่องเดียว ส่วนแคช CDN (shared cache) ถูกใช้ร่วมกันโดยผู้ใช้ทุกคนที่เข้ามาที่ edge node นั้น และแต่ละเลเยอร์มี directive ของตัวเอง max-age=60 บอกเบราว์เซอร์ให้ใช้ response ซ้ำได้หกสิบวินาที ส่วน s-maxage=600 บอก shared cache ให้เก็บไว้สิบนาที และจะชนะ max-age ทุกครั้งที่ shared cache เป็นผู้จัดเก็บ การตั้งค่าทั้งคู่แยกกันทำให้ HTML อยู่บน CDN ได้สั้น ๆ ขณะที่เบราว์เซอร์ถือว่าสดเสมอ หรือให้ API สาธารณะถูกแคชที่ edge อย่างเข้มข้นแต่อุปกรณ์แคชแบบประหยัด ๆ
immutable สำหรับ Hashed Assets
immutable บอกเบราว์เซอร์ว่า resource จะไม่เปลี่ยนตลอดช่วงที่ยังสด จึงข้ามแม้แต่ request revalidation แบบมีเงื่อนไข เมื่อจับคู่กับ content hash ในชื่อไฟล์ (อย่าง app.a8f3d2.js) และ max-age=31536000 ผู้ใช้ที่กลับมาจะโหลด bundle จากดิสก์โดยตรงโดยไม่มี network chatter เลย ห้ามใช้ immutable กับ URL ที่คอนเทนต์เปลี่ยนได้ — นั่นคือสาเหตุของอาการ "deploy แล้วแต่ผู้ใช้ยังเห็นเว็บเก่า"
stale-while-revalidate และ stale-if-error ทำงานอย่างไร
stale-while-revalidate=86400 คือหน้าต่างผ่อนปรนแบบ asynchronous: เมื่อ response ในแคชหมดอายุ แคชจะเสิร์ฟสำเนาเก่าทันทีแล้วไปรีเฟรชในเบื้องหลัง ผู้ใช้ได้ response แบบทันที ส่วนผู้ใช้คนถัดไปได้คอนเทนต์ใหม่ stale-if-error=604800 ต่อยอดแนวคิดเดียวกันสู่กรณีล้มเหลว — ถ้า origin ตอบ 5xx หรือ timeout แคชจะยังเสิร์ฟสำเนาเก่าต่อได้ตามหน้าต่างที่กำหนด แทนที่จะโชว์หน้า error รวมกันแล้วทั้งคู่คือการอัปเกรดความทนทานที่ถูกที่สุดสำหรับเว็บที่เน้น static
no-cache กับ no-store ต่างกันอย่างไร
สองตัวนี้ถูกสับสนกันบ่อยที่สุด no-cache หมายถึง "เก็บไว้ได้ แต่ต้อง revalidate กับเซิร์ฟเวอร์ทุกครั้งก่อนใช้" — response ยังได้ประโยชน์จาก conditional request ที่ตอบ 304 Not Modified ส่วน no-store หมายถึง "ห้ามบันทึกไว้ที่ใดเลย" — เหมาะกับหน้าธนาคาร ไฟล์ส่งออกเฉพาะบุคคล และทุกอย่างใต้การยืนยันตัวตนที่ต้องไม่ตกค้างในแคชใด ๆ
must-revalidate ใช้เมื่อไหร่
เมื่อ response ที่มี must-revalidate เก่าเกินกำหนด แคชจะเสิร์ฟมันไม่ได้แม้กับไคลเอนต์ออฟไลน์ — ต้อง revalidate และอาจต้องตอบ 504 หาก origin ติดต่อไม่ได้ ใช้เมื่อการเสิร์ฟของเก่าแย่กว่าการเสิร์ฟไม่ได้เลย (เช่น ข้อมูลราคาหรือสต็อก) และจับคู่ max-age=0, must-revalidate เมื่อต้องการให้แคชที่เบราว์เซอร์โดยไม่มีความเสี่ยงเรื่องความเก่า
สามสูตรสำเร็จที่ครอบคลุมเว็บ 95% ของกรณี
Hashed static assets. TTL ยาวบวกความไม่เปลี่ยนแปลง:
add_header Cache-Control "public, max-age=31536000, immutable";
เอกสาร HTML. Revalidate ทุกครั้งที่เข้าหน้า พร้อมหน้าต่างผ่อนปรนให้ CDN:
Header set Cache-Control "no-cache, s-maxage=60, stale-while-revalidate=300"
JSON API. กัน response ส่วนบุคคลออกจาก shared cache หรือเปิดให้ GET ที่ไม่อ่อนไหวอยู่ที่ edge ได้สั้น ๆ:
app.use('/api/me', (req, res, next) => {
res.set('Cache-Control', 'private, no-store');
next();
});
กรณีการใช้งานจริง
Static Asset Pipeline
Bundler อย่าง webpack, Vite และ Next.js ใส่ fingerprint ให้ไฟล์ JS และ CSS ทุกไฟล์ เสิร์ฟไฟล์ที่มี hash เหล่านั้นด้วย public, max-age=31536000, immutable แล้วเวลาโหลดของผู้ใช้เก่าจะเหลือเกือบศูนย์ ขณะที่อัตรา offload ของ CDN พุ่งเกิน 95% เครื่องมือสร้างสนิปเป็ตทั้งสามเซิร์ฟเวอร์ให้ ทำให้มาตรฐานพอลิซีเดียวกันทั้ง staging และ production
การ Deploy Single-Page Application
SPA ต้องการพอลิซีแบบแยกส่วน: index.html ต้องสดใหม่เสมอ (เพราะอ้างถึง bundle ที่มี hash ผ่าน URL) ขณะที่ตัว bundle เองแคชได้ถึงหนึ่งปี ใช้ no-cache กับ HTML เพื่อให้เบราว์เซอร์ revalidate แบบถูก ๆ ตั้ง s-maxage สั้น ๆ ให้ CDN ดูดซับ traffic revalidation และใส่ immutable กับ asset ถ้าพลาดจุดนี้จะเจอบั๊กหน้าขาวคลาสสิกตอน deploy
API Response
Endpoint GET แบบสาธารณะที่แคชได้ จะได้ประโยชน์จาก public, s-maxage=300, stale-while-revalidate=600 — CDN ตอบ request ส่วนใหญ่และฐานข้อมูลแทบไม่รู้สึกถึง traffic ที่พุ่ง ส่วน endpoint ที่ต้องยืนยันตัวตนหรือเฉพาะบุคคลต้องส่ง private, no-store เพื่อไม่ให้ตัวกลางเก็บข้อมูลผู้ใช้ toggle builder ทำให้เห็นชัดว่าแต่ละกลุ่ม endpoint ควรใช้ directive คอมบิเนชันไหน
แก้บั๊กเห็นเว็บเก่าหลัง Deploy
เมื่อผู้ใช้รายงานว่าเห็นเวอร์ชันเก่าหลัง deploy ตัวการมักเป็น max-age ยาวบน HTML หรือ asset ที่มี hash แต่เสิร์ฟโดยไม่มี immutable ประกอบพอลิซีแบบแยกส่วนที่ถูกต้องด้วยเครื่องมือนี้ แล้ว deploy header ใหม่ บั๊กจะหายไปเองเมื่อแคชหมดอายุ — ไม่ต้องพึ่ง query string กันแคชอีกต่อไป
แนวปฏิบัติที่ดีที่สุดสำหรับ Production
- ใส่ hash ในชื่อไฟล์ก่อนให้ TTL ยาว. max-age=31536000, immutable ปลอดภัยก็ต่อเมื่อ URL เปลี่ยนทุกครั้งที่คอนเทนต์เปลี่ยน
- ทดสอบด้วย curl -I หลัง deploy ทุกครั้ง. ตรวจ Cache-Control header จริงจากเซิร์ฟเวอร์และ CDN ของคุณ เพราะคอนฟิกมักถูก override ที่ใดที่หนึ่งในสายเสมอ
- จำไว้ว่า CDN อาจ override header ของคุณ. หลายแพลตฟอร์มบังคับค่าเริ่มต้นของตัวเองหรือรับฟังเฉพาะ s-maxage — ตรวจสอบว่าผู้ให้บริการแคชอะไรจริง ๆ อย่าเพิ่งเชื่อ
- กำหนดหนึ่งพอลิซีต่อหนึ่งกลุ่ม resource. hashed asset, HTML และ API สมควรได้กฎของตัวเอง header กลางชุดเดียวคือจุดกำเนิดของบั๊กเว็บเก่า
- เลือก no-cache แทน no-store สำหรับ HTML. คุณจะได้ความสดใหม่ที่การันตีได้ ขณะที่รอบเทียบ 304 Not Modified ยังถูกและเร็ว
- ใส่ stale-if-error เป็นประกันราคาถูก. directive บรรทัดเดียวช่วยให้เว็บยังขึ้น (ในรูปแบบของเก่า) ได้ตลอดช่วง origin ล่ม
เร่งความเร็วเว็บคุณตั้งแต่วันนี้
ชวนทีมของคุณเข้าไปที่ Cache-Control Header Generator เลือกสูตรสำเร็จที่ตรงกับ resource แต่ละกลุ่ม แล้ววางสนิปเป็ตที่สร้างให้ลงในคอนฟิกเซิร์ฟเวอร์ การตั้งค่า header เพียงสิบนาทีมักให้ผลเร่งความเร็วจริงมากกว่าการจูน JavaScript แบบละเอียดนานหนึ่งสัปดาห์เสียอีก
เครื่องมือที่เกี่ยวข้องที่คุณอาจสนใจ:
- Security Headers Generator — สร้าง CSP, HSTS และ header ป้องกันภัยอื่น ๆ ด้วยแนวทาง toggle เดียวกัน
- HSTS Header Generator — ประกอบพอลิซี Strict-Transport-Security ที่บังคับ HTTPS ทั่วทั้งโดเมน
- htaccess Generator — สร้างไฟล์ .htaccess ของ Apache ที่รวมการแคชเข้ากับ redirect และกฎอื่น ๆ
ขอให้แคชของคุณ HIT ตลอด!
คำถามที่พบบ่อย
ถ: max-age กับ s-maxage ต่างกันอย่างไร?
ตอบ: max-age กำหนดว่าแคชใด ๆ — รวมถึงเบราว์เซอร์ — ใช้ response ซ้ำได้นานเท่าไร ส่วน s-maxage มีผลเฉพาะ shared cache อย่าง CDN และจะ override max-age ในเลเยอร์นั้น การตั้งทั้งคู่ทำให้ CDN เก็บได้นานกว่าอุปกรณ์แต่ละเครื่อง
ถ: ควรใช้ no-cache แทน no-store เมื่อไหร่?
ตอบ: ใช้ no-cache เมื่อคอนเทนต์ต้อง revalidate ก่อนใช้ทุกครั้งแต่ยังเก็บไว้ได้ ซึ่งทำให้ response แบบ 304 Not Modified เร็วและถูก ส่วน no-store ใช้เฉพาะ response ที่อ่อนไหวหรือเฉพาะตัวตนมาก จนต้องไม่ถูกบันทึกโดยแคชใดเลย
ถ: immutable ใช้กับ asset ทุกไฟล์ได้ปลอดภัยไหม?
ตอบ: ปลอดภัยเฉพาะ URL ที่ชื่อไฟล์มี content hash หรือเวอร์ชันที่เปลี่ยนทุกครั้งที่ไฟล์เปลี่ยน การใส่ immutable กับ URL คงที่อย่าง /styles.css จะทำให้เบราว์เซอร์ใช้ไฟล์เก่าต่อไปจนกว่า TTL จะหมด
ถ: stale-while-revalidate ทำให้ผู้ใช้แรกหลังหมดอายุช้าลงหรือไม่?
ตอบ: ไม่ จุดประสงค์หลักคือแคชตอบทันทีด้วยสำเนาเก่าแล้วไปดึงคอนเทนต์ใหม่ในเบื้องหลัง ผู้ใช้คนแรกจึงได้ response เร็วที่สุดเท่าที่เป็นไปได้ และผู้ใช้คนถัด ๆ ไปได้คอนเทนต์ที่รีเฟรชแล้ว
ถ: CDN ของฉันจะเคารพ header ที่เครื่องมือสร้างให้หรือไม่?
ตอบ: CDN ใหญ่ ๆ ส่วนใหญ่เคารพ Cache-Control และให้น้ำหนัก s-maxage สูงสุด แต่บางแพลตฟอร์มมีกฎการแคชเริ่มต้นของตัวเอง ควรตรวจสอบพฤติกรรมจริงด้วย curl -I กับโดเมน production และอ่านเอกสารของผู้ให้บริการเสมอ