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

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

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

תאימות דפדפן

המטמון לדף הקודם/הבא נתמך גם ב-Firefox וגם ב-Safari במשך שנים רבות, במחשבים ובניידים.

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

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

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

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

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

הסרטון הבא על bfcache בפעולה:

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

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

מטמון לדף הקודם/הבא לא רק מאיץ את הניווט, הוא גם מצמצם את השימוש בנתונים, כי לא צריך להוריד משאבים שוב.

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

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

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

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

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

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

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

המטמון לדף הקודם/הבא ומסגרות iframe

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

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

המטמון לדף הקודם/הבא ואפליקציות בדף יחיד (SPA)

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

ממשקי API לצפייה במטמון לדף הקודם/הבא

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

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

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

לראות מתי דף משוחזר ממטמון לדף הקודם/הבא

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

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 מופעל כשהדפים משוחזרים מהמטמון לדף הקודם/הבא (מיד לפני האירוע pageshow) וכשמשתמש נכנס שוב לכרטיסיית רקע שהוקפאה. אם רוצים לעדכן מצב של דף אחרי שהוא קפוא (כולל דפים במטמון לדף הקודם/הבא), אפשר להשתמש באירוע resume, אבל כדי למדוד את שיעור ההיטים של המטמון לדף הקודם/הבא של האתר, צריך להשתמש באירוע pageshow. במקרים מסוימים, יכול להיות שתצטרכו להשתמש בשניהם.

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

לראות מתי דף עובר למטמון לדף הקודם/הבא

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

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

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, אבל המשמעות היא רק שהדפדפן intends לשמור את הדף במטמון. יכול להיות שהוא עדיין יצטרך למחוק אותה, מכמה סיבות שמפורטות בהמשך.

אופטימיזציה של הדפים למטמון לדף הקודם/הבא

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

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

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

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

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

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

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

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

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

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

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

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

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

Permission-Policy: unload()

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

הוספת 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);
});
הקוד הזה מוסיף את ה-listener של beforeunload רק כשהוא צריך (ומסיר אותו כשצריך).

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

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

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

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

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

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

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

עדכון של מידע לא פעיל או רגיש אחרי שחזור 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();
  }
});

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

שחזור מודעות ומטמון לדף הקודם/הבא

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

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

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

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

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

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

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

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

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

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

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

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

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

הדוגמה הבאה מראה איך לוודא שדפים שמשתמשים ב-IndexedDB עומדים בדרישות לשמירה במטמון לדף הקודם/הבא על ידי סגירת חיבור פתוח ב-event listener של pagehide:

let dbPromise;
function openDB() {
  if (!dbPromise) {
    dbPromise = new Promise((resolve, reject) => {
      const req = indexedDB.open('my-db', 1);
      req. => req.result.createObjectStore('keyval');
      req. => reject(req.error);
      req. => 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. לוחצים על הלחצן הפעלת בדיקה. לאחר מכן, כלי הפיתוח מנסים לצאת מהדף ולחזור אליו, כדי לבדוק אם ניתן לשחזר את הדף מהמטמון לדף הקודם/הבא.
החלונית 'מטמון לדף הקודם/הבא' בכלי הפיתוח
החלונית מטמון לדף הקודם/הבא בכלי הפיתוח.

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

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

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

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

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

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

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

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

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

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

כדי לכלול שחזור של המטמון לדף הקודם/הבא בספירת הצפיות בדף, צריך להגדיר מאזינים לאירוע 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');
  }
});

מדידת יחס ההיטים של המטמון לדף הקודם/הבא

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

// 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, גם אם לא מדובר בניווטים 'הקודם'/'הבא'.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

מקורות נוספים