מה המפתחים צריכים לדעת על מצבי הזיכרון ומצב החיסכון באנרגיה של Chrome

בגרסה 108 של Chrome הוספו שני מצבים חדשים, חיסכון בזיכרון וחיסכון באנרגיה, כדי לתת למשתמשים יותר שליטה על האופן שבו Chrome משתמש במשאבי המערכת שלהם.

המצבים החדשים האלה מיועדים בעיקר למשתמשים, אבל יש להם השלכות מסוימות שחשוב שמפתחי האתרים יהיו מודעים להן, כי הן עלולות להשפיע על חוויית המשתמש באתר.

בפוסט הזה נסביר על ההשפעות האפשריות של המצבים החדשים האלה, ונציג את הפעולות שמפתחי אתרים יכולים לבצע כדי להבטיח שהם מספקים את חוויית השימוש הטובה ביותר.

מצב חיסכון בזיכרון

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

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

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

Chrome משמיד כרטיסיות כדי לחסוך בזיכרון כבר שנים, אבל הוא עשה זאת רק במצבים שבהם המערכת הייתה בלחץ זיכרון. מכיוון שהאירוע הזה קורה לעיתים נדירות יחסית, יכול להיות שמפתחי אתרים לא הבינו שהוא מתרחש.

החל מגרסה 108 של Chrome, ביטול כרטיסיות יהיה נפוץ יותר, ולכן חשוב מאוד שאתרים יוכלו לטפל במקרים כאלה בצורה חלקה.

שיטות מומלצות לטיפול במחיקת כרטיסיות

סגירת כרטיסיות היא לא אתגר חדש למפתחי אתרים. תמיד היה אפשר למשתמש לטעון מחדש דף – בכוונה או בטעות – לפני השלמת המשימה. לכן תמיד היה חשוב לאתרים לאחסן את מצב המשתמש כדי שיוכלו לשחזר אותו אם המשתמש יוצא מהאתר וחוזר אליו.

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

הזמנים הטובים ביותר לשמירת מצב המשתמש הם:

  • מדי פעם, כשהמצב משתנה.
  • כשכרטיסייה מועברת ברקע (האירוע visibilitychange).

הזמנים הגרועים ביותר לשמירת מצב הם:

  • בקריאה חוזרת (callback) של אירוע beforeunload.
  • בקריאה חוזרת של אירוע unload.

אלה הזמנים הגרועים ביותר לשמירת מצב, כי האירועים האלה לא מהימנים לחלוטין ולא מופעלים במצבים רבים – כולל כשכרטיסייה מסוימת נמחקת.

אפשר לעיין בתרשים האירועים של מחזור החיים של דף כדי לראות אילו אירועים צפויים להתרחש כשדף מסוים יוסר. כפי שאפשר לראות מהתרשים הזה, כרטיסייה יכולה לעבור ממצב 'מוסתר' למצב 'נמחק', בלי להפעיל אירועים.

מצב וזרימה של אירועים ב-Page Lifecycle API. ייצוג חזותי של המצב ושל רצף האירועים שמתוארים במסמך הזה.

למעשה, בכל פעם שהדף נמצא במצב 'מוסתר', אין ערובה לכך שאירועים אחרים יופעלו לפני שהדף יוסר על ידי הדפדפן או יופסק על ידי המשתמש. לכן חשוב תמיד לשמור את מצב המשתמש שלא נשמר באירוע visibilitychange, כי יכול להיות שלא תהיה לכם הזדמנות נוספת.

הקוד הבא מציג דוגמה ללוגיקת שמירת המצב הנוכחי של המשתמש בזמן שינוי, או באופן מיידי אם המשתמש מעביר את הכרטיסייה לרקע או עובר לכרטיסייה אחרת:

let state = {};
let hasUnstoredState = false;

function storeState() {
  if (hasUnstoredState) {
    // Store `state` to localStorage or IndexedDB...
  }
  hasUnstoredState = false;
}

export function updateState(newState) {
  state = newState;
  hasUnstoredState = true;
  requestIdleCallback(storeState);
}

document.addEventListener('visibilitychange', () => {
  if (document.visibilityState === 'hidden') {
    storeState();
  }
});

זיהוי שהכרטיסייה נמחקה

כפי שצוין קודם, אי אפשר לזהות כרטיסייה שעומד להימחק, אבל אפשר לזהות כרטיסייה שנמחקה אחרי שמשתמש חוזר אליה והדף נטען מחדש. במצבים כאלה המאפיין document.wasDiscarded יתקיים.

if (document.wasDiscarded) {
  // The page was reloaded after a discard.
} else {
  // The page was not reloaded after a discard.
}

אם אתם רוצים להבין באיזו תדירות המשתמשים נתקלים בבעיות כאלה, תוכלו להגדיר את כלי הניתוח כך שיתעדו את המידע הזה.

לדוגמה, ב-Google Analytics אפשר להגדיר פרמטר אירוע מותאם אישית שיאפשר לכם לקבוע איזה אחוז מהצפיות בדפים הגיע מביטולים של כרטיסיות:

gtag('config', 'G-XXXXXXXXXX', {
  was_discarded: document.wasDiscarded,
});

אם אתם ספקי ניתוח נתונים, כדאי לכם להוסיף את המאפיין הזה למוצר כברירת מחדל.

בדיקת האתר במצב חיסכון בזיכרון

כדי לבדוק איך דף מטפל בהשלכה, אפשר לטעון את הדף ואז להיכנס לכתובת chrome://discards בכרטיסייה או בחלון נפרדים.

בממשק המשתמש של chrome://discards, אפשר לאתר את הכרטיסייה שרוצים לבטל מהרשימה, ואז ללחוץ על Urgent Discard (ביטול דחוף) בעמודה Actions (פעולות).

צילום מסך של ממשק המשתמש של chrome://discards שבו מוצג המיקום של הקישור לכרטיסיות של פריטים שנמחקו

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

לתשומת ליבכם: בשלב זה אין דרך לבצע אוטומציה של ביטול כרטיסיות באמצעות כלי בדיקה כמו webdriver או puppeteer. עם זאת, מכיוון שביטול ושחזור של כרטיסיות כמעט זהים לרענון דפים, אם בודקים שהמצב של המשתמש משוחזר אחרי רענון באמצע תהליך השימוש, סביר להניח שהבדיקה תעבוד גם במקרה של ביטול/שחזור. ההבדל העיקרי בין השניים הוא שהאירועים beforeunload,‏ pagehide ו-unload לא מופעלים כשכרטיסייה מסוימת נמחקת, כך שכל עוד אתם לא מסתמכים על האירועים האלה כדי לשמור את מצב המשתמש, אתם יכולים להשתמש בעומסים מחדש כדי לבדוק את ההתנהגות של המחיקה/השחזור.

מצב חיסכון באנרגיה

כשמצב החיסכון באנרגיה מופעל, Chrome חוסך בחיי הסוללה על ידי הפחתת קצב הרענון של המסך, דבר שמשפיע על איכות הגלילה והאנימציה ועל קצב הפריימים של הסרטונים.

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

התרחיש העיקרי שבו המצב הזה עלול לגרום לבעיות הוא אם האתר שלכם משתמש באנימציות מבוססות-JavaScript שמניחות קצב רענון מסוים לכל המשתמשים.

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

חשוב לזכור שלמפתחים תמיד הייתה בעיה להניח ששיעור הרענון שמוגדר כברירת מחדל הוא 60Hz לכל המשתמשים, כי זה לא נכון לגבי הרבה מכשירים נוכחיים.

מדידת קצב הרענון של המסך

אין ממשק API ייעודי לאינטרנט למדידת קצב הרענון של המסך, ובאופן כללי לא מומלץ לנסות לעשות זאת באמצעות ממשקי ה-API הקיימים.

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

בדיקת האתר במצב חיסכון באנרגיה

אחת הדרכים לבדוק את האתר במצב חיסכון באנרגיה היא להפעיל את המצב בהגדרות של Chrome ולהגדיר אותו לפעול כשהמכשיר לא מחובר לחשמל.

אם אין לכם מכשיר שאפשר לנתק מהחשמל, תוכלו להפעיל את המצב גם באופן ידני לפי השלבים הבאים:

  1. מפעילים את הדגל chrome://flags/#battery-saver-mode-available.
  2. נכנסים לאתר chrome://discards ולוחצים על הקישור החלפת מצב החיסכון בסוללה (חשוב: הדגל #battery-saver-mode-available צריך להיות מופעל כדי שהקישור יפעל).

צילום מסך של ממשק המשתמש של chrome://discards שבו מוצג המיקום של הקישור להפעלת מצב חיסכון באנרגיה

לאחר ההפעלה, תוכלו לבצע פעולות באתר ולוודא שהכול נראה כמו שצריך: לדוגמה, שהאנימציות והמעברים פועלים במהירות הרצויה.

סיכום

המצבים 'חיסכון בזיכרון' ו'חיסכון באנרגיה' ב-Chrome הם בעיקר תכונות שמתמקדות במשתמשים, אבל יש להן השלכות על המפתחים, כי הן עלולות להשפיע לרעה על חוויית הביקור באתר אם לא מטפלים בהן כראוי.

באופן כללי, המצבים החדשים האלה תוכננו מתוך מחשבה על השיטות המומלצות הקיימות למפתחים. אם המפתחים פועלים בהתאם לשיטות המומלצות הוותיקות באינטרנט, האתרים שלהם אמורים להמשיך לפעול בצורה תקינה במצבים החדשים האלה.

עם זאת, אם האתר שלכם מכיל אחת מהשיטות שצוינו בפוסט הזה, סביר להניח שהמשתמשים נתקלים בבעיות שיחריפו ככל שהשני המצבים האלה יהיו מופעלים.

כמו תמיד, הדרך הטובה ביותר לוודא שאתם מספקים חוויה מעולה היא לבדוק את האתר בתנאים שתואמים לאלה של המשתמשים שלכם.