ตรวจสอบว่า Service Worker ของคุณทราบสิ่งที่ต้องทําเมื่อมีการขอการตอบกลับบางส่วน
คำขอ HTTP บางรายการมีส่วนหัว Range:
ซึ่งบ่งบอกว่าควรแสดงเฉพาะบางส่วนของทรัพยากรทั้งหมด โดยมักใช้สำหรับการสตรีมเนื้อหาเสียงหรือวิดีโอเพื่อให้โหลดสื่อเป็นชิ้นเล็กๆ ตามต้องการแทนที่จะขอไฟล์ระยะไกลทั้งไฟล์พร้อมกัน
Service Worker คือโค้ด JavaScript ที่อยู่ระหว่างเว็บแอปกับเครือข่าย ซึ่งอาจขัดขวางคำขอขาออกของเครือข่ายและสร้างคำตอบสำหรับคำขอเหล่านั้น
ที่ผ่านมา คำขอช่วงและ Service Worker ทำงานร่วมกันไม่ค่อยดีนัก คุณจึงต้องทำตามขั้นตอนพิเศษเพื่อหลีกเลี่ยงผลลัพธ์ที่ไม่พึงประสงค์ใน Service Worker แต่โชคดีที่สถานการณ์นี้เริ่มเปลี่ยนแปลงไป ในเบราว์เซอร์ที่แสดงลักษณะการทำงานที่ถูกต้อง คำขอช่วงจะ "ทํางานได้" เมื่อส่งผ่าน Service Worker
ปัญหาคืออะไร
ลองพิจารณา Service Worker ที่มี fetch
event listener ต่อไปนี้ ซึ่งจะรับคําขอขาเข้าทุกรายการและส่งไปยังเครือข่าย
self.addEventListener('fetch', (event) => {
// The Range: header will not pass through in
// browsers that behave incorrectly.
event.respondWith(fetch(event.request));
});
ในเบราว์เซอร์ที่มีลักษณะการทํางานไม่ถูกต้อง หาก event.request
มีส่วนหัว Range:
ระบบจะทิ้งส่วนหัวนั้นโดยอัตโนมัติ คำขอที่ได้รับจากเซิร์ฟเวอร์ระยะไกลจะไม่รวม Range:
เลย การดำเนินการนี้ไม่จําเป็นต้อง "ขัดข้อง" แต่อย่างใด เนื่องจากในทางเทคนิคแล้ว เซิร์ฟเวอร์ได้รับอนุญาตให้แสดงผลเนื้อหาการตอบกลับแบบเต็มพร้อมรหัสสถานะ 200
แม้ว่าจะมีส่วนหัว Range:
ในคําขอต้นฉบับก็ตาม แต่วิธีนี้จะทำให้มีการโอนข้อมูลมากกว่าที่จำเป็นจากมุมมองของเบราว์เซอร์
นักพัฒนาแอปที่ทราบถึงลักษณะการทำงานนี้สามารถแก้ปัญหาได้โดยการตรวจสอบว่ามีส่วนหัว Range:
อยู่หรือไม่อย่างชัดเจน และจะไม่เรียกใช้ event.respondWith()
หากมี ซึ่งการดําเนินการนี้จะช่วยให้ Service Worker ตัดตัวเองออกจากภาพรวมการสร้างการตอบกลับได้อย่างมีประสิทธิภาพ และระบบจะใช้ตรรกะการทํางานของเครือข่ายเบราว์เซอร์เริ่มต้นซึ่งทราบวิธีเก็บรักษาคําขอช่วงแทน
self.addEventListener('fetch', (event) => {
// Return without calling event.respondWith()
// if this is a range request.
if (event.request.headers.has('range')) {
return;
}
event.respondWith(fetch(event.request));
});
แต่เรามั่นใจได้ว่านักพัฒนาแอปส่วนใหญ่ไม่ทราบถึงความจำเป็นในการดำเนินการนี้ และไม่ได้อธิบายเหตุผลที่ควรกำหนดให้ต้องระบุ ท้ายที่สุดแล้ว ข้อจํากัดนี้เกิดจากเบราว์เซอร์ต้องตามทันการเปลี่ยนแปลงในข้อกําหนดพื้นฐาน ซึ่งเพิ่มการรองรับฟังก์ชันการทํางานนี้
ปัญหาที่แก้ไขแล้ว
เบราว์เซอร์ที่ทํางานอย่างถูกต้องจะเก็บรักษาส่วนหัว Range:
ไว้เมื่อมีการส่ง event.request
ไปยัง fetch()
ซึ่งหมายความว่าโค้ด Service Worker ในตัวอย่างแรกจะอนุญาตให้เซิร์ฟเวอร์ระยะไกลเห็นส่วนหัว Range:
หากเบราว์เซอร์เป็นผู้ตั้งค่า
self.addEventListener('fetch', (event) => {
// The Range: header will pass through in browsers
// that behave correctly.
event.respondWith(fetch(event.request));
});
ตอนนี้เซิร์ฟเวอร์มีโอกาสจัดการคำขอช่วงอย่างถูกต้องและแสดงการตอบกลับบางส่วนด้วยรหัสสถานะ 206
เบราว์เซอร์ใดทำงานอย่างถูกต้อง
Safari เวอร์ชันล่าสุดมีฟังก์ชันการทำงานที่ถูกต้อง Chrome และ Edge ตั้งแต่เวอร์ชัน 87 ทำงานได้อย่างถูกต้องเช่นกัน
ในเดือนตุลาคม 2020 นี้ Firefox ยังไม่ได้แก้ไขลักษณะการทำงานนี้ คุณจึงอาจต้องคำนึงถึงเรื่องนี้ขณะที่ทําให้โค้ดของ Service Worker ใช้งานได้จริง
การตรวจสอบแถว "รวมส่วนหัวช่วงในคำขอเครือข่าย" ของหน้าแดชบอร์ดการทดสอบแพลตฟอร์มเว็บเป็นวิธีที่ดีที่สุดในการยืนยันว่าเบราว์เซอร์หนึ่งๆ แก้ไขลักษณะการทำงานนี้หรือไม่
การแสดงคําขอช่วงจากแคชจะเป็นอย่างไร
เซอร์วิสเวิร์กทําได้มากกว่าแค่ส่งคําขอไปยังเครือข่าย กรณีการใช้งานที่พบบ่อยคือการเพิ่มทรัพยากร เช่น ไฟล์เสียงและวิดีโอ ลงในแคชในเครื่อง จากนั้น Service Worker จะดำเนินการตามคำขอจากแคชดังกล่าวได้โดยไม่ต้องใช้เครือข่ายเลย
เบราว์เซอร์ทั้งหมด รวมถึง Firefox รองรับการตรวจสอบคําขอภายในตัวแฮนเดิล fetch
ตรวจสอบว่ามีส่วนหัว Range:
หรือไม่ จากนั้นตอบสนองคําขอในเครื่องด้วยการตอบกลับ 206
ที่มาจากแคช อย่างไรก็ตาม โค้ด Service Worker สำหรับการแยกวิเคราะห์ส่วนหัว Range:
อย่างถูกต้องและแสดงเฉพาะส่วนที่สอดคล้องกันของการตอบกลับที่แคชไว้อย่างสมบูรณ์นั้นไม่ใช่เรื่องง่าย
แต่นักพัฒนาซอฟต์แวร์ที่ต้องการความช่วยเหลือสามารถหันมาใช้ Workbox ซึ่งเป็นชุดไลบรารีที่ลดความซับซ้อนของกรณีการใช้งาน Service Worker ทั่วไป workbox-range-request module
ใช้ตรรกะทั้งหมดที่จําเป็นในการแสดงคําตอบบางส่วนจากแคชโดยตรง ดูสูตรการใช้งานทั้งหมดสำหรับกรณีการใช้งานนี้ได้ในเอกสารประกอบของ Workbox
รูปภาพหลักในโพสต์นี้โดย Natalie Rhea Riggs จาก Unsplash