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

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

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

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

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

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

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

แล้วคุณจะใช้ประโยชน์จากทั้ง 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

การตั้งค่า 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 มากกว่าพื้นฐาน โปรดดูคู่มือแนวทางปฏิบัติแนะนำในการแคชและ M-age Gotchas ของ 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 ระบบไม่อนุญาตให้แคชการตอบกลับและต้องดึงข้อมูลทั้งหมดในคำขอทุกรายการ