ช่วงทดลองใช้จากต้นทางAPI ของFetchLater

Brendan Kenny
Brendan Kenny

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

เดิมทีนักพัฒนาซอฟต์แวร์ใช้เหตุการณ์ pagehide และ visibilitychange เพื่อจับหน้าเว็บขณะที่ระบบยกเลิกการโหลด จากนั้นใช้ navigator.sendBeacon() หรือ fetch() ที่มี keepalive เพื่อส่งข้อมูลบีคอน อย่างไรก็ตาม เหตุการณ์ทั้ง 2 รายการนี้มีปัญหาเฉพาะที่ยากซึ่งแตกต่างกันไปตามเบราว์เซอร์ของผู้ใช้ และบางครั้งเหตุการณ์อาจไม่เกิดขึ้นเลย โดยเฉพาะบนอุปกรณ์เคลื่อนที่

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

fetchLater() พร้อมใช้งานใน Chrome สำหรับการทดสอบกับผู้ใช้จริงในช่วงทดลองใช้จากต้นทางตั้งแต่เวอร์ชัน 121 (เปิดตัวในเดือนมกราคม 2024) จนถึงวันที่ 3 กันยายน 2024

fetchLater() API

const fetchLaterResult = fetchLater(request, options);

fetchLater() รับอาร์กิวเมนต์ 2 แบบ ซึ่งโดยทั่วไปจะเหมือนกับอาร์กิวเมนต์ของ fetch() ดังนี้

  • request ซึ่งเป็น URL สตริงหรืออินสแตนซ์ Request
  • ออบเจ็กต์ options ที่ไม่บังคับ ซึ่งขยาย options จาก fetch() ด้วยระยะหมดเวลาที่เรียกว่า activateAfter

fetchLater() จะแสดงผล FetchLaterResult ซึ่งมีพร็อพเพอร์ตี้ activated แบบอ่านอย่างเดียวรายการเดียวในปัจจุบัน ซึ่งจะตั้งค่าเป็น true เมื่อ "ภายหลัง" ผ่านไปแล้วและดึงข้อมูลแล้ว ระบบจะทิ้งการตอบกลับคำขอ fetchLater()

request

การใช้งานที่ง่ายที่สุดคือ URL เพียงอย่างเดียว ดังนี้

fetchLater('/endpoint/');

แต่เช่นเดียวกับ fetch() คุณสามารถตั้งค่าตัวเลือกจํานวนมากในคําขอ fetchLater() ซึ่งรวมถึงส่วนหัวที่กําหนดเอง ลักษณะการทํางานของข้อมูลเข้าสู่ระบบ POST body และ AbortController signal เพื่อยกเลิกคําขอได้

fetchLater('/endpoint/', {
  method: 'GET',
  cache: 'no-store',
  mode: 'same-origin',
  headers: {Authorization: 'SUPER_SECRET'},
});

options

ออบเจ็กต์ตัวเลือกจะขยายตัวเลือกของ fetch() ด้วยระยะหมดเวลา activateAfter ในกรณีที่คุณต้องการให้คำขอเริ่มทำงานหลังจากหมดเวลา หรือเมื่อหน้าเว็บยกเลิกการโหลด ขึ้นอยู่กับว่ากรณีใดจะเกิดขึ้นก่อน

ซึ่งจะช่วยให้คุณตัดสินใจได้ว่าต้องการรับข้อมูลในนาทีสุดท้ายที่เป็นไปได้หรือเมื่อข้อมูลนั้นมีความทันท่วงทีมากกว่า

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

const hourInMilliseconds = 60 * 60 * 1000;
fetchLater('/endpoint/', {activateAfter: hourInMilliseconds});

ตัวอย่างการใช้งาน

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

อย่างไรก็ตาม คุณไม่ต้องการเสี่ยงที่จะสูญเสียข้อมูลประสิทธิภาพทั้งหมดเนื่องจากบีคอนทำงานผิดพลาดหรือไม่สมบูรณ์เมื่อหน้าเว็บปิด เหมาะสำหรับ fetchLater()

ในตัวอย่างนี้ ไลบรารี web-vitals.js จะใช้เพื่อตรวจสอบเมตริก และใช้ fetchLater() ในการรายงานผลลัพธ์ไปยังปลายทางข้อมูลวิเคราะห์

import {onCLS, onINP, onLCP} from 'web-vitals';

const queue = new Set();
let fetchLaterController;
let fetchLaterResult;

function updateQueue(metricUpdate) {
  // If there was an already complete request for whatever
  // reason, clear out the queue of already-sent updates.
  if (fetchLaterResult?.activated) {
    queue.clear();
  }

  queue.add(metricUpdate);

  // JSON.stringify used here for simplicity and will likely include
  // more data than you need. Replace with a preferred serialization.
  const body = JSON.stringify([...queue]);

  // Abort any existing `fetchLater()` and schedule a new one with
  // the update included.
  fetchLaterController?.abort();
  fetchLaterController = new AbortController();
  fetchLaterResult = fetchLater('/analytics', {
    method: 'POST',
    body,
    signal: fetchLaterController.signal,
    activateAfter: 60 * 60 * 1000, // Timeout to ensure timeliness.
  });
}

onCLS(updateQueue);
onINP(updateQueue);
onLCP(updateQueue);

ทุกครั้งที่มีการอัปเดตเมตริก ระบบจะยกเลิกfetchLater()ที่กำหนดเวลาไว้ด้วย AbortController และสร้าง fetchLater() ใหม่พร้อมการอัปเดตดังกล่าว

ลองใช้ fetchLater()

ตามที่ได้แจ้งไว้ก่อนหน้านี้ fetchLater() มีให้บริการในช่วงทดลองใช้จากต้นทางจนถึง Chrome 126 ดูข้อมูลเบื้องต้นเกี่ยวกับการทดลองใช้ต้นทางได้ที่ "เริ่มต้นใช้งานการทดลองใช้ต้นทาง"

สำหรับการทดสอบในเครื่อง คุณสามารถเปิดใช้ fetchLater ด้วยแฟล็กฟีเจอร์แพลตฟอร์มเว็บแบบทดลองที่ chrome://flags/#enable-experimental-web-platform-features นอกจากนี้ คุณยังเปิดใช้ได้โดยเรียกใช้ Chrome จากบรรทัดคำสั่งด้วย --enable-experimental-web-platform-features หรือ Flag --enable-features=FetchLaterAPI ที่มุ่งเน้นมากขึ้น

หากคุณใช้ในหน้าสาธารณะ อย่าลืมใช้ฟีเจอร์โดยตรวจสอบว่ามีการกำหนด fetchLater ส่วนกลางหรือไม่ก่อนใช้งาน

if (globalThis.fetchLater) {
  // Set up beaconing using fetchLater().
  // ...
}

ความคิดเห็น

ความคิดเห็นของนักพัฒนาซอฟต์แวร์มีความสำคัญต่อการสร้าง API ของเว็บใหม่ๆ อย่างถูกต้อง ดังนั้นโปรดยื่นปัญหาและความคิดเห็นเกี่ยวกับ GitHub

ข้อมูลเพิ่มเติม