מטמון לדף הקודם/הבא

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

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

תאימות דפדפן

כל הדפדפנים העיקריים כוללים bfcache, כולל Chrome מגרסה 96,‏ Firefox ו-Safari.

מידע בסיסי על bfcache

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

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

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

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

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

בסרטון, הדוגמה עם bfcache קצת יותר מהירה מהדוגמה בלעדיה.

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

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

איך פועל המטמון

'המטמון' שמשמש את המטמון לדף הקודם/הבא שונה ממטמון ה-HTTP, שממלא תפקיד משלו בהאצת ניווטים חוזרים. bfcache הוא תמונת מצב של כל הדף בזיכרון, כולל ערימת ה-JavaScript, ואילו מטמון ה-HTTP מכיל רק את התגובות לבקשות שבוצעו בעבר. מכיוון שנדיר מאוד שכל הבקשות הנדרשות לטעינה של דף ימולאו מהמטמון של HTTP, ביקורים חוזרים באמצעות שחזור של bfcache תמיד מהירים יותר גם מהניווטים שמותאמים בצורה הטובה ביותר ללא bfcache.

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

התשובה היא שהדפדפנים משהים כל שעון חול או הבטחה לא פתורה לדפים ב-bfcache, כולל כמעט כל המשימות בהמתנה בתורנויות המשימות של JavaScript, וממשיכים לעבד משימות אם הדף משוחזר מה-bfcache.

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

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

המטמון לדף הקודם/הבא ו-iframes

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

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

bfcache ואפליקציות בדף יחיד (SPA)

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

ממשקי API למעקב אחרי bfcache

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

האירועים הראשיים שמשמשים למעקב אחרי bfcache הם אירועי המעבר לדף pageshow ו-pagehide, שנתמכים ברוב הדפדפנים.

האירועים החדשים יותר של מחזור החיים של הדףfreeze ו-resume – נשלחים גם כשדפים נכנסים או יוצאים מ-bfcache, וגם במצבים מסוימים אחרים, למשל כשכרטיסייה ברקע קופאת כדי למזער את השימוש במעבד. האירועים האלה נתמכים רק בדפדפנים המבוססים על Chromium.

מעקב אחרי שחזור דף מ-bfcache

האירוע pageshow מופעל מיד אחרי האירוע load כשהדף נטען לראשונה, ובכל פעם שהדף משוחזר מ-bfcache. לאירוע pageshow יש מאפיין persisted, שמקבל את הערך true אם הדף שוחזר מהמטמון לדף הקודם/הבא, ואת הערך false במקרים אחרים. אפשר להשתמש בנכס persisted כדי להבדיל בין טעינת דפים רגילה לבין שחזור של bfcache. לדוגמה:

window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    console.log('This page was restored from the bfcache.');
  } else {
    console.log('This page was loaded normally.');
  }
});

בדפדפנים שתומכים ב-Page Lifecycle API, האירוע resume מופעל כשדפים משוחזרים מ-bfcache (מיד לפני האירוע pageshow) וכשמשתמש חוזר לכרטיסייה קפואה ברקע. אם רוצים לעדכן מצב של דף אחרי ההקפאה (כולל דפים ששמורים במטמון לדף הקודם), אפשר להשתמש באירוע resume. אבל כדי למדוד את שיעור ההיטים של האתר במטמון לדף הקודם/הבא, צריך להשתמש באירוע pageshow. במקרים מסוימים, ייתכן שתצטרכו להשתמש בשניהם.

פרטים על שיטות מומלצות למדידת bfcache זמינים במאמר איך bfcache משפיע על ניתוח נתונים ומדידה של ביצועים.

מעקב אחרי מועד הכניסה של דף ל-bfcache

האירוע pagehide מופעל כשדף מסוים פורק או כשהדפדפן מנסה להעביר אותו ל-bfcache.

לאירוע pagehide יש גם מאפיין persisted. אם הערך הוא false, אפשר להיות בטוחים שהדף הזה לא עומד להיכנס למטמון לדף הקודם/הבא. עם זאת, העובדה ש-persisted הוא true לא מבטיחה שהדף יישמר במטמון. המשמעות היא שהדפדפן מתכוון לשמור את הדף במטמון, אבל יכולים להיות גורמים אחרים שמונעים שמירת את הדף במטמון.

