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

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

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

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

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

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

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

Cache-Control

การสนับสนุนเบราว์เซอร์

  • จริง
  • 12
  • จริง
  • จริง

แหล่งที่มา

ETag

การสนับสนุนเบราว์เซอร์

  • จริง
  • 12
  • จริง
  • จริง

แหล่งที่มา

Last-Modified

การสนับสนุนเบราว์เซอร์

  • จริง
  • 12
  • จริง
  • จริง

แหล่งที่มา

วิธีการทำงานของแคช 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 หรือจนกว่าจะมีการนำออกจากแคชด้วยเหตุผลอื่น เช่น ผู้ใช้ล้างแคชของเบราว์เซอร์ ดังนั้น ผู้ใช้แต่ละรายอาจโหลดไฟล์เวอร์ชันต่างๆ กันเมื่อสร้างหน้าเว็บ ผู้ใช้ที่เพิ่งดึงข้อมูลแหล่งข้อมูลจะใช้เวอร์ชันใหม่ แต่ผู้ใช้ที่แคชสำเนาก่อนหน้านี้ (แต่ยังคงใช้งานได้) จะใช้เวอร์ชันเก่า

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

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

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

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

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

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

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

ค่า 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 ซึ่งเทียบเท่ากับ "Ok ใช้สิ่งที่คุณมีอยู่แล้วต่อไป" เมื่อส่งคำตอบประเภทนี้ ข้อมูลที่จะโอนมีน้อยมาก จึงมักรวดเร็วกว่าการต้องส่งสำเนาทรัพยากรตามคำขอจริงกลับมา

แผนภาพของไคลเอ็นต์ที่ขอทรัพยากร และเซิร์ฟเวอร์ตอบสนองด้วยส่วนหัว 304
เบราว์เซอร์จะขอ /file จากเซิร์ฟเวอร์และมีส่วนหัว If-None-Match เพื่อสั่งให้เซิร์ฟเวอร์แสดงผลไฟล์แบบเต็มเฉพาะเมื่อ ETag ของไฟล์ในเซิร์ฟเวอร์ไม่ตรงกับค่า If-None-Match ของเบราว์เซอร์ ในกรณีนี้ ค่าจะตรงกัน เซิร์ฟเวอร์จึงตอบกลับด้วย 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 gotchas ของ Jake Archibald

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

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

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

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

ภาคผนวก: 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 แคชการตอบกลับไม่ได้และต้องดึงข้อมูลทั้งหมดในทุกคำขอ