การเรียกทรัพยากรผ่านเครือข่ายนั้นช้าและมีค่าใช้จ่ายสูง:
- การตอบสนองขนาดใหญ่ต้องใช้การส่งข้อมูลไปกลับหลายรอบระหว่างเบราว์เซอร์และเซิร์ฟเวอร์
- หน้าเว็บจะไม่โหลดจนกว่าทรัพยากรที่สำคัญทั้งหมดจะดาวน์โหลดเสร็จสมบูรณ์
- หากผู้ใช้ในเว็บไซต์มีแพ็กเกจอินเทอร์เน็ตมือถือแบบจำกัด ทุกคำขอจากเครือข่ายที่ไม่จำเป็นก็จะสูญเปล่าด้วย
คุณจะหลีกเลี่ยงคำขอเครือข่ายที่ไม่จำเป็นได้อย่างไร แคช HTTP ของเบราว์เซอร์เป็น ด่านแรกในการป้องกัน ซึ่งอาจไม่ใช่วิธีการที่มีประสิทธิภาพหรือยืดหยุ่นมากที่สุด และคุณสามารถควบคุมอายุการใช้งานของคำตอบที่แคชไว้ได้อย่างจำกัด แต่วิธีนี้มีประสิทธิภาพ ใช้ได้กับทุกเบราว์เซอร์ และไม่จำเป็นต้องทำงานมากนัก
คู่มือนี้แสดงข้อมูลพื้นฐานเกี่ยวกับการใช้งานการแคช HTTP ที่มีประสิทธิภาพ
ความเข้ากันได้กับเบราว์เซอร์
แคช HTTP เป็นชื่อทั่วไปสำหรับคอลเล็กชันของ API แพลตฟอร์มเว็บที่รองรับในเบราว์เซอร์ทั้งหมด ได้แก่
Cache-Control
ETag
Last-Modified
วิธีการทำงานของแคช 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 ที่มีการกำหนดเวอร์ชัน
สมมติว่าเซิร์ฟเวอร์ของคุณสั่งให้เบราว์เซอร์แคชไฟล์ 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
เพราะวิธีนี้จะแม่นยำกว่า
สมมติว่าเวลาที่ผ่านไป 120 วินาทีแล้วนับตั้งแต่การดึงข้อมูลครั้งแรกและเบราว์เซอร์ได้เริ่มคำขอใหม่สำหรับทรัพยากรเดียวกัน ก่อนอื่น เบราว์เซอร์จะตรวจสอบแคช HTTP และค้นหาการตอบสนองก่อนหน้า
ขออภัย เบราว์เซอร์นี้ใช้การตอบกลับก่อนหน้านี้ไม่ได้เนื่องจากหมดอายุแล้ว ในจุดนี้ เบราว์เซอร์จะส่งคำขอใหม่และดึงการตอบกลับใหม่แบบเต็มได้ อย่างไรก็ตาม วิธีนี้ไม่มีประสิทธิภาพ เนื่องจากหากทรัพยากรไม่มีการเปลี่ยนแปลง ก็ไม่มีเหตุผลที่จะต้องดาวน์โหลดข้อมูลที่อยู่ในแคชแล้วอีกครั้ง
นี่คือปัญหาที่โทเค็นสำหรับตรวจสอบความถูกต้อง ETag
ออกแบบมาเพื่อแก้ไข เซิร์ฟเวอร์สร้างและแสดงผลโทเค็นที่กำหนดเอง ซึ่งโดยปกติแล้วจะเป็นแฮชหรือลายนิ้วมืออื่นๆ ของเนื้อหาในไฟล์
เบราว์เซอร์ไม่จำเป็นต้องรู้วิธีสร้างลายนิ้วมือ โดยจะต้องส่งไปยังเซิร์ฟเวอร์ในคำขอถัดไปเท่านั้น หากลายนิ้วมือยังคงเหมือนเดิม แสดงว่าทรัพยากรไม่มีการเปลี่ยนแปลง และเบราว์เซอร์จะข้ามการดาวน์โหลดได้
การตั้งค่า ETag
หรือ Last-Modified
จะทำให้คำขอตรวจสอบความถูกต้องอีกครั้งมีประสิทธิภาพมากขึ้นโดยอนุญาตให้เรียกใช้ส่วนหัวของคำขอ If-Modified-Since
หรือ If-None-Match
ที่กล่าวถึงในส่วนหัวของคำขอ
เมื่อเว็บเซิร์ฟเวอร์ที่กำหนดค่าอย่างถูกต้องเห็นส่วนหัวของคำขอที่เข้ามาใหม่ ก็จะยืนยันได้ว่าเวอร์ชันของทรัพยากรที่เบราว์เซอร์มีในแคช HTTP ตรงกับเวอร์ชันล่าสุดในเว็บเซิร์ฟเวอร์หรือไม่ หากมีรายการที่ตรงกัน เซิร์ฟเวอร์จะตอบกลับด้วยการตอบกลับ HTTP 304 Not Modified
ซึ่งเทียบเท่ากับ "Ok ใช้สิ่งที่คุณมีอยู่แล้วต่อไป" เมื่อส่งคำตอบประเภทนี้ ข้อมูลที่จะโอนมีน้อยมาก จึงมักรวดเร็วกว่าการต้องส่งสำเนาทรัพยากรตามคำขอจริงกลับมา
สรุป
แคช 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 |
คำอธิบาย |
---|---|
max-age=86400 |
เบราว์เซอร์และแคชตัวกลางอาจแคชการตอบกลับไว้สูงสุด 1 วัน (60 วินาที x 60 นาที x 24 ชั่วโมง) |
private, max-age=600 |
เบราว์เซอร์สามารถแคชการตอบกลับได้สูงสุด 10 นาที (60 วินาที x 10 นาที) ยกเว้นแคชตัวกลาง |
public, max-age=31536000 |
แคชใดก็ได้จะจัดเก็บการตอบกลับไว้เป็นเวลา 1 ปี |
no-store |
แคชการตอบกลับไม่ได้และต้องดึงข้อมูลทั้งหมดในทุกคำขอ |