window.addEventListener('pagehide', (event) => {
  if (event.persisted) {
    console.log('This page *might* be entering the bfcache.');
  } else {
    console.log('This page will unload normally and be discarded.');
  }
});

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

אופטימיזציה של הדפים ל-bfcache

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

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

לעולם אל תשתמשו באירוע unload

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

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

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

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

בנייד, דפדפני Chrome ו-Safari ינסו לשמור בדפדפן דפים עם מאזין לאירועים מסוג unload, כי הסיכון לשיבושים נמוך יותר מאחר שהאירוע unload תמיד היה לא מהימן במיוחד בנייד. דפים שנעשה בהם שימוש ב-unload לא עומדים בדרישות של Firefox לשמירה במטמון לדף הקודם/הבא, מלבד ב-iOS, שבו כל הדפדפנים חייבים להשתמש במנוע הרינדור של WebKit, ולכן הוא פועל כמו Safari.

במקום להשתמש באירוע unload, צריך להשתמש באירוע pagehide. האירוע pagehide מופעל בכל המקרים שבהם האירוע unload מופעל, וגם כשדף מועבר ל-bfcache.

למעשה, ב-Lighthouse יש ביקורת no-unload-listeners, שמזהירה מפתחים אם JavaScript כלשהו בדפים שלהם (כולל קוד מספריות של צד שלישי) מוסיף unload event listener.

בגלל חוסר האמינות שלו וההשפעה על הביצועים של bfcache, אנחנו ב-Chrome שוקלים להוציא משימוש את האירוע unload.

שימוש במדיניות ההרשאות כדי למנוע שימוש בטיפולי פריקה בדף

אתרים שלא משתמשים בגורמים שמטפלים באירועים של unload יכולים להשתמש במדיניות הרשאות כדי לוודא שהם לא יתווספו.

Permission-Policy: unload=()

כך גם מונעים מצדדים שלישיים או מתוספים להאט את האתר על ידי הוספת טיפולי פריקה (unload handlers) והפיכת האתר לבלתי מתאים ל-bfcache.

הוספת מאזינים ל-beforeunload רק באופן מותנה

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

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

מה אסור לעשות
window.addEventListener('beforeunload', (event) => {
  if (pageHasUnsavedChanges()) {
    event.preventDefault();
    return event.returnValue = 'Are you sure you want to exit?';
  }
});
הקוד הזה מוסיף מאזין beforeunload ללא תנאים.
מה מותר לעשות
function beforeUnloadListener(event) {
  event.preventDefault();
  return event.returnValue = 'Are you sure you want to exit?';
};

// A function that invokes a callback when the page has unsaved changes.
onPageHasUnsavedChanges(() => {
  window.addEventListener('beforeunload', beforeUnloadListener);
});

// A function that invokes a callback when the page's unsaved changes are resolved.
onAllChangesSaved(() => {
  window.removeEventListener('beforeunload', beforeUnloadListener);
});
הקוד הזה מוסיף את אוזן beforeunload רק כשיש צורך (ומסיר אותו כשלא צריך).

צמצום השימוש ב-Cache-Control: no-store

Cache-Control: no-store היא כותרת HTTP ששרתי אינטרנט יכולים להגדיר בתגובות, ומורה לדפדפן לא לאחסן את התגובה במטמון HTTP כלשהו. הוא משמש למשאבים שמכילים מידע רגיש על המשתמשים, כמו דפים שמחייבים התחברות.

למרות ש-bfcache הוא לא מטמון HTTP, בעבר, כשהערך Cache-Control: no-store מוגדר במשאב הדף עצמו (בניגוד למשאב משנה כלשהו), הדפדפנים בחרו לא לשמור את הדף ב-bfcache. לכן, יכול להיות שדפים שנעשה בהם שימוש ב-Cache-Control: no-store לא יעמדו בדרישות לשמירה במטמון לדף הקודם/הבא. אנחנו עובדים על שינוי ההתנהגות הזו ב-Chrome באופן ששומר על הפרטיות.

מכיוון שההגדרה Cache-Control: no-store מגבילה את הזכאות של דף להשתמש במטמון לדף הקודם/הבא, צריך להגדיר אותה רק בדפים שמכילים מידע רגיש, שבהם שמירת נתונים במטמון מכל סוג שהוא לא מתאימה.

