התכונה 'מטמון לדף הקודם/הבא' (או bfcache) היא אופטימיזציה של דפדפן שמאפשרת ניווט מיידי אחורה וקדימה. היא משפרת משמעותית את חוויית השימוש בדפדפן, במיוחד למשתמשים שהרשתות או המכשירים שלהם איטיים יותר.
מפתחי אתרים צריכים להבין איך מבצעים אופטימיזציה של הדפים לשימוש במטמון אחורה/קדימה, כדי שהמשתמשים יוכלו ליהנות מהיתרונות שלו.
תאימות דפדפן
כל הדפדפנים הנפוצים כוללים bfcache, כולל Chrome מגרסה 96, Firefox ו-Safari.
מידע בסיסי על bfcache
במטמון לדף הקודם/הבא (bfcache), במקום להרוס דף כשמשתמש מנווט ממנו, אנחנו דוחים את ההרס ומשהים את ביצוע ה-JS. אם המשתמש חוזר לדף במהירות, אנחנו הופכים את הדף לגלוי שוב ומבטלים את ההשהיה של ביצוע ה-JS. כך המשתמש יכול לנווט בין הדפים כמעט באופן מיידי.
כמה פעמים קרה לכם שנכנסתם לאתר מסוים ולחצתם על קישור כדי לעבור לדף אחר, ואז הבנתם שזה לא מה שרציתם ולחצתם על לחצן החזרה? במקרה כזה, המטמון לדף הקודם/הבא יכול לשפר משמעותית את מהירות הטעינה של הדף הקודם:
| ללא bfcache | מתחילה בקשה חדשה לטעינת הדף הקודם, ותלוי באיכות האופטימיזציה של הדף לביקורים חוזרים, יכול להיות שהדפדפן יצטרך להוריד מחדש, לנתח מחדש ולהפעיל מחדש חלק מהמשאבים שהוא הוריד זה עתה (או את כולם). |
| עם bfcache מופעל | טעינת הדף הקודם היא כמעט מיידית, כי אפשר לשחזר את כל הדף מהזיכרון, בלי צורך לגשת לרשת בכלל. |
כדאי לצפות בסרטון הזה כדי לראות את המטמון לדף הקודם/הבא בפעולה ולהבין איך הוא יכול לזרז את הניווטים:
בדוגמה בסרטון, המטמון bfcache מהיר משמעותית מהדוגמה בלי המטמון.
ה-bfcache לא רק מזרז את הניווט, אלא גם מצמצם את השימוש בנתונים, כי לא צריך להוריד שוב את המשאבים.
נתוני השימוש ב-Chrome מראים ש-1 מתוך 10 ניווטים במחשב ו-1 מתוך 5 בנייד הם ניווטים אחורה או קדימה. אם bfcache מופעל, דפדפנים יכולים למנוע את העברת הנתונים ואת הזמן שנדרש לטעינה של מיליארדי דפי אינטרנט בכל יום!
איך פועל ה'מטמון'
המטמון שבו נעשה שימוש ב-bfcache שונה ממטמון ה-HTTP, שגם לו יש תפקיד בזירוז של ניווטים חוזרים. bfcache הוא תמונת מצב של הדף כולו בזיכרון, כולל ה-heap של JavaScript, בעוד שמטמון ה-HTTP מכיל רק את התשובות לבקשות שבוצעו בעבר. מאחר שמאוד נדיר שכל הבקשות שנדרשות לטעינת דף יסופקו מהמטמון של HTTP, ביקורים חוזרים באמצעות שחזורים של bfcache תמיד מהירים יותר אפילו מהניווטים הכי מותאמים שלא משתמשים ב-bfcache.
הקפאת דף כדי להפעיל אותו מחדש בהמשך היא תהליך מורכב שדורש שימור של קוד בתהליך. לדוגמה, איך מטפלים בשיחות setTimeout() שבהן הגיע הזמן הקצוב לתפוגה בזמן שהדף נמצא במטמון bfcache?
התשובה היא שהדפדפנים משהים את כל הטיימרים בהמתנה או את ההבטחות שלא נפתרו בדפים במטמון bfcache, כולל כמעט כל המשימות בהמתנה בתורי המשימות של JavaScript, וממשיכים לעבד את המשימות אם הדף משוחזר מהמטמון bfcache.
במקרים מסוימים, כמו פסק זמן והבטחות, הסיכון נמוך יחסית, אבל במקרים אחרים זה עלול להוביל להתנהגות מבלבלת או לא צפויה. לדוגמה, אם הדפדפן משהה משימה שנדרשת כחלק מטרנזקציה של IndexedDB, זה יכול להשפיע על כרטיסיות פתוחות אחרות באותו מקור, כי אפשר לגשת למסדי נתונים של IndexedDB מכמה כרטיסיות בו-זמנית. כתוצאה מכך, בדרך כלל הדפדפנים לא ינסו לשמור במטמון דפים באמצע טרנזקציה של IndexedDB או בזמן שימוש בממשקי API שעשויים להשפיע על דפים אחרים.
פרטים נוספים על האופן שבו השימוש ב-API משפיע על ההתאמה של דף ל-bfcache זמינים במאמר אופטימיזציה של דפים ל-bfcache.
המטמון bfcache ומסגרות iframe
אם דף מכיל מסגרות iframe מוטמעות, המסגרות האלה לא עומדות בנפרד בדרישות לשמירה במטמון לדף הקודם/הבא. לדוגמה, אם עוברים לכתובת URL אחרת בתוך iframe, התוכן הקודם לא נכנס ל-bfcache, ואם חוזרים אחורה, הדפדפן יחזור אחורה בתוך ה-iframe ולא בפריים הראשי, אבל הניווט אחורה בתוך ה-iframe לא ישתמש ב-bfcache.
עם זאת, כשמשחזרים את המסגרת הראשית מהמטמון לדף הקודם/הבא, מסגרות iframe מוטמעות ישוחזרו כמו שהן היו כשהדף נכנס למטמון לדף הקודם/הבא.
גם השימוש ב-bfcache בפריים הראשי יכול להיחסם אם נעשה שימוש ב-API שחוסם את זה ב-iframe מוטמע. כדי למנוע את הבעיה הזו, אפשר להשתמש במדיניות ההרשאות שמוגדרת בפריים הראשי או במאפייני sandbox.
מטמון הדפדפן (bfcache) ואפליקציות בדף יחיד (SPA)
מכיוון שה-bfcache פועל עם ניווטים שמנוהלים על ידי הדפדפן, הוא לא פועל עם 'ניווטים רכים' באפליקציה של דף יחיד (SPA). עם זאת, bfcache עדיין יכול לעזור כשחוזרים ל-SPA במקום לבצע שוב אתחול מלא של האפליקציה מההתחלה.
ממשקי API לצפייה ב-bfcache
למרות שמטמון bfcache הוא אופטימיזציה שהדפדפנים מבצעים באופן אוטומטי, עדיין חשוב למפתחים לדעת מתי הוא מתרחש כדי שהם יוכלו לבצע אופטימיזציה של הדפים שלהם ולשנות את המדדים או את מדידת הביצועים בהתאם.
האירועים העיקריים שמשמשים למעקב אחרי bfcache הם אירועי מעבר בין דפים pageshow ו-pagehide, שנתמכים על ידי רוב הדפדפנים.
גם האירועים החדשים יותר של מחזור החיים של הדף – freeze ו-resume – נשלחים כשדפים נכנסים ל-bfcache או יוצאים ממנו, וגם במצבים אחרים, למשל כשכרטיסייה ברקע קופאת כדי לצמצם את השימוש במעבד. האירועים האלה נתמכים רק בדפדפנים שמבוססים על Chromium.
מעקב אחרי מקרים שבהם דף משוחזר מ-bfcache
האירוע 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.');
}
});
בדפדפנים שתומכים ב-Page Lifecycle API, האירוע resume מופעל כשדפים משוחזרים מ-bfcache (מטמון אחורי/קדימה) (מיד לפני האירוע pageshow) וכשמשתמש חוזר לכרטיסיית רקע קפואה. אם רוצים לעדכן את מצב הדף אחרי שהוא קופא (כולל דפים במטמון bfcache), אפשר להשתמש באירוע resume, אבל אם רוצים למדוד את שיעור הפגיעה במטמון bfcache באתר, צריך להשתמש באירוע 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
הדרך הכי חשובה לבצע אופטימיזציה ל-bfcache בכל הדפדפנים היא לא להשתמש אף פעם באירוע unload. אף פעם!
האירוע unload בעייתי לדפדפנים כי הוא קדם ל-bfcache, והרבה דפים באינטרנט פועלים מתוך הנחה (סבירה) שדף לא ימשיך להתקיים אחרי שהאירוע unload יופעל. זו בעיה כי הרבה מהדפים האלה נבנו גם מתוך הנחה שהאירוע unload יופעל בכל פעם שמשתמש עובר לדף אחר, אבל זה כבר לא נכון (ולא היה נכון במשך הרבה זמן).
לכן, הדפדפנים מתמודדים עם דילמה: הם צריכים לבחור בין שיפור חוויית המשתמש לבין סיכון לשבירת הדף.
במחשב, ב-Chrome וב-Firefox בחרו להוציא דפים מהרשימה של bfcache אם מוסיפים להם מאזין unload, מה שמפחית את הסיכון אבל גם מוציא מהרשימה הרבה דפים. דפדפן Safari ינסה לשמור במטמון חלק מהדפים עם מאזין אירועים מסוג unload, אבל כדי לצמצם את הסיכון לבעיות, הוא לא יפעיל את האירוע unload כשמשתמש עובר לדף אחר, ולכן אי אפשר להסתמך על האירוע הזה.
בנייד, דפדפני Chrome ו-Safari ינסו לשמור במטמון דפים עם מאזין לאירוע unload, כי הסיכון לשבירה נמוך יותר בגלל שהאירוע unload תמיד היה לא אמין במיוחד בנייד. דפדפן Firefox לא מאפשר לשמור במטמון לדף הקודם/הבא דפים שנעשה בהם שימוש ב-unload, למעט ב-iOS. ב-iOS כל הדפדפנים צריכים להשתמש במנוע העיבוד WebKit, ולכן הוא מתנהג כמו Safari.
במקום להשתמש באירוע unload, צריך להשתמש באירוע pagehide. האירוע pagehide מופעל בכל המקרים שבהם מופעל האירוע unload, וגם כשהדף מוכנס למטמון bfcache.
למעשה, ב-Lighthouse יש ביקורת no-unload-listeners, שמזהירה מפתחים אם קוד JavaScript בדפים שלהם (כולל קוד מספריות של צד שלישי) מוסיף event listener מסוג unload.
בגלל חוסר המהימנות של האירוע הזה וההשפעה שלו על הביצועים של bfcache, אנחנו ב-Chrome מתכננים להוציא משימוש את האירוע unload.
שימוש במדיניות הרשאות כדי למנוע שימוש ב-unload handlers בדף
אתרים שלא משתמשים בגורמים מטפלים באירועים של unload יכולים להשתמש במדיניות הרשאות כדי לוודא שהם לא נוספים.
Permissions-Policy: unload=()
בנוסף, כך אפשר למנוע מצדדים שלישיים או מתוספים להאט את האתר על ידי הוספת גורמים מטפלים בהסרת הנתונים שנטענו, ולמנוע מהאתר להיות כשיר לשימוש ב-bfcache.
הוספת beforeunload מאזינים רק בתנאי
האירוע beforeunload לא יגרום לכך שהדפים שלכם לא יעמדו בדרישות לשימוש ב-bfcache ב-bfcache של דפדפנים מודרניים, אבל בעבר הוא גרם לכך, והוא עדיין לא אמין, לכן מומלץ להימנע משימוש בו אלא אם הדבר הכרחי.
עם זאת, בניגוד לאירוע 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 הוגדר במשאב הדף עצמו (בניגוד לכל משאב משני), הדפדפנים בחרו לא לשמור את הדף במטמון לדף הקודם/הבא, ולכן יכול להיות שדפים שנעשה בהם שימוש ב-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 הם מיידיים, והדפים לא נשארים ב-bfcache למשך זמן רב מדי, כך שסביר להניח שהתוכן עדיין עדכני. עם זאת, אם התוכן שלכם משתנה מדי דקה, אתם יכולים לאחזר עדכונים באמצעות האירוע pageshow, כפי שמתואר בקטע הבא.
עדכון נתונים לא עדכניים או רגישים אחרי שחזור מ-bfcache
אם האתר שלכם שומר את מצב המשתמש – במיוחד מידע רגיש כלשהו על המשתמש – צריך לעדכן או לנקות את הנתונים האלה אחרי שדף משוחזר מ-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", לדף הפותח תהיה הפניה לאובייקט החלון של הדף שנפתח.
בנוסף לסיכון האבטחה, אי אפשר להכניס בבטחה דף עם הפניה window.opener שאינה null למטמון bfcache, כי זה עלול לגרום לשגיאה בכל הדפים שמנסים לגשת אליו.
לכן, מומלץ להימנע מיצירת הפניות ל-window.opener. אפשר לעשות את זה באמצעות rel="noopener" בכל הזדמנות (שימו לב, זו עכשיו ברירת המחדל בכל הדפדפנים המודרניים). אם האתר שלכם דורש פתיחת חלון ושליטה בו באמצעות window.postMessage() או הפניה ישירה לאובייקט החלון, החלון שנפתח והחלון שפתח אותו לא יעמדו בדרישות לשימוש במטמון הדפדפן.
סגירת חיבורים פתוחים לפני שהמשתמש עובר לדף אחר
כמו שצוין קודם, כשדף נשמר במטמון לדף הקודם/הבא, כל משימות ה-JavaScript המתוזמנות מושהות ומתחדשות כשהדף מוצא מהמטמון.
אם משימות ה-JavaScript המתוזמנות האלה ניגשות רק לממשקי DOM API – או לממשקי API אחרים שמבודדים רק לדף הנוכחי – השהיית המשימות האלה בזמן שהדף לא מוצג למשתמש לא תגרום לבעיות.
עם זאת, אם המשימות האלה מקושרות לממשקי API שנגישים גם מדפים אחרים באותו מקור (לדוגמה: IndexedDB, Web Locks, WebSockets), זה עלול להיות בעייתי כי השהיית המשימות האלה עלולה למנוע את הפעלת הקוד בכרטיסיות אחרות.
כתוצאה מכך, בדפדפנים מסוימים לא תהיה אפשרות להכניס דף ל-bfcache בתרחישים הבאים:
- דפים עם חיבור IndexedDB פתוח
- דפים עם fetch() או XMLHttpRequest בתהליך
- דפים עם חיבור פתוח של WebSocket או WebRTC
אם הדף שלכם משתמש באחד מהממשקי ה-API האלה, מומלץ מאוד לסגור את החיבורים ולהסיר או לנתק את האובייקטים של Observer במהלך האירוע pagehide או freeze. כך הדפדפן יכול לשמור את הדף במטמון בצורה בטוחה בלי להשפיע על כרטיסיות פתוחות אחרות.
לאחר מכן, אם הדף משוחזר מה-bfcache, אפשר לפתוח מחדש את ממשקי ה-API האלה או להתחבר אליהם מחדש במהלך האירוע pageshow או resume.
בדוגמה הבאה אפשר לראות איך לוודא שדפים שמשתמשים ב-IndexedDB עומדים בדרישות לשימוש במטמון לדף הקודם/הבא, על ידי סגירת חיבור פתוח ב-pagehide event listener:
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 יכולים לעזור לכם לבדוק את הדפים כדי לוודא שהם מותאמים ל-bfcache, ולזהות בעיות שעשויות למנוע את ההתאמה שלהם.
כדי לבדוק דף:
- עוברים לדף ב-Chrome.
- בכלי הפיתוח, עוברים אל Application -> Back-forward Cache.
- לוחצים על הלחצן הפעלת הבדיקה. לאחר מכן, כלי הפיתוח מנסים לנווט החוצה ואז לחזור כדי לקבוע אם אפשר לשחזר את הדף ממטמון bfcache.
אם הבדיקה מצליחה, בחלונית מופיעה ההודעה 'שוחזר מתוך מטמון לדף הקודם/הבא'.
אם הפעולה לא מצליחה, בלוח מופיעה הסיבה לכך. אם הסיבה היא משהו שאתם יכולים לטפל בו כמפתחים, החלונית תסמן אותה כניתנת לביצוע.
בדוגמה הזו, השימוש ב-event listener unload גורם לכך שהדף לא עומד בדרישות לשמירה במטמון לדף הקודם/הבא. כדי לפתור את הבעיה, אפשר לעבור משימוש ב-unload לשימוש ב-pagehide:
window.addEventListener('pagehide', ...);
window.addEventListener('unload', ...);
ב-Lighthouse 10.0 נוספה גם בדיקה של מטמון אחורי/קדימה, שמבצעת בדיקה דומה. מידע נוסף זמין במסמכי התיעוד בנושא ביקורת של מטמון דפים קדימה.
איך מטמון bfcache משפיע על ניתוח נתונים ומדידת ביצועים
אם אתם משתמשים בכלי ניתוח כדי למדוד את הביקורים באתר, יכול להיות שתבחינו בירידה במספר הכולל של הצפיות בדף שמדווחות כש-Chrome מפעיל את bfcache עבור יותר משתמשים.
למעשה, סביר להניח שאתם כבר מדווחים על מספר נמוך מדי של צפיות בדפים מדפדפנים אחרים שמטמיעים 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';
});
}
});
כדי לחשב את שיעור הפגיעה במטמון הדפדפן, משתמשים בערכים של back_forward ניווטים וback_forward_cache ניווטים.
חשוב להבין שיש מספר תרחישים, שלא נמצאים בשליטת בעלי האתרים, שבהם לא נעשה שימוש במטמון הדפדפן כשמנווטים אחורה או קדימה, כולל:
- כשהמשתמש יוצא מהדפדפן ומפעיל אותו מחדש
- כשהמשתמש משכפל כרטיסייה
- כשמשתמש סוגר כרטיסייה ופותח אותה מחדש
בחלק מהמקרים האלה, סוג הניווט המקורי עשוי להישמר על ידי חלק מהדפדפנים, ולכן עשוי להופיע סוג של back_forward למרות שאלה לא ניווטים מסוג 'הקודם' או 'הבא'.
גם בלי ההחרגות האלה, מטמון הדפים הקודמים יימחק אחרי תקופה מסוימת כדי לחסוך בזיכרון.
לכן, בעלי אתרים לא צריכים לצפות ליחס של 100% פגיעות במטמון bfcache לכל back_forward הניווטים. עם זאת, מדידת היחס הזה יכולה לעזור לזהות דפים שבהם הדף עצמו מונע שימוש ב-bfcache עבור שיעור גבוה של ניווטים לחזרה ולמעבר קדימה.
צוות Chrome הוסיף את NotRestoredReasons API כדי לחשוף את הסיבות לכך שדפים לא משתמשים במטמון bfcache, וכך לעזור למפתחים לשפר את שיעורי ההצלחה של bfcache. צוות Chrome גם הוסיף סוגי ניווט ל-CrUX, כך שאפשר לראות את מספר הניווטים ב-bfcache גם בלי למדוד אותו בעצמכם.
מדידת ביצועים
בנוסף, מטמון bfcache יכול להשפיע באופן שלילי על מדדי ביצועים שנאספים בשטח, במיוחד על מדדים שמודדים את זמני הטעינה של הדף.
מכיוון שהניווטים במטמון לדף הקודם/הבא משחזרים דף קיים במקום ליזום טעינה של דף חדש, המספר הכולל של טעינות הדפים שנאסף יקטן כשהמטמון לדף הקודם/הבא מופעל. עם זאת, חשוב לזכור שטעינות הדפים שמוחלפות בשחזורים ממטמון הדפדפן היו כנראה חלק מטעינות הדפים המהירות ביותר במערך הנתונים שלכם. הסיבה לכך היא שהניווט לדף הקודם ולדף הבא הוא, מעצם הגדרתו, ביקור חוזר, וטעינות חוזרות של דפים הן בדרך כלל מהירות יותר מטעינות של דפים על ידי מבקרים בפעם הראשונה (בגלל שמירה במטמון של HTTP, כפי שצוין קודם).
התוצאה היא פחות טעינות מהירות של דפים במערך הנתונים, ולכן סביר להניח שהחלוקה תהיה איטית יותר – למרות שהביצועים שהמשתמש חווה כנראה השתפרו!
יש כמה דרכים לפתור את הבעיה הזו. אחת מהן היא להוסיף הערות לכל מדדי טעינת הדף עם סוג הניווט המתאים: navigate, reload, back_forward או prerender. כך תוכלו להמשיך לעקוב אחרי הביצועים שלכם בסוגי הניווט האלה, גם אם הפיזור הכולל מוטה לכיוון השלילי. אנחנו ממליצים על הגישה הזו למדדים של טעינת דפים שלא מתמקדים במשתמש, כמו Time to First Byte (TTFB).
במקרה של מדדים שמתמקדים במשתמשים, כמו מדדי הליבה לבדיקת חוויית המשתמש באתר, עדיף לדווח על ערך שמייצג בצורה מדויקת יותר את חוויית המשתמש.
ההשפעה על מדדי הליבה לבדיקת חוויית המשתמש באתר
המדדים הבסיסיים של חוויית המשתמש מודדים את חוויית המשתמש בדף אינטרנט במגוון היבטים (מהירות טעינה, אינטראקטיביות, יציבות חזותית). מכיוון שהמשתמשים חווים שחזורים ממטמון bfcache כניווטים מהירים יותר מאשר טעינות מלאות של דפים, חשוב שהמדדים הבסיסיים של חוויית המשתמש ישקפו זאת. בסופו של דבר, למשתמש לא משנה אם bfcache הופעל או לא, אלא רק שהניווט היה מהיר.
כלים שאוספים נתונים על מדדי חוויית המשתמש הבסיסיים ומדווחים עליהם, כמו הדוח לגבי חוויית המשתמש ב-Chrome, מתייחסים לשחזורים של bfcache כאל כניסות נפרדות לדף במערך הנתונים שלהם. אין ממשקי API ייעודיים לביצועי אתרים למדידת המדדים האלה אחרי שחזור מ-bfcache, אבל אפשר להעריך את הערכים שלהם באמצעות ממשקי API קיימים לאינטרנט:
- במקרה של Largest Contentful Paint (LCP), צריך להשתמש בהפרש בין חותמת הזמן של האירוע
pageshowלבין חותמת הזמן של המסגרת המצוירת הבאה, כי כל הרכיבים במסגרת יצוירו בו-זמנית. במקרה של שחזור מ-bfcache, הערכים של LCP ו-FCP זהים. - לגבי מהירות התגובה לאינטראקציה באתר (INP), ממשיכים להשתמש ב-Performance Observer הקיים, אבל מאפסים את הערך הנוכחי של INP ל-0.
- לגבי מדד יציבות חזותית (CLS), ממשיכים להשתמש ב-Performance Observer הקיים, אבל מאפסים את ערך ה-CLS הנוכחי ל-0.
פרטים נוספים על ההשפעה של מטמון bfcache על כל מדד זמינים בדפים של מדריכי המדדים של Core Web Vitals . דוגמה ספציפית להטמעה של גרסאות bfcache של המדדים האלה מופיעה בבקשת המשיכה (PR) להוספת המדדים האלה לספריית web-vitals JS.
ספריית JavaScript web-vitals תומכת בשחזורים של bfcache במדדים שהיא מדווחת עליהם.
מקורות מידע נוספים
- Firefox Caching (bfcache in Firefox)
- Page Cache (bfcache in Safari)
- Back/forward cache: web exposed behavior (bfcache differences across browsers)
- bfcache tester (test how different APIs and events affect bfcache in browsers)
- שיפור משמעותי בביצועים: מטמון לדף הקודם/הבא בדפדפן (מחקר מקרה מ-Smashing Magazine שמראה שיפורים דרמטיים במדדי הליבה של חוויית המשתמש בעקבות הפעלת bfcache)