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

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

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

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

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

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

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

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

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

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

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

นอกจากนั้น การตั้งค่าส่วนหัวการตอบกลับเพิ่มเติม 1 จาก 2 รายการก็อาจช่วยแก้ปัญหาได้ เช่น 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 ของเบราว์เซอร์ ในกรณีนี้ ทั้ง 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 gotchas ของ Jake Archibald

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

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

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

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