בדפים שצריך להציג בהם תמיד תוכן עדכני, והתוכן הזה לא מכיל מידע רגיש, צריך להשתמש ב-Cache-Control: no-cache או ב-Cache-Control: max-age=0. ההוראות האלה מורות לדפדפן לאמת מחדש את התוכן לפני הצגתו, והן לא משפיעות על הזכאות של דף להיכלל ב-bfcache.

חשוב לזכור שכאשר דף משוחזר מהמטמון לדף הקודם/הבא, הוא משוחזר מהזיכרון ולא מהמטמון של HTTP. כתוצאה מכך, הוראות כמו Cache-Control: no-cache או Cache-Control: max-age=0 לא נלקחות בחשבון, ולא מתבצע אימות מחדש לפני שהתוכן מוצג למשתמש.

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

עדכון נתונים לא עדכניים או רגישים אחרי שחזור של bfcache

אם האתר שומר את מצב המשתמש – במיוחד מידע רגיש של משתמשים – צריך לעדכן או לנקות את הנתונים האלה אחרי שדף משווח מ-bfcache.

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

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

כדי למנוע מצבים כאלה, כדאי לעדכן תמיד את הדף אחרי אירוע pageshow אם הערך של event.persisted הוא true:

window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    // Do any checks and updates to the page
  }
});

מומלץ לעדכן את התוכן במקום, אבל בשינויים מסוימים כדאי לאלץ טעינת מחדש מלאה. הקוד הבא בודק אם יש קובץ cookie ספציפי לאתר באירוע pageshow, ומבצע טעינה מחדש אם קובץ ה-cookie לא נמצא:

window.addEventListener('pageshow', (event) => {
  if (event.persisted && !document.cookie.match(/my-cookie)) {
    // Force a reload if the user has logged out.
    location.reload();
  }
});

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

שחזור של מודעות ו-bfcache

יכול להיות שתתפתתו לנסות להימנע משימוש ב-bfcache כדי להציג קבוצה חדשה של מודעות בכל ניווט אחורה/קדימה. עם זאת, בנוסף להשפעה על הביצועים, לא ברור אם התנהגות כזו מובילה למעורבות גבוהה יותר במודעות. יכול להיות שמשתמשים ראו מודעה שהם התכוונו לחזור אליה כדי ללחוץ עליה, אבל אם הם יטענו מחדש את הדף במקום לשחזר אותו מה-bfcache, הם לא יוכלו לעשות זאת. חשוב לבדוק את התרחיש הזה, רצוי באמצעות בדיקת A/B, לפני שמניחים הנחות.

באתרים שבהם רוצים לרענן מודעות בזמן שחזור של bfcache, אפשר לעשות זאת על ידי רענון המודעות בלבד באירוע pageshow כשהערך של event.persisted הוא true, בלי להשפיע על ביצועי הדף. מומלץ לבדוק עם ספק המודעות, אבל כאן יש דוגמה אחת לאופן שבו אפשר לעשות זאת באמצעות Google Publishing Tag.

הימנעות מהפניות ל-window.opener

בדפדפנים ישנים יותר, אם דף נפתח באמצעות window.open() מקישור עם target=_blank, בלי לציין את rel="noopener", לדף הפותח תהיה הפניה לאובייקט החלון של הדף שנפתח.

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

לכן, מומלץ להימנע מיצירת הפניות ל-window.opener. כדי לעשות זאת, צריך להשתמש ב-rel="noopener" בכל הזדמנות אפשרית (שימו לב: זוהי עכשיו ברירת המחדל בכל הדפדפנים המודרניים). אם באתר שלכם נדרש פתיחת חלון ושליטה בו באמצעות window.postMessage() או הפניה ישירה לעצם החלון, גם החלון שנפתח וגם הגורם שפתח אותו לא יעמדו בדרישות לשימוש ב-bfcache.

סגירת חיבורים פתוחים לפני שהמשתמש מנווט למקום אחר

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

אם משימות ה-JavaScript המתוזמנות האלה ניגשות רק לממשקי API של DOM – או לממשקי API אחרים שמבודדים רק לדף הנוכחי – השהיה של המשימות האלה בזמן שהדף לא גלוי למשתמש לא תגרום לבעיות.

עם זאת, אם המשימות האלה מקושרות לממשקי API שאפשר לגשת אליהם גם מדפים אחרים באותו מקור (לדוגמה: IndexedDB,‏ Web Locks,‏ WebSockets), יכול להיות שזו בעיה כי השהיית המשימות האלה עשויה למנוע את הפעלת הקוד בכרטיסיות אחרות.

