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