טיפים לעבודה יעילה עם bfcache
אחד הטריקים של דפדפן כדי להציג עמודים מהר יותר נקרא bfcache. זה בעצם זיכרון מטמון בו הדפדפן שומר את העמוד ואת כל מצב ה JavaScript של העמוד ביציאה ממנו, כאילו העמוד עדיין פעיל באיזה "טאב" נסתר. בלחיצה על כפתור "אחורה" הדפדפן מושך מהמטמון את העמוד ואת כל זיכרון ה JavaScript כדי שמשתמשים יוכלו להמשיך לעבוד על העמוד במהירות ומאותה נקודה.
בתור מתכנתים אנחנו שמחים על כל התנהגות של הדפדפן שמאיצה את האתרים שלנו, אבל גם צריכים להיות מודעים לכמה אתגרים ספציפיים סביב טעינת עמוד מ bfcache.
1. המחשת השימוש ב bfcache
היכנסו לקישור הבא: https://cdpn.io/pen/debug/JjegWao
תוכלו לראות שם מספרים יורדים מ 9 עד 1, ואז במקום 0 יופיע טקסט ומתחת לטקסט יש לינק. לוחצים על הלינק ואז לוחצים "אחורה" בדפדפן, ותוכלו לראות שהדפדפן לא יריץ את המספרים אחורה שוב וישר יציג את הטקסט, בדיוק מהנקודה בה עצרנו.
זה קוד העמוד אגב מוטמע כאן:
2. איך יודעים אם העמוד נטען מה Cache
דפדפנים מספקים לנו API כדי להבין איך העמוד נטען והאם הוא הגיע מה cache. האירוע pageshow
יישלח ל window מיד אחרי load
ובכל פעם שהעמוד נטען מה Cache. לאירוע זה יש מאפיין בשם persisted
, ואם ערכו true אנחנו יודעים שהעמוד הגיע מה cache. בעזרת אירוע זה אני יכול להציג הודעה ספציפית למשתמש שהגיע אחרי לחיצה על כפתור "אחורה", כמו בדוגמה הבאה:
https://cdpn.io/pen/debug/BaGXWGJ
קוד הדוגמה:
let countdown = 10;
function tick() {
countdown -= 1;
if (countdown > 0) {
document.getElementById("app").innerHTML = `${countdown}`;
return setTimeout(tick, 1000);
}
document.getElementById("app").innerHTML = `
<h1>Hello Vanilla!</h1>
<div>
We use the same configuration as Parcel to bundle this sandbox, you can find more
info about Parcel
<a href="https://parceljs.org" target="_blank" rel="noopener noreferrer">here</a>.
</div>
`;
}
window.addEventListener('pageshow', (ev) => {
console.dir(ev);
if (ev.persisted) {
// page loaded from cache after "back"
document.getElementById("app").innerHTML = `Did you find what you were looking for?`
}
});
setTimeout(tick, 0);
3. איך לגרום לעמוד לא להיטען מה Cache
יש מספר דברים שאנחנו יכולים לעשות בעמוד שימנעו מדפדפן לשמור את העמוד שלנו ב bfcache, ולכן רוב הזמן אלה דברים שנרצה להימנע מהם:
רוב הדפדפנים לא ישמרו את העמוד ב bfcache אם מוגדר קוד טיפול באירוע unload.
דפדפן פיירפוקס לא ישמור את העמוד ב bfcache אם מוגדר קוד טיפול באירוע beforeunload.
דפדפנים לא ישמרו את העמוד ב bfcache אם השרת שולח את הכותרת
Cache-Control: no-store
.חלק מהדפדפנים לא ישמרו עמוד ב bfcache אם יש לו חיבורים פתוחים או בקשות רשת פתוחות (לדוגמה חיבור ל IndexDB, ממתין לתשובה של fetch, ממתין לתשובה של
XMLHttpRequest
או מחזיקWebSocket
פתוח). אירוע בשםpagehide
יישלח לעמוד שלכם בדיוק לפני שמשתמשים גולשים החוצה ממנו, ואתם יכולים להשתמש באירוע זה כדי לסגור חיבורים ולבטל בקשות פתוחות.
בדוגמה האחרונה אני משתמש באירוע pagehide כדי להחזיר את שעון ה 10 שניות למצבו המקורי, ומתחיל להריץ את השעון אחורה באירוע pageshow במקום בטעינה של העמוד. בצורה כזאת העמוד עדיין נטען מה bfcache, אבל בניווט אחורה אליו משתמשים יצטרכו לחכות שוב 10 שניות עד שיראו את התוכן:
https://cdpn.io/pen/debug/vYQoxMx
הקוד:
let countdown = 10;
function tick() {
countdown -= 1;
if (countdown > 0) {
document.getElementById("app").innerHTML = `${countdown}`;
return setTimeout(tick, 1000);
}
document.getElementById("app").innerHTML = `
<h1>Hello Vanilla!</h1>
<div>
We use the same configuration as Parcel to bundle this sandbox, you can find more
info about Parcel
<a href="https://parceljs.org" target="_blank" rel="noopener noreferrer">here</a>.
</div>
`;
}
window.addEventListener('pagehide', (ev) => {
countdown = 10;
document.getElementById("app").innerHTML = `${countdown}`
});
window.addEventListener('pageshow', (ev) => {
setTimeout(tick, 0);
});