כתוצאה מכך, דפדפנים מסוימים לא ינסו להעביר דף ל-bfcache בתרחישים הבאים:

אם בדף שלכם נעשה שימוש באחד מממשקי ה-API האלה, מומלץ מאוד לסגור את החיבורים ולהסיר או לנתק את המשגיחים במהלך האירוע pagehide או freeze. כך הדפדפן יכול לשמור את הדף במטמון בבטחה בלי להשפיע על כרטיסיות פתוחות אחרות.

לאחר מכן, אם הדף ישוחזר מ-bfcache, תוכלו לפתוח מחדש או להתחבר מחדש לממשקי ה-API האלה במהלך האירוע pageshow או resume.

בדוגמה הבאה מוסבר איך לוודא שדפים שמשתמשים ב-IndexedDB עומדים בדרישות לשימוש ב-bfcache, על ידי סגירת חיבור פתוח בבורר האירועים pagehide:

let dbPromise;
function openDB() {
  if (!dbPromise) {
    dbPromise = new Promise((resolve, reject) => {
      const req = indexedDB.open('my-db', 1);
      req.onupgradeneeded = () => req.result.createObjectStore('keyval');
      req.onerror = () => reject(req.error);
      req.onsuccess = () => resolve(req.result);
    });
  }
  return dbPromise;
}

// Close the connection to the database when the user leaves.
window.addEventListener('pagehide', () => {
  if (dbPromise) {
    dbPromise.then(db => db.close());
    dbPromise = null;
  }
});

// Open the connection when the page is loaded or restored from bfcache.
window.addEventListener('pageshow', () => openDB());

בדיקה כדי לוודא שאפשר לשמור את הדפים במטמון

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

כדי לבדוק דף:

  1. עוברים לדף ב-Chrome.
  2. בכלי הפיתוח, עוברים אל Application (אפליקציה) -> Back-forward Cache (מטמון 'הקודם' ו'הבא').
  3. לוחצים על הלחצן הרצת הבדיקה. לאחר מכן, כלי הפיתוח ינסה לנווט הלאה ואז לחזור כדי לקבוע אם ניתן לשחזר את הדף מהמטמון לדף הקודם/הבא.
החלונית 'מטמון לדף הקודם/הבא' ב-DevTools
החלונית Back-forward Cache ב-DevTools.

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

דיווח של כלי הפיתוח על כך שדף שוחזר בהצלחה מ-bfcache
דף ששוחזר בהצלחה.

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

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

בדוגמה הזו, השימוש ב-event listener מסוג unload הופך את הדף ללא כשיר לשמירה במטמון לדף הקודם/הבא. כדי לפתור את הבעיה, צריך לעבור משימוש ב-unload לשימוש ב-pagehide:

מה מותר לעשות
window.addEventListener('pagehide', ...);
מה אסור לעשות
window.addEventListener('unload', ...);

ב-Lighthouse 10.0 נוספה ביקורת bfcache, שמבצעת בדיקה דומה. מידע נוסף זמין במסמכי הביקורת של המטמון לדף הקודם/הבא.

איך bfcache משפיע על ניתוח הנתונים ומדידה של הביצועים

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

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

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

בדוגמה הבאה מוסבר איך לעשות זאת באמצעות Google Analytics. סביר להניח שכלים אחרים לניתוח נתונים משתמשים בלוגיקה דומה:

// Send a pageview when the page is first loaded.
gtag('event', 'page_view');

window.addEventListener('pageshow', (event) => {
  // Send another pageview if the page is restored from bfcache.
  if (event.persisted) {
    gtag('event', 'page_view');
  }
});

מדידת יחס ההיטים של bfcache

כדאי גם למדוד אם נעשה שימוש ב-bfcache, כדי לזהות דפים שלא משתמשים ב-bfcache. כדי לעשות זאת, אפשר למדוד את סוג הניווט בטעינות הדף:

// Send a navigation_type when the page is first loaded.
gtag('event', 'page_view', {
   'navigation_type': performance.getEntriesByType('navigation')[0].type;
});

window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    // Send another pageview if the page is restored from bfcache.
    gtag('event', 'page_view', {
      'navigation_type': 'back_forward_cache';
    });
  }
});

