שיפור לסגירת דף ב-XMLHttpRequest() סינכרוני

צמצום הניווטים באיחור

ג'ו מדלי
ג'ו מדלי

לעיתים קרובות, דף או אפליקציה כוללים ניתוח נתונים או נתונים אחרים שלא נשלחו כשהמשתמש סוגר אותם. כדי למנוע אובדן נתונים, חלק מהאתרים משתמשים בקריאה סינכרונית ל-XMLHttpRequest() כדי שהדף או האפליקציה יישארו פתוחים עד שהנתונים שלהם יועברו לשרת. לא רק שיש דרכים טובות יותר לחסוך נתונים, אלא שהשיטה הזו גורמת לחוויית משתמש גרועה על ידי עיכוב סגירת הדף למשך עד מספר שניות.

השיטה הזו צריכה להשתנות והדפדפנים מגיבים. המפרט של XMLHttpRequest() כבר מיועד להוצאה משימוש והסרה. גרסת Chrome 80 מבצעת את השלב הראשון בכך שאוסרת על קריאות סינכרוניות בתוך כמה גורמים מטפלים באירועים, באופן ספציפי beforeunload, unload, pagehide ו-visibilitychange כשהן מופעלות בסגירה. לאחרונה גם ל-WebKit יש מחויבות שמיישמת את אותו שינוי בהתנהגות.

במאמר הזה אתאר בקצרה את האפשרויות שזמינות לאלה שצריכים זמן לעדכון האתרים שלהם ואת החלופות ל-XMLHttpRequest().

ביטולי הסכמה זמניים

Chrome לא רוצה פשוט לנתק את השקע ב-XMLHttpRequest(), ולכן יש כמה אפשרויות לביטול הסכמה זמני. לאתרים באינטרנט, יש גרסת מקור לתקופת ניסיון. באמצעות כך, מוסיפים לכותרות הדפים אסימון ספציפי למקור, שמאפשר קריאות סינכרוניות XMLHttpRequest(). האפשרות הזו מסתיימת זמן קצר לפני שהגרסה של Chrome 89 יצאה לדרך, מתישהו במרץ 2021. לקוחות ארגוניים של Chrome יכולים גם להשתמש בדגל המדיניות AllowSyncXHRInPageDismissal, שמסתיים באותו זמן.

חלופות

לא משנה איך אתם שולחים את הנתונים חזרה לשרת, עדיף להימנע מהמתנה עד להסרת כל הנתונים על מנת לשלוח את כל הנתונים בבת אחת. מעבר ליצירת חוויית משתמש גרועה, הסרת הנתונים שנטענו היא לא אמינה בדפדפנים מודרניים, ומסתכן באובדן נתונים אם משהו משתבש. באופן ספציפי, אירועים של הסרת הנתונים שנטענו לא מופעלים בדפדפנים בניידים כי יש הרבה דרכים לסגור כרטיסייה או דפדפן במערכות הפעלה לנייד ללא הפעלת האירוע unload. עם XMLHttpRequest(), הבחירה במטענים ייעודיים קטנים הייתה. עכשיו זו דרישה. לשתי החלופות יש מגבלת העלאה של 64KB לכל הקשר, בהתאם לנדרש במפרט.

אחזור הודעת keep-alive

ה-Fetch API מספק אמצעי חזק להתמודדות עם אינטראקציות עם שרת וממשק עקבי לשימוש בממשקי API שונים של הפלטפורמה. אחת מהאפשרויות היא keepalive, מה שמבטיח שהבקשה תמשיך לפעול גם אם הדף שגרם לה להישאר פתוח וגם אם לא:

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

לשיטה fetch() יש יתרון רב יותר – שליטה רבה יותר על מה שנשלח לשרת. מה שאני לא מציג בדוגמה הזו זה גם ש-fetch() מחזיר הבטחה שמסתיימת עם אובייקט Response. מכיוון שאני מנסה להימנע מהסרת הנתונים שנטענו לדף, בחרתי לא לעשות שום דבר.

SendBeacon()

SendBeacon() משתמש בפועל ב-Fetch API, ולכן יש לו את אותה מגבלת מטען ייעודי (payload) של 64KB, וגם מבטיח שהבקשה תמשיך אחרי הסרת הדף. היתרון העיקרי שלה הוא הפשטות שלו. כך אפשר לשלוח את הנתונים בשורת קוד אחת:

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

סיכום

בעקבות הזמינות המוגברת של fetch() בדפדפנים, אנחנו מקווים ש-XMLHttpRequest() יוסר מפלטפורמת האינטרנט בשלב כלשהו. ספקי הדפדפנים מסכימים שצריך להסיר אותם, אבל זה ייקח זמן. הוצאה משימוש של אחד מהתרחישים הגרועים ביותר היא הצעד הראשון לשיפור חוויית המשתמש לכולם.

צילום של מטיו המילטון ב-UnFlood