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

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

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

תאימות דפדפן

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

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

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

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

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

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

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

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

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

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

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

איך "המטמון" עובד

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

האירוע pageshow מופעל מיד אחרי האירוע load כשהדף נטען בפעם הראשונה ובכל פעם שהדף שוחזר מהמטמון לדף הקודם/הבא. האירוע 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.');
  }
});

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

שימוש במדיניות הרשאות כדי למנוע שימוש ברכיבי handler של הסרת נתונים שנטענו בדף

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

Permission-Policy: unload=()

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

הוספת מאזינים ל-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 כלשהו. הוא משמש למשאבים שמכילים מידע רגיש על המשתמשים, כמו דפים שמחייבים התחברות.

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

עדכון מידע מיושן או מידע אישי רגיש אחרי שחזור של המטמון לדף הקודם

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

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

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

כדי למנוע מצבים כאלה, כדאי לעדכן תמיד את הדף אחרי אירוע 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

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

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

הימנעות מקובצי עזר של window.opener

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

מערכת Lighthouse 10.0 נוספה גם ביקורת של 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');
  }
});

מדידת יחס ההיטים של 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';
    });
  }
});

חישוב של יחס ההיטים במטמון לדף הקודם/הבא לפי הספירות של back_forward ניווטים ו-back_forward_cache ניווטים.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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