เทคนิคตั้งค่า HTTP Cache ให้เว็บโหลดไวขึ้นแบบไม่ต้องอัปสเปก
การตั้งค่า HTTP Cache อย่างถูกวิธีช่วยให้เว็บโหลดเร็วขึ้น ลดการโหลดไฟล์ซ้ำ ประหยัดแบนด์วิดท์ และลดภาระเซิร์ฟเวอร์ได้อย่างชัดเจน โดยหัวใจสำคัญคือการแยกประเภทไฟล์และกำหนด Cache-Control, ETag, และ Last-Modified ให้เหมาะสม

เทคนิคตั้งค่า HTTP Cache ให้เว็บโหลดไวขึ้นแบบไม่ต้องอัปสเปก
หนึ่งในสาเหตุสำคัญที่ทำให้เว็บไซต์ช้าคือเบราว์เซอร์ต้องโหลดไฟล์เดิมซ้ำ ๆ ไม่ว่าจะเป็น CSS, JavaScript, รูปภาพ หรือฟอนต์ ทั้งที่หลายไฟล์แทบไม่ได้เปลี่ยนเลย หากตั้งค่า HTTP Cache อย่างถูกต้อง เบราว์เซอร์จะช่วยจดจำไฟล์เหล่านี้และลดการร้องขอที่ไม่จำเป็นได้ทันที
ผลลัพธ์ที่มักเห็นได้ชัดคือหน้าเว็บรีเฟรชได้เร็วขึ้น ใช้แบนด์วิดท์น้อยลง และลดภาระของเซิร์ฟเวอร์โดยไม่ต้องรีบเพิ่มสเปกเครื่อง
HTTP Cache คืออะไร และมีส่วนประกอบอะไรบ้าง
HTTP Cache คือกลไกที่ช่วยให้เบราว์เซอร์หรือระบบกลางอย่าง CDN เก็บสำเนาไฟล์ไว้ชั่วคราว เพื่อไม่ต้องดาวน์โหลดใหม่ทุกครั้งที่มีการเปิดหน้าเดิม
ส่วนประกอบสำคัญที่ควรรู้มี 3 อย่าง
- Cache-Control ใช้กำหนดนโยบายการแคช ว่าไฟล์ควรถูกเก็บไว้นานแค่ไหน และต้องกลับไปตรวจสอบกับเซิร์ฟเวอร์เมื่อใด
- ETag เป็นเหมือนลายนิ้วมือของไฟล์ ใช้ตรวจว่าเนื้อหาเปลี่ยนไปหรือยัง
- Last-Modified เป็นเวลาที่ไฟล์ถูกแก้ไขล่าสุด ใช้ช่วยตรวจสอบได้เช่นกัน แต่โดยทั่วไปไม่แม่นเท่า ETag
การใช้งานทั้งสามอย่างร่วมกันอย่างเหมาะสม จะช่วยให้เว็บเร็วขึ้นโดยไม่เสี่ยงแสดงข้อมูลเก่าผิดจังหวะ
ความผิดพลาดที่พบบ่อย: แคช HTML เหมือนไฟล์สแตติก
ข้อผิดพลาดที่คนทำเว็บพลาดกันบ่อยคือใช้กฎแคชแบบเดียวกันกับทุกไฟล์ โดยเฉพาะการนำ HTML ไปแคชยาวเหมือนไฟล์สแตติก เช่น CSS หรือ JS ผลคือผู้ใช้อาจยังเห็นหน้าเก่า ทั้งที่ข้อมูลจริงเปลี่ยนไปแล้ว
ทางที่ถูกคือควรแยกไฟล์ออกเป็นกลุ่มก่อน แล้วค่อยกำหนดนโยบายแคชให้ตรงตามลักษณะการเปลี่ยนแปลงของไฟล์นั้น
หลักการแบ่งไฟล์ก่อนตั้งค่าแคช
1) ไฟล์ที่ไม่ค่อยเปลี่ยน และเปลี่ยนแล้วเปลี่ยนชื่อได้
ตัวอย่างเช่น
app.3f2c1a.jsstyle.91ac.css
ไฟล์ลักษณะนี้มักถูกสร้างจากระบบ build และมี hash ติดมากับชื่อไฟล์ เมื่อเนื้อหาเปลี่ยน ชื่อไฟล์ก็จะเปลี่ยนตามทันที
สำหรับไฟล์ประเภทนี้ สามารถตั้งค่าได้แบบยาวมาก เช่น
Cache-Control: public, max-age=31536000, immutable
ความหมายคือ
max-age=31536000ให้เบราว์เซอร์เก็บไว้ได้นาน 1 ปีimmutableบอกว่าไฟล์นี้จะไม่เปลี่ยนในช่วงอายุแคช
เหตุผลที่ปลอดภัยก็เพราะถ้าไฟล์เปลี่ยนจริง ระบบ build จะสร้างชื่อใหม่จาก hash ทำให้เบราว์เซอร์ร้องขอไฟล์ใหม่โดยอัตโนมัติ
2) ไฟล์ที่อาจเปลี่ยน แต่ยังใช้ชื่อเดิม
ตัวอย่างเช่น
/api/config.json- รูปภาพที่อัปเดตทับไฟล์เดิม
ไฟล์ประเภทนี้ไม่เหมาะกับการแคชยาว เพราะชื่อเดิมอาจชี้ไปยังเนื้อหาใหม่ได้ตลอด ค่าที่เหมาะสมคือ
Cache-Control: public, max-age=0, must-revalidate
พฤติกรรมที่เกิดขึ้นคือเบราว์เซอร์ยังเก็บไฟล์ไว้ได้ แต่ทุกครั้งที่จะใช้ต้องถามเซิร์ฟเวอร์ก่อนว่าไฟล์เปลี่ยนหรือยัง ถ้าไม่เปลี่ยน เซิร์ฟเวอร์สามารถตอบกลับเป็น 304 Not Modified โดยไม่ต้องส่งเนื้อไฟล์ซ้ำ ทำให้เร็วและประหยัดทรัพยากรมาก
ในกรณีนี้ ETag มีความสำคัญมาก เพราะเป็นตัวช่วยให้การตรวจสอบว่าไฟล์เปลี่ยนหรือไม่ทำได้แม่นยำ
ตัวอย่างการทำงานแบบย่อ
- ครั้งแรก เซิร์ฟเวอร์ส่งไฟล์พร้อม
ETag: "v1a2b" - ครั้งถัดมา เบราว์เซอร์ส่ง
If-None-Match: "v1a2b" - หากไฟล์ยังเหมือนเดิม เซิร์ฟเวอร์ตอบ
304 Not Modified
3) HTML ที่ต้องการความสดใหม่มากกว่าไฟล์อื่น
สำหรับไฟล์ HTML โดยเฉพาะเว็บที่มีเนื้อหาเปลี่ยนบ่อย ค่าที่นิยมใช้คือ
Cache-Control: no-cache
คำว่า no-cache ไม่ได้แปลว่า “ห้ามเก็บ” แต่หมายถึง “เก็บได้ แต่ต้องตรวจสอบกับเซิร์ฟเวอร์ก่อนใช้ทุกครั้ง” ซึ่งเหมาะกับ HTML มาก เพราะช่วยลดความเสี่ยงที่ผู้ใช้จะเห็นข้อมูลเก่า
ส่วน no-store นั้นเข้มกว่ามาก เพราะหมายถึงห้ามเก็บเลย เหมาะกับข้อมูลอ่อนไหว เช่น หน้าข้อมูลเงินเดือน หรือหน้าที่มีข้อมูลส่วนตัวระดับสำคัญ
ETag ที่ไม่เสถียร: ปัญหาที่หลายระบบไม่ทันระวัง
อีกประเด็นที่ไม่ค่อยมีคนพูดถึงคือ ETag บางระบบอาจสร้างค่าจากข้อมูลเฉพาะเครื่อง เช่น inode หรือเวลาแก้ไขไฟล์ของแต่ละเซิร์ฟเวอร์ หากระบบมีหลายเครื่องอยู่หลัง Load Balancer ค่า ETag อาจไม่ตรงกันแม้ไฟล์จริงจะเหมือนกัน
ผลที่ตามมาคือเบราว์เซอร์ตรวจสอบแล้วไม่แมตช์ ทำให้เซิร์ฟเวอร์ตอบ 200 OK พร้อมไฟล์เต็มบ่อยเกินจำเป็น แคชที่ควรทำงานจึงเสียประสิทธิภาพ
แนวทางแก้คือ
- ใช้ ETag ที่สร้างจาก hash ของไฟล์หรือเวอร์ชัน build ให้เหมือนกันทุกเครื่อง
- หรือปิด ETag ไปเลย แล้วใช้
Last-Modifiedร่วมกับmust-revalidateแทน แม้ความแม่นยำจะลดลงบ้าง
แนวทางตั้งค่าบน Nginx และโครงสร้างไฟล์
ถ้าใช้ Nginx แนวคิดที่ดีคือแยก path ของไฟล์สแตติกให้ชัดเจน เช่น
/static//assets/
การแยกเส้นทางแบบนี้ช่วยให้ตั้งกฎแคชได้ง่าย ลดความผิดพลาด และทำให้ทีมดูแลระบบร่วมกันได้สะดวกขึ้นเมื่อโปรเจกต์ขยายใหญ่
แนวทางทั่วไปคือ
- ไฟล์ที่มี hash ในชื่อ ตั้งแคชยาว 1 ปี พร้อม
immutable - ไฟล์ทั่วไปที่ชื่อเดิมแต่เนื้อหาอาจเปลี่ยน ตั้ง
must-revalidateและใช้ ETag แบบคงที่ - ไฟล์ HTML ใช้
no-cacheเป็นค่าเริ่มต้นในหลายกรณี
วิธีตรวจสอบว่าตั้งค่าแคชถูกหรือยัง
หลังตั้งค่าแล้ว ควรตรวจสอบด้วย DevTools ของเบราว์เซอร์ โดยดูที่แท็บ Network
สิ่งที่ควรสังเกตคือ
- สถานะ
200 (from disk cache)หรือรูปแบบการใช้แคชจากเบราว์เซอร์ - สถานะ
304 Not Modifiedสำหรับไฟล์ที่ต้อง revalidate - Response Headers ว่ามี
Cache-Control,ETagหรือLast-Modifiedตามที่คาดไว้
การตรวจสอบขั้นนี้สำคัญมาก เพราะทำให้มั่นใจว่าพฤติกรรมจริงตรงกับที่ออกแบบไว้ ไม่ใช่แค่ตั้งค่าแล้วคิดว่าใช้งานได้
ถ้าใช้ CDN ควรระวังอะไรบ้าง
ในระบบที่มี CDN คั่นอยู่หน้าเซิร์ฟเวอร์ ควรตั้งค่า origin cache header ให้ดี และตรวจว่า CDN ถูกตั้งให้เคารพ header จากต้นทางจริง
บางผู้ให้บริการ CDN อาจต้องเปิดโหมดประเภท respect origin หรือกำหนด cache key เพิ่มเติม เพื่อให้การแคชทำงานถูกต้องตามที่ตั้งใจ หากละเลยจุดนี้ อาจเกิดปัญหาไฟล์บางชนิดถูกแคชผิดกฎ หรือ HTML ถูกเก็บนานเกินไปได้
สรุป
การตั้งค่า HTTP Cache ที่ดีไม่ใช่การตั้งค่าเดียวใช้กับทุกไฟล์ แต่คือการแยกประเภทไฟล์และกำหนดนโยบายให้เหมาะกับการเปลี่ยนแปลงของแต่ละชนิด
สรุปแบบจำง่ายคือ
- ไฟล์มี hash → แคชยาว +
immutable - ไฟล์ชื่อเดิมแต่เนื้อหาอาจเปลี่ยน →
max-age=0+must-revalidate+ ETag ที่เสถียร - HTML → ส่วนใหญ่ใช้
no-cache
เมื่อจัดการครบทั้ง 3 กลุ่มนี้ เว็บไซต์จะตอบสนองเร็วขึ้นอย่างรู้สึกได้ ช่วยประหยัดแบนด์วิดท์ ลดภาระเซิร์ฟเวอร์ และเพิ่มประสบการณ์ใช้งานโดยไม่ต้องรีบลงทุนเพิ่มเครื่อง