ป้องกันคำขอเครือข่ายที่ไม่จำเป็นด้วยแคช HTTP

การดึงข้อมูลทรัพยากรผ่านเครือข่ายทั้งช้าและมีค่าใช้จ่ายสูง ดังนี้

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

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

คู่มือนี้จะแสดงข้อมูลเบื้องต้นเกี่ยวกับการติดตั้งใช้งานการแคช HTTP ที่มีประสิทธิภาพ

ความเข้ากันได้กับเบราว์เซอร์

จริงๆ แล้วไม่มี API เดียวที่เรียกว่าแคช HTTP ซึ่งเป็นชื่อทั่วไปของคอลเล็กชัน API ของแพลตฟอร์มเว็บ API เหล่านี้รองรับในเบราว์เซอร์ทั้งหมด

Cache-Control

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 1.

Source

ETag

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 1.

Source

Last-Modified

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 1.

Source

วิธีการทำงานของแคช HTTP

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

ลักษณะการทำงานของแคช HTTP จะควบคุมโดยการรวมส่วนหัวของคำขอและส่วนหัวการตอบกลับเข้าด้วยกัน ในสถานการณ์ที่เหมาะสม คุณจะควบคุมทั้งโค้ดสำหรับเว็บแอปพลิเคชัน (ซึ่งจะกำหนดส่วนหัวของคำขอ) และการกำหนดค่าของเว็บเซิร์ฟเวอร์ (ซึ่งจะกำหนดส่วนหัวการตอบกลับ)

ดูภาพรวมเชิงแนวคิดที่เจาะลึกยิ่งขึ้นได้ในบทความการแคช HTTP ของ MDN

ส่วนหัวของคำขอ: ใช้ค่าเริ่มต้น (โดยปกติ)

มีส่วนหัวที่สำคัญจำนวนหนึ่งที่ควรใส่ไว้ในคำขอขาออกของเว็บแอป แต่เบราว์เซอร์มักจะดูแลการตั้งค่าส่วนหัวเหล่านี้ในนามของคุณเมื่อส่งคำขอ ส่วนหัวของคำขอที่ส่งผลต่อการตรวจสอบความใหม่ เช่น If-None-Match และ If-Modified-Since จะปรากฏตามความเข้าใจของเบราว์เซอร์เกี่ยวกับค่าปัจจุบันในแคช HTTP

ซึ่งถือเป็นข่าวดี เพราะหมายความว่าคุณสามารถใส่แท็กอย่าง <img src="my-image.png"> ไว้ใน HTML ต่อไปได้ และเบราว์เซอร์จะจัดการการแคช HTTP ให้คุณโดยอัตโนมัติโดยไม่ต้องดำเนินการใดๆ เพิ่มเติม

ส่วนหัวการตอบกลับ: กำหนดค่าเว็บเซิร์ฟเวอร์

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

  • Cache-Control เซิร์ฟเวอร์สามารถแสดงคำสั่ง Cache-Control เพื่อระบุวิธีและระยะเวลาที่เบราว์เซอร์และแคชระดับกลางอื่นๆ ควรแคชการตอบกลับแต่ละรายการ
  • ETag เมื่อเบราว์เซอร์พบการตอบกลับที่แคชไว้ซึ่งหมดอายุแล้ว เบราว์เซอร์จะส่งโทเค็นขนาดเล็ก (โดยปกติจะเป็นแฮชของเนื้อหาไฟล์) ไปยังเซิร์ฟเวอร์เพื่อตรวจสอบว่าไฟล์มีการเปลี่ยนแปลงหรือไม่ หากเซิร์ฟเวอร์แสดงผลโทเค็นเดียวกัน แสดงว่าไฟล์เหมือนกันและไม่จำเป็นต้องดาวน์โหลดอีกครั้ง
  • Last-Modified ส่วนหัวนี้มีวัตถุประสงค์เดียวกับ ETag แต่ใช้กลยุทธ์ตามเวลาเพื่อพิจารณาว่าทรัพยากรมีการเปลี่ยนแปลงหรือไม่ ซึ่งตรงข้ามกับกลยุทธ์ตามเนื้อหาของ ETag

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

เพื่อช่วยประหยัดเวลาในการค้นหา ต่อไปนี้เป็นวิธีการกำหนดค่าเว็บเซิร์ฟเวอร์ยอดนิยมบางส่วน

