ว่าด้วยเรื่อง Caching ของ Cloudflare

Chai Phonbopit

Software Engineer & Blogger

25 July 2020

In

สืบเนื่องจากว่าตอนนี้ย้ายบล็อก มา Host เองแล้ว (ย้ายจาก Netlify) เมื่อก่อน Netlify มี DNS และ CND เอง ก็เลยยกเลิก Cloudflare ไป แต่ตอนนี้ไม่ใช้ Netlify แล้ว ก็เลยกลับมาลอง Cloudflare อีกครั้ง

สาเหตุที่ย้ายออกจาก Netlify เพราะว่า Free Plan ให้ Bandwidth 100GB ต่อเดือน มันไม่พอ เพราะมันแชร์หลายเว็บ เหมาะเอาไว้ทำเว็บเล็กๆ หรือพัฒนาเล่นๆ หรือ MVP มากกว่า สำหรับ Netlify และอีกอย่างคือ Bandwidth มันดันนับรวมพวก Bot พวก crawlers ต่างๆ ด้วย แถมรู้ว่าสึกว่า CDN และ cached file มันก็กิน Bandwidth usage ยิ่งช่วง เดือนที่ผ่านมา Traffic มัน 2-5 เท่าเลย เทียบ Analytics ของ Netlify กับ Google เดือนที่แล้ว โดนเพิ่ม \$20 / 100 GB แบบ Soft Limit เลยรู้สึกว่าไม่ดีละ

นอกเรื่องเยอะละ มาพูดถึงเรื่องวันนี้ดีกว่า คือเรื่องของการ Caching บน Cloudflare ครับ

Cache อะไรบ้าง?

ตัวเว็บเป็น Gatsby ต้องการปรับแต่ง Cache ให้ Static site ให้โหลดไวขึ้น อ้างอิงจาก Caching Static Sites

ก็เลยปรับ NGINX ให้ cache พวกไฟล์ css, js และไม่ต้อง cache พวก sw.js, page-data อะไรพวกนี้

ส่วน Cloudflare เป็น DNS และ Proxy ครอบเว็บอีกทีนึง มีรูปแบบการ Cache ของ Cloudflare เอง ซึ่งถ้าไม่มี Cloudflare มันก็สามารถ cache ได้ ปรับ Cache Control ได้ถูกต้องตาม NGINX เลย

ทีนี้พอมี Cloudflare มาครอบ ทีนี้ บางไฟล์ หรือบางโฟลเดอร์ ก็ไม่ได้ตามที่ต้องการ เนื่องจาก ว่าเราไม่ได้เข้าใจ concept ของ Cloudflare ดีพอ

เป้าหมายคือ

  1. ไม่ต้อง cache ไฟล์ .html ทั้งหมด
  2. ไม่ต้อง cache ไฟล์ /sw.js
  3. ไม่ต้อง cache /page-data/
  4. ไฟล์อื่นๆ cache ให้หมด

ปรับ Cache ตรงส่วนไหนบ้าง?

อย่างแรกเลย เราสามารถปรับให้ Cloudflare cache ไฟล์อะไร หรือไม่ cache อะไรบ้าง โดยไปที่แท็ป Caching -> Caching Level และ Browser Cache TTL

  • Caching Level - เลือกแบบ Standard - และ default Cloudflare ไม่ cache html ซึ่งผ่านแล้ว 1 ข้อ
  • Browser Cache TTL - ตัวนี้ Cloudflare จะทำการ Override Expire Header เพื่อทำการ Browser cache นั่นเอง ถ้าเราเลือก Respect Existing Headers Cloudflare ก็จะไม่ Override และจะใช้ ค่า Origin Server แทน แต่ถ้าเรามี Page Rule มันก็จะดูว่า Expires อันไหนมากกว่า ใช้อันนั้น

ทีนี้เรื่องของ Browser Cache TTL ถ้าเราไป set ค่าเป็น 30 นาที 1 hour หรืออื่นๆ แม้เราจะ สั่ง Cloudflare เคลียร์ cache ด้วย Purge cache เพื่อให้เว็บโหลด content ใหม่ ที่เราเพิ่งอัพเดท มันก็จะไม่เคลียร์จนกว่า TTL Expires จะหมดนะครับ ปัญหานี้ผมหาตั้งนาน ว่าทำไม Purge cached everyting ก็แล้ว แต่เนื้่อหา ไม่ fetch ใหม่ มันอ่าน sw.js ตัวเก่าตลอด

ต่อมา Page Rules เลือก Cache Level เป็น By Pass สำหรับ

  • /sw.js - ไม่ต้อง cache service worker ให้โหลดใหม่ทุกครั้ง
  • /page-data/*.json - ไม่ต้อง cache ไฟล์นี้เช่นกัน

สุดท้าย ถ้ากำหนดให้ไม่ต้อง cache หมดแล้ว แต่ content ใหม่ ก็ยังไม่อัพเดท เพราะ sw.js ก็ท่าสุดท้ายคือ Caching -> Purge Cache แล้วเลือก purge ไฟล์ หรือ Everyting ไปเลย

อีกรอบ! แต่ต้องดูด้วยนะ ว่าอย่าลืม อย่าไปกำหนด Browser Cache TTL ละ เดี๋ยว Cloudflare มันจะ Override Cache Control และ Expires ซึ่งการ Purge มันก็ช่วยอะไรไม่ได้

ก็เป็นอันเรียบร้อย สุดท้าย ทีเหลือ Cloudflare ก็อ่านพวก Cache Setting จาก Origin Server ซึ่งเรา Config ไว้ที่ nginx conf เรียบร้อย

สรุป

  • เพิ่ม Page Rules ทั้งหมด 2 ตัว เพื่อ By pass cached คือ sw.js, page-data/*.json
  • ปรับ Browser Cache TTL เป็น Respect Existing Headers
  • Caching Level ต้องเป็น Standard เพื่อไม่ต้อง cache ไฟล์ html
  • purge everyting ผ่านหน้า Dashboard หรือ เรียกจาก API สำหรับให้มัน clear cache ทั้งหมด

บทความนี้ก็บันทึกสิ่งที่เรียนรู้ไว้ ลองผิดลองถูก มั่วๆกันไป ซึ่งไม่แน่ใจว่า nginx config ดีหรือเปล่า หากตรงไหนผิดพลาด แนะนำ ติชม ข้อเสนอแนะได้นะครับ ขอบคุณครับ

Happy Learning 🔥

References