การปรับปรุงการปิดหน้าเว็บใน XMLHttpRequest() พร้อมกัน

การลดการนำทางที่ล่าช้า

โจ เมดเลย์
โจ เมดเลย์

เป็นเรื่องปกติที่หน้าเว็บหรือแอปจะมีการวิเคราะห์หรือข้อมูลอื่นๆ ที่ยังไม่ได้ส่งในขณะที่ผู้ใช้ปิดหน้านั้น เพื่อป้องกันข้อมูลสูญหาย บางเว็บไซต์ใช้การเรียก XMLHttpRequest() แบบพร้อมกันเพื่อเปิดหน้าหรือแอปไว้จนกว่าข้อมูลจะส่งผ่านไปยังเซิร์ฟเวอร์ วิธีนี้ไม่เพียงแต่เป็นวิธีที่ดีกว่าในการบันทึกข้อมูลเท่านั้น แต่เทคนิคนี้ยังสร้างประสบการณ์ที่ไม่ดีแก่ผู้ใช้ด้วยการเลื่อนการปิดหน้าเว็บออกไปเป็นเวลาหลายวินาที

แนวทางปฏิบัตินี้ต้องเปลี่ยนแปลงและเบราว์เซอร์ก็ตอบสนองได้ ทั้งนี้ ข้อกำหนดของ XMLHttpRequest() มีกำหนดที่จะเลิกใช้งานและนำออกแล้ว Chrome 80 เริ่มขั้นตอนแรกโดยไม่อนุญาตให้ใช้การเรียกแบบซิงโครนัสภายในเครื่องจัดการเหตุการณ์หลายรายการ โดยเฉพาะ beforeunload, unload, pagehide และ visibilitychange เมื่อมีการเริ่มทำงานในช่วงปิด นอกจากนี้ เมื่อเร็วๆ นี้ WebKit ยังได้รับสัญญาผูกมัดที่ใช้การเปลี่ยนแปลงลักษณะการทำงานเดียวกันนี้

ในบทความนี้ เราจะอธิบายตัวเลือกคร่าวๆ สำหรับผู้ที่ต้องการเวลาอัปเดตเว็บไซต์ และสรุปตัวเลือกต่างๆ ที่ใช้แทน XMLHttpRequest()

การเลือกไม่ใช้ชั่วคราว

Chrome ไม่เพียงต้องการดึงปลั๊กบน XMLHttpRequest() เท่านั้น จึงมีตัวเลือกการเลือกไม่ใช้ชั่วคราวบางส่วนให้ใช้งาน สำหรับเว็บไซต์บนอินเทอร์เน็ตจะมีช่วงทดลองใช้จากต้นทาง พร้อมให้ใช้งาน คุณจึงเพิ่มโทเค็นเฉพาะต้นทางลงในส่วนหัวของหน้าเว็บที่เปิดใช้การเรียกใช้ XMLHttpRequest() แบบพร้อมกัน ตัวเลือกนี้จะสิ้นสุดในไม่ช้าก่อนที่ Chrome 89 จะจัดส่ง ซึ่งในช่วงเดือนมีนาคม 2021 ลูกค้า Chrome Enterprise ยังใช้แฟล็กนโยบาย AllowSyncXHRInPageDismissal ได้ด้วย ซึ่งจะสิ้นสุดพร้อมกัน

ตัวเลือกอื่นๆ

ไม่ว่าคุณจะส่งข้อมูลกลับไปที่เซิร์ฟเวอร์ด้วยวิธีใด คุณควรหลีกเลี่ยงการรอจนหน้ายกเลิกการโหลดเพื่อส่งข้อมูลทั้งหมดพร้อมกัน นอกจากจะสร้างประสบการณ์ที่ไม่ดีแก่ผู้ใช้แล้ว การยกเลิกการโหลดยังไม่น่าเชื่อถือในเบราว์เซอร์สมัยใหม่ และยังมีความเสี่ยงที่จะสูญเสียข้อมูลหากมีข้อผิดพลาดอีกด้วย กล่าวคือ เหตุการณ์การยกเลิกการโหลดมักไม่เริ่มทำงานบนเบราว์เซอร์ในอุปกรณ์เคลื่อนที่เนื่องจากมีหลายวิธีในการ ปิดแท็บหรือเบราว์เซอร์ในระบบปฏิบัติการบนอุปกรณ์เคลื่อนที่โดยที่เหตุการณ์ unload ไม่เริ่มทำงาน การใช้เพย์โหลดขนาดเล็กกับ XMLHttpRequest() เป็นทางเลือกอย่างหนึ่ง ทีนี้เราจำเป็นต้องมีข้อกำหนด โดยทั้ง 2 ทางเลือกมีขีดจำกัดการอัปโหลดอยู่ที่ 64 KB ต่อบริบทตามข้อกำหนด

ดึงข้อมูล Keepalive

API การดึงข้อมูลเป็นวิธีที่มีประสิทธิภาพในการจัดการกับการโต้ตอบของเซิร์ฟเวอร์และอินเทอร์เฟซที่สอดคล้องกันสำหรับใช้กับ API ของแพลตฟอร์มต่างๆ ตัวอย่างของตัวเลือก ได้แก่ keepalive ซึ่งจะช่วยให้มั่นใจได้ว่าคำขอจะยังอยู่ต่อไปไม่ว่าหน้าเว็บที่ทำให้เปิดอยู่หรือไม่ ดังนี้

window.addEventListener('unload', {
  fetch('/siteAnalytics', {
    method: 'POST',
    body: getStatistics(),
    keepalive: true
  });
}

เมธอด fetch() มีข้อดีคือการควบคุมข้อความที่ส่งไปยังเซิร์ฟเวอร์ได้มากกว่า สิ่งที่ผมไม่แสดงในตัวอย่างคือ fetch() จะแสดงคำสัญญาที่แปลงด้วยออบเจ็กต์ Response ด้วย เนื่องจากฉันพยายามออกจากการ ยกเลิกการโหลดหน้าเว็บ ฉันจึงเลือกที่จะไม่ดำเนินการใดๆ

SendBeacon()

SendBeacon() ใช้ API การดึงข้อมูลในระบบจริงๆ จึงมีข้อจำกัดด้านเพย์โหลด 64 KB แบบเดียวกันนี้ และในขณะเดียวกันก็ช่วยให้มั่นใจได้ว่าคำขอจะดำเนินต่อไปหลังยกเลิกการโหลดหน้าเว็บ ข้อดีหลักๆ ของผลิตภัณฑ์นี้ก็คือความเรียบง่าย ซึ่งจะช่วยให้คุณส่งข้อมูลด้วยรหัสบรรทัดเดียวได้ ดังนี้

window.addEventListener('unload', {
  navigator.sendBeacon('/siteAnalytics', getStatistics());
}

บทสรุป

เนื่องจากความพร้อมใช้งานของ fetch() ในเบราว์เซอร์ต่างๆ เพิ่มมากขึ้น XMLHttpRequest() อาจถูกนำออกจากแพลตฟอร์มเว็บในบางกรณี ผู้ให้บริการเบราว์เซอร์ยอมรับว่าควรนำออก แต่ก็ต้องใช้เวลา การเลิกใช้หนึ่งในกรณีการใช้งานที่แย่ที่สุดคือขั้นแรกซึ่งจะปรับปรุงประสบการณ์ของผู้ใช้สำหรับทุกคน

รูปภาพโดย Matthew Hamilton ใน Unsplash