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

Brendan Kenny
Brendan Kenny

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

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

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

fetchLater() พร้อมใช้งานใน Chrome สำหรับการทดสอบกับผู้ใช้จริงหลังช่วงทดลองใช้จากต้นทาง โดยเริ่มตั้งแต่เวอร์ชัน 121 (เปิดตัวในเดือนมกราคม 2024) ซึ่งใช้ได้ถึง Chrome 126 (กรกฎาคม 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 และ AbortController signal ที่อาจยกเลิกได้

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

options

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

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

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

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 หรือแฟล็ก --enable-features=FetchLaterAPI ที่ตรงเป้าหมายมากขึ้นได้ด้วย

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

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

ความคิดเห็น

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

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