ป้องกันคำขอเครือข่ายที่ไม่จำเป็นด้วยแคช 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

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

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