การละเว้นส่วนหัวการตอบกลับ Cache-Control ไม่ได้ปิดใช้การแคช HTTP แต่เบราว์เซอร์จะคาดเดาอย่างมีประสิทธิภาพว่าลักษณะการแคชประเภทใดเหมาะสมที่สุดสำหรับเนื้อหาประเภทหนึ่งๆ คุณอาจต้องการควบคุมมากกว่าที่ตัวเลือกนั้นมีให้ ดังนั้นโปรดสละเวลาในการกำหนดค่าส่วนหัวการตอบกลับ

คุณควรใช้ค่าส่วนหัวการตอบกลับใด

มี 2 สถานการณ์สำคัญที่คุณควรพิจารณาเมื่อกำหนดค่าส่วนหัวการตอบกลับของเว็บเซิร์ฟเวอร์

การแคชเป็นระยะเวลานานสำหรับ URL ที่มีการกำหนดเวอร์ชัน

วิธีที่ URL ที่กำหนดเวอร์ชันช่วยกลยุทธ์การแคชได้
URL ที่กำหนดเวอร์ชันเป็นแนวทางปฏิบัติที่ดีเนื่องจากช่วยให้การทำให้การตอบกลับที่แคชไว้ใช้งานไม่ได้นั้นง่ายขึ้น

สมมติว่าเซิร์ฟเวอร์ของคุณสั่งให้เบราว์เซอร์แคชไฟล์ CSS เป็นเวลา 1 ปี (Cache-Control: max-age=31536000) แต่นักออกแบบเพิ่งทำการอัปเดตฉุกเฉินที่คุณต้องทำให้ใช้งานได้ทันที คุณจะแจ้งให้เบราว์เซอร์อัปเดตสำเนาไฟล์ที่แคชไว้ซึ่ง "ล้าสมัย" ได้อย่างไร คุณทำไม่ได้ อย่างน้อยก็ทำไม่ได้หากไม่เปลี่ยน URL ของทรัพยากร

หลังจากเบราว์เซอร์แคชการตอบกลับแล้ว ระบบจะใช้เวอร์ชันที่แคชไว้จนกว่าจะไม่มีการอัปเดตตามที่ max-age หรือ expires กำหนด หรือจนกว่าจะถูกนำออกจากแคชด้วยเหตุผลอื่นๆ เช่น ผู้ใช้ล้างแคชของเบราว์เซอร์ ด้วยเหตุนี้ ผู้ใช้แต่ละรายจึงอาจใช้ไฟล์เวอร์ชันที่แตกต่างกันเมื่อสร้างหน้าเว็บ โดยผู้ใช้ที่เพิ่งดึงข้อมูลทรัพยากรจะใช้เวอร์ชันใหม่ ส่วนผู้ใช้ที่แคชสำเนาก่อนหน้า (แต่ยังคงใช้ได้) จะใช้การตอบกลับเวอร์ชันเก่า

คุณจะใช้ประโยชน์จากทั้ง 2 อย่าง ได้แก่ การแคชฝั่งไคลเอ็นต์และการอัปเดตอย่างรวดเร็วได้อย่างไร คุณเปลี่ยน URL ของทรัพยากรและบังคับให้ผู้ใช้ดาวน์โหลดการตอบกลับใหม่เมื่อใดก็ตามที่เนื้อหามีการเปลี่ยนแปลง โดยปกติแล้ว คุณจะดำเนินการนี้ได้โดยฝังลายนิ้วมือของไฟล์หรือหมายเลขเวอร์ชันไว้ในชื่อไฟล์ เช่น style.x234dff.css

เมื่อตอบกลับคำขอ URL ที่มีข้อมูล "ฟิงเกอร์ปรินต์" หรือการกำหนดเวอร์ชัน และเนื้อหาที่ไม่ได้มีไว้เพื่อเปลี่ยนแปลง ให้เพิ่ม Cache-Control: max-age=31536000 ลงในการตอบกลับ

การตั้งค่านี้จะบอกเบราว์เซอร์ว่าเมื่อต้องการโหลด URL เดียวกันเมื่อใดก็ตามในช่วง 1 ปีข้างหน้า (31,536,000 วินาที ซึ่งเป็นค่าสูงสุดที่รองรับ) เบราว์เซอร์จะใช้ค่าในแคช HTTP ได้ทันทีโดยไม่ต้องส่งคำขอเครือข่ายไปยังเว็บเซิร์ฟเวอร์เลย ยอดเยี่ยมมาก คุณได้รับความน่าเชื่อถือและความเร็วที่มาจากการหลีกเลี่ยงเครือข่ายทันที

เครื่องมือสร้างอย่าง webpack สามารถทำให้กระบวนการกำหนดลายนิ้วมือแฮชให้กับ URL ของเนื้อหาเป็นแบบอัตโนมัติได้