כדי לחשב את יחס ההיטים של bfcache, משתמשים בספירה של back_forward ניווטים ושל back_forward_cache ניווטים.

חשוב להבין שיש כמה תרחישים, מחוץ לשליטה של בעלי האתר, שבהם ניווט לדף הקודם/הבא לא ישתמש במטמון לדף הקודם/הבא, כולל:

  • כשהמשתמש יוצא מהדפדפן ומפעיל אותו מחדש
  • כשהמשתמש מעתיק כרטיסייה
  • כשהמשתמש סוגר כרטיסייה ופותח אותה מחדש

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

גם בלי ההחרגות האלה, הנתונים ב-bfcache יוסרו אחרי פרק זמן כדי לחסוך בזיכרון.

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

צוות Chrome הוסיף את NotRestoredReasons API כדי לעזור לחשוף את הסיבות לכך שדפים לא משתמשים ב-bfcache, וכך למפתחים תהיה אפשרות לשפר את שיעורי ההיט של bfcache. צוות Chrome גם הוסיף סוגים של ניווט ל-CrUX, כך שאפשר לראות את מספר הניווטים ב-bfcache גם בלי למדוד אותם בעצמכם.

מדידת ביצועים

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

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

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

יש כמה דרכים לטפל בבעיה הזו. אחת מהן היא להוסיף הערות לכל מדדי טעינת הדף עם סוג הניווט המתאים: navigate,‏ reload,‏ back_forward או prerender. כך תוכלו להמשיך לעקוב אחרי הביצועים שלכם בסוגי הניווט האלה, גם אם הנתונים הכוללים נוטים לרעה. אנחנו ממליצים על הגישה הזו למדדי טעינת דפים שלא ממוקדים במשתמש, כמו Time to First Byte (TTFB) (זמן עד בייט אחד).

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

ההשפעה על מדדי הליבה לבדיקת חוויית המשתמש באתר

מדדי הליבה לבדיקת חוויית המשתמש באתר מודדים את חוויית המשתמש בדף אינטרנט במגוון מימדים (מהירות הטעינה, אינטראקטיביות ויציבות חזותית). המשתמשים חווים שחזור מהיר של המטמון לדף הקודם/הבא כניווט מהיר יותר מאשר טעינה מלאה של דף, ולכן חשוב שהמדדים של Core Web Vitals ישקפו זאת. אחרי הכול, למשתמש לא אכפת אם התכונה 'מטמון לדף הקודם/הבא' הופעלה או לא, הוא רק מעוניין שהניווט היה מהיר!

כלים שאוספים את מדדי Core Web Vitals ומדווחים עליהם, כמו הדוח לגבי חוויית המשתמש ב-Chrome, מתייחסים לשחזור של bfcache ככניסות נפרדות לדף במערך הנתונים שלהם. למרות שאין ממשקי API ייעודיים למדידת ביצועים באינטרנט למדידת המדדים האלה אחרי שחזור של המטמון לדף הקודם/הבא, אפשר להעריך את הערכים שלהם באמצעות ממשקי API קיימים לאינטרנט:

  • במדד Largest Contentful Paint ‏(LCP), משתמשים בדלתא בין חותמת הזמן של האירוע pageshow לבין חותמת הזמן של המסגרת המוצגת הבאה, כי כל הרכיבים במסגרת יוצגו באותו זמן. במקרה של שחזור של bfcache, הערכים של LCP ו-FCP זהים.
  • לגבי המדד מהירות התגובה לאינטראקציה באתר (INP), ממשיכים להשתמש במדד הנוכחי למעקב אחר ביצועים, אבל מאפסים את ערך ה-INP הנוכחי ל-0.
  • במדד Cumulative Layout Shift‏ (CLS), ממשיכים להשתמש במדד המעקב אחר הביצועים הקיים, אבל מאפסים את ערך ה-CLS הנוכחי ל-0.

פרטים נוספים על האופן שבו bfcache משפיע על כל מדד זמינים בדפי המדריך של המדדים של Core Web Vitals. דוגמה ספציפית לאופן השימוש בגרסאות bfcache של המדדים האלה זמינה במאמר PR מוסיפים אותן לספריית JS של vitals באינטרנט.

ספריית JavaScript של web-vitals תומכת בשחזור של bfcache במדדים שהיא מדווחת עליהם.

משאבים נוספים