ตรวจสอบว่า Service Worker ทราบสิ่งที่ต้องทำเมื่อมีการขอคำตอบบางส่วน
คำขอ HTTP บางรายการมีส่วนหัว Range:
ซึ่งบ่งชี้ว่าควรส่งคืนเฉพาะบางส่วนของทรัพยากรแบบเต็ม มักใช้สำหรับการสตรีมเนื้อหาเสียงหรือวิดีโอเพื่อให้โหลดสื่อกลุ่มเล็กๆ ได้แบบออนดีมานด์ แทนที่จะขอไฟล์ระยะไกลทั้งหมดพร้อมกัน
โปรแกรมทำงานของบริการคือโค้ด JavaScript ที่อยู่ระหว่างเว็บแอปกับเครือข่าย ซึ่งอาจสกัดกั้นคำขอของเครือข่ายขาออกและสร้างการตอบกลับให้
ที่ผ่านมา คำขอหลายช่วงและ Service Worker จะทำงานได้ไม่ดีพอ คุณจำเป็นต้องดำเนินการตามขั้นตอนพิเศษเพื่อหลีกเลี่ยงผลลัพธ์ที่ไม่ดีที่เกิดขึ้นกับโปรแกรมทำงานของคุณ โชคดีที่ตอนนี้กำลังมีการเปลี่ยนแปลง ในเบราว์เซอร์ที่แสดงลักษณะการทำงานที่ถูกต้อง คำขอช่วงจะ "ทำงานได้" เมื่อส่งผ่าน Service Worker
ปัญหาคืออะไร
ลองใช้ Service Worker ที่มี Listener เหตุการณ์ fetch
ต่อไปนี้ ซึ่งจะนำคำขอที่เข้ามาทั้งหมดและส่งต่อไปยังเครือข่าย
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()
(หากมี) เมื่อทำเช่นนี้ โปรแกรมทำงานของบริการจะนำตัวเองออกจากรูปภาพการสร้างการตอบกลับได้อย่างมีประสิทธิภาพ และใช้ตรรกะเครือข่ายเบราว์เซอร์เริ่มต้นซึ่งรู้วิธีเก็บรักษาคำขอช่วงแทน
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 ทำสิ่งต่างๆ ได้อีกมากมายนอกเหนือจากการส่งคำขอไปยังเครือข่าย กรณีการใช้งานทั่วไปคือการเพิ่มทรัพยากร เช่น ไฟล์เสียงและวิดีโอไปยังแคชในเครื่อง จากนั้น Service Worker จะดำเนินการตามคำขอจากแคชดังกล่าวได้โดยข้ามเครือข่ายทั้งหมด
เบราว์เซอร์ทั้งหมด รวมถึง Firefox รองรับการตรวจสอบคำขอภายในเครื่องจัดการ fetch
ตรวจหาการมีอยู่ของส่วนหัว Range:
จากนั้นดำเนินการตามคำขอในเครื่องด้วยการตอบกลับ 206
ที่มาจากแคช แต่โค้ด Service Worker เพื่อแยกวิเคราะห์ส่วนหัว Range:
อย่างเหมาะสมและแสดงผลเฉพาะกลุ่มที่เหมาะสมของการตอบกลับที่แคชไว้ที่สมบูรณ์นั้นไม่ใช่เรื่องสำคัญ
โชคดีที่นักพัฒนาซอฟต์แวร์ที่ต้องการความช่วยเหลือสามารถเปลี่ยนไปใช้Workbox ซึ่งเป็นชุดไลบรารีที่ช่วยให้กรณีการใช้งานของ Service Worker ทั่วไปง่ายขึ้น workbox-range-request module
จะใช้ตรรกะทั้งหมดที่จำเป็นในการตอบสนองบางส่วนโดยตรงจากแคช ดูสูตรอาหารทั้งหมดสำหรับกรณีการใช้งานนี้ได้ในเอกสารของ Workbox
รูปภาพหลักของโพสต์นี้โดย Natalie Rhea Riggs ใน Unsplash