การตรวจสอบความถูกต้องของเซิร์ฟเวอร์อีกครั้งสำหรับ URL ที่ไม่มีเวอร์ชัน

อย่างไรก็ตาม URL บางรายการที่คุณโหลดอาจไม่มีการกำหนดเวอร์ชัน คุณอาจไม่สามารถรวมขั้นตอนการสร้างก่อนที่จะทำให้เว็บแอปใช้งานได้ คุณจึงเพิ่มแฮชลงใน URL ของเนื้อหาไม่ได้ และเว็บแอปพลิเคชันทุกรายการต้องมีไฟล์ HTML ซึ่งไฟล์เหล่านั้น (เกือบ) จะไม่มีข้อมูลการกำหนดเวอร์ชัน เนื่องจากจะไม่มีใครสนใจใช้เว็บแอปของคุณหากต้องจำว่า URL ที่จะเข้าชมคือ https://example.com/index.34def12.html แล้วคุณจะทำอะไรกับ URL เหล่านั้นได้บ้าง

นี่เป็นสถานการณ์หนึ่งที่คุณต้องยอมรับความพ่ายแพ้ การแคช HTTP เพียงอย่างเดียวไม่มีประสิทธิภาพเพียงพอที่จะหลีกเลี่ยงเครือข่ายได้อย่างสมบูรณ์ (ไม่ต้องกังวล คุณจะได้เรียนรู้เกี่ยวกับ Service Worker ในเร็วๆ นี้ ซึ่งจะให้การสนับสนุนที่เราต้องการเพื่อพลิกสถานการณ์ให้กลับมาเป็นฝ่ายได้เปรียบ) แต่คุณสามารถทำตามขั้นตอนต่อไปนี้เพื่อให้คำขอเครือข่ายทำงานได้เร็วและมีประสิทธิภาพมากที่สุด

ค่า Cache-Control ต่อไปนี้จะช่วยให้คุณปรับแต่งตำแหน่งและวิธีแคช URL ที่ไม่มีเวอร์ชันได้

  • no-cache ซึ่งจะบอกเบราว์เซอร์ว่าต้องตรวจสอบความถูกต้องกับเซิร์ฟเวอร์อีกครั้งทุกครั้งก่อนใช้ URL เวอร์ชันที่แคชไว้
  • no-store ซึ่งจะสั่งให้เบราว์เซอร์และแคชระดับกลางอื่นๆ (เช่น CDN) ไม่จัดเก็บไฟล์เวอร์ชันใดๆ เลย
  • private เบราว์เซอร์สามารถแคชไฟล์ได้ แต่แคชระดับกลางจะแคชไม่ได้
  • public แคชใดๆ ก็จัดเก็บการตอบกลับได้

ดูภาคผนวก: แผนผังลำดับงานของ Cache-Control เพื่อให้เห็นภาพกระบวนการตัดสินใจว่าจะใช้ค่า Cache-Control ใด Cache-Control ยังยอมรับรายการคำสั่งที่คั่นด้วยคอมมาด้วย ดูภาคผนวก: ตัวอย่าง Cache-Control

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

ตัวอย่าง ETag

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

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

การตั้งค่า ETag หรือ Last-Modified จะทำให้คำขอตรวจสอบความถูกต้องอีกครั้งมีประสิทธิภาพมากขึ้นโดยการเรียกให้ส่วนหัวของคำขอ If-Modified-Since หรือ If-None-Match ที่กล่าวถึงในส่วนหัวของคำขอทำงาน

เมื่อเว็บเซิร์ฟเวอร์ที่กำหนดค่าอย่างถูกต้องเห็นส่วนหัวของคำขอขาเข้าเหล่านั้น ก็จะยืนยันได้ว่าเวอร์ชันของทรัพยากรที่เบราว์เซอร์มีอยู่แล้วในแคช HTTP ตรงกับเวอร์ชันล่าสุดบนเว็บเซิร์ฟเวอร์หรือไม่ หากตรงกัน เซิร์ฟเวอร์จะตอบกลับด้วยการตอบกลับ HTTP 304 Not Modified ซึ่งเทียบเท่ากับ "เฮ้ ใช้สิ่งที่คุณมีอยู่แล้วต่อไป" การตอบกลับประเภทนี้มีข้อมูลที่ต้องโอนน้อยมาก จึงมักจะเร็วกว่าการส่งสำเนาของทรัพยากรจริงที่ขอมากลับไป

ภาพแสดงไคลเอ็นต์ที่ขอทรัพยากรและเซิร์ฟเวอร์ที่ตอบกลับด้วยส่วนหัว 304
เบราว์เซอร์จะขอ /file จากเซิร์ฟเวอร์และรวมส่วนหัว If-None-Match เพื่อสั่งให้เซิร์ฟเวอร์แสดงผลไฟล์แบบเต็มก็ต่อเมื่อ ETag ของไฟล์ในเซิร์ฟเวอร์ไม่ตรงกับค่า If-None-Match ของเบราว์เซอร์ ในกรณีนี้ ค่าทั้ง 2 ค่าตรงกัน เซิร์ฟเวอร์จึงแสดงการตอบกลับ 304 Not Modified พร้อมวิธีการเกี่ยวกับระยะเวลาที่ควรแคชไฟล์ (Cache-Control: max-age=120)

สรุป

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

การกำหนดค่า Cache-Control ต่อไปนี้เป็นจุดเริ่มต้นที่ดี

  • Cache-Control: no-cache สำหรับทรัพยากรที่ควรตรวจสอบความถูกต้องอีกครั้งกับเซิร์ฟเวอร์ก่อนการใช้งานทุกครั้ง
  • Cache-Control: no-store สำหรับทรัพยากรที่ไม่ควรแคชไว้
  • Cache-Control: max-age=31536000 สำหรับทรัพยากรที่มีเวอร์ชัน

และส่วนหัว ETag หรือ Last-Modified จะช่วยให้คุณตรวจสอบทรัพยากรแคชที่หมดอายุอีกครั้งได้อย่างมีประสิทธิภาพมากขึ้น

ดูข้อมูลเพิ่มเติม

หากต้องการทราบข้อมูลเพิ่มเติมเกี่ยวกับการใช้ส่วนหัว Cache-Control นอกเหนือจากข้อมูลพื้นฐาน โปรดดูคู่มือแนวทางปฏิบัติแนะนำในการแคชและข้อควรระวังเกี่ยวกับ max-age ของ Jake Archibald

ดูคำแนะนำเกี่ยวกับวิธีเพิ่มประสิทธิภาพการใช้แคชสำหรับผู้เข้าชมที่กลับมาได้ที่รักแคชของคุณ

ภาคผนวก: เคล็ดลับเพิ่มเติม

หากมีเวลามากขึ้น คุณสามารถเพิ่มประสิทธิภาพการใช้แคช HTTP ได้ด้วยวิธีต่อไปนี้

  • ใช้ URL ที่สอดคล้องกัน หากคุณแสดงเนื้อหาเดียวกันใน URL ที่แตกต่างกัน ระบบจะดึงข้อมูลและจัดเก็บเนื้อหานั้นหลายครั้ง
  • ลดการเลิกใช้งาน หากส่วนหนึ่งของทรัพยากร (เช่น ไฟล์ CSS) มีการอัปเดตบ่อยครั้ง แต่ส่วนที่เหลือของไฟล์ไม่มีการอัปเดต (เช่น โค้ดไลบรารี) ให้พิจารณาแยกโค้ดที่อัปเดตบ่อยออกเป็นไฟล์แยกต่างหาก และใช้กลยุทธ์การแคชระยะสั้นสำหรับโค้ดที่อัปเดตบ่อย และกลยุทธ์การแคชระยะยาวสำหรับโค้ดที่ไม่มีการเปลี่ยนแปลงบ่อยนัก
  • ดูคำสั่ง stale-while-revalidate ใหม่หากนโยบาย Cache-Control ของคุณยอมรับความเก่าได้ในระดับหนึ่ง

ภาคผนวก: โฟลว์ชาร์ต Cache-Control

โฟลว์ชาร์ต
กระบวนการตัดสินใจในการตั้งค่าส่วนหัว Cache-Control

ภาคผนวก: ตัวอย่าง Cache-Control รายการ

ค่า Cache-Control คำอธิบาย
max-age=86400 เบราว์เซอร์และแคชสื่อกลางจะแคชการตอบกลับได้นานสูงสุด 1 วัน (60 วินาที x 60 นาที x 24 ชั่วโมง)
private, max-age=600 เบราว์เซอร์สามารถแคชการตอบกลับได้ (แต่ไม่ใช่แคชสื่อกลาง) เป็นเวลาสูงสุด 10 นาที (60 วินาที x 10 นาที)
public, max-age=31536000 แคชใดๆ จะจัดเก็บการตอบกลับได้เป็นเวลา 1 ปี
no-store ไม่อนุญาตให้แคชการตอบกลับ และต้องดึงข้อมูลทั้งหมดในทุกคำขอ