การจัดการคำขอช่วงใน Service Worker

ตรวจสอบว่า 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