ה-cache של הדפדפן הוא אחד מהעזרים הכי גדולים שלנו בכל מה שקשור למהירות ושליטה בביצועים אבל גם יכול להיות מוקד לצרות צרורות עבור מפתחי פרונט אנד. בשנים האחרונות יש לנו יכולות שליטה חדשות ומעניינות ב-cache של הדפדפן באופן שמקל עלינו מאוד בסיטואציות מסוימות.
נכון, רוב הפעמים אנו חיים בעולם שבו אנו לא צריכים להסתכל על ה-cache של הדפדפן. דוגמאות טובות הן למשל קובץ שהשרת עובד עליו ממש קשה ואנו רוצים שמי שביקש אותו ונכנס שוב פעם לדף – שהקובץ יהיה זמין לו. או למשל תמונה גדולה שיכולה לסתום את התעבורה ללקוח או כל קובץ אחר שפשוט חוזר על עצמו ואנו מעונינים מכל מיני סיבות להכניס אותו ל-cache של הדפדפן.
כשמשאב מסוים – בין אם מדובר בתמונה, וידאו או אפילו HTML נמצא בתוך הדפדפן – זה אומר שברגע שמשהו בדפדפן (סקריפט, לחיצה על קישור) מבקש את המשאב הזה – הדפדפן לא שולח את הבקשה ברשת אלא מביא אותו מייד מהזכרון שלו. על מנת לסמן למפתחים שמדובר בבקשה שלא נשלחה, היא כביכול "חוזרת" עם 304.
אם אני רוצה לבחון בכלי המפתחים מה יש לי ב-cache של הדפדפן – אני צריך לפתוח את לשונית ה-application בכלי המפתחים של כרום או storage בכלי המפתחים של פיירפוקס. עשו זאת באתר של גוגל ותראו מה הוא שומר ב-cache! כל מה שיש שם לא יטען מהשרת של גוגל בכניסה הבאה שלי – לפחות עד שארפרש את ה-Cache.
השאלה היא איך אני יכול לשלוט ב-cache? בדיוק בשביל זה יש לנו Service Worker שמפעיל את Cache API. זמין בכל הדפדפנים כולל אדג' אך ללא אקספלורר. מצטער חבריי שמפתחים לפח הזבל הדולף הזה שנקרא אקספלורר. זה הזמן להזכיר למנהלי הפרויקטים שלכם שאחוז המשתמשים בזוהמה הזו הוא 2.6 אחוז בישראל.
ה-Service Worker הזה עובד עם פרומיסים. אם אתם לא יודעים מה זה – זה הזמן לקפוץ למאמר המתאים ולקרוא על זה. גם בספר שלי על ללמוד ג'אווהסקריפט בעברית יש הסבר מקיף על כך.
אז איך מתחילים? האמת? בפשטות. משתמשים באובייקט cache הגלובלי שזמין לדפדפנים שתומכים בכך, בוחרים שם ל-cache (אל תשכחו שמדובר ב-cache שהוא ייחודי לכל שם מתחם, אז לא צריך ממש לחשוש להתנגש עם אתרים אחרים) ומשיגים אליו גישה עם open. בפרומיס אחר כך, אני יכול להשתמש ב-addAll שמקבל מערך של נתיבים למשאבים.
ההסבר איכשהו הרבה יותר מסובך מהקוד:
caches.open('ran-cache').then((cache) => {
// We have cache. let's party!
cache.addAll(['/images/beer.jpg'])
.then(() => {
console.log('Cached!');
});
});
ברגע שתעשו את זה, תראו שבאמת נוצר לכם אובייקט ב-cache שמכיל את המשאב. וזה יכול להיות גם דף HTML, וידאו, כל דבר שנכנס ל-cache.
זה כבר מעולה, ואני מתאר לעצמי שכל אחד מכם יכול לחשוב על אימפלמנטציות – כמו טעינת משאבים ללקוח כבר בשלב הלוגין למשל. אבל ה-API של cache הוא הרבה יותר רחב מזה. עם keys אני יכול לקבל את כל הפרטים של ה-cache למשל:
caches.open('ran-cache').then((cache) => {
// We have cache. let's party!
cache.keys().then(keys => console.log(keys));
});
הקוד הזה יחזיר לי את כל הבקשות שנשמרו ב-ran-cache. אני יכול למחוק אותן לפי המפתחות.
caches.open('ran-cache').then((cache) => {
// We have cache. let's party!
cache.delete('/images/beer.jpg')
.then(() => console.log('deleted!'));
});
אפשר למחוק את כל ה-Cache בלי בעיה באמצעות:
caches.delete('ran-cache').then(() => {
console.log('All cache successfully deleted!');
});
כדאי לשים לב שלא הייתי צריך לבצע open במקרה הזה.
אפשר לקרוא למשאבים חיצוניים, אפשר לקרוא לכל משאב שהוא. זה באמת פיצ'ר מאוד מגניב וכיפי וכדאי להכיר.
3 תגובות
הי,
מאמר מעניין ורלוונטי 🙂
כמה הערות קטנות:
1. לא חייבים service worker כדי להפעיל את הcache API. הוא זמין על אובייקט הwindow לשימוש גם על ידי אפליקציות.
2. הcache מוגבל בכמות המשאבים שהוא יכול להכיל (זה משתנה בין כל דפדפן) ולכן יש API נוסף שנקרא StorageEstimate כדי להעריך כמה מקום נשאר בcache. מובנה בcache מנגנונים של מחיקה אוטומטית של משאבים במקרה ומגיעים למגבלת הכמות.
3. בזמן הכתיבה של הפוסט הcache API הוא עדיין working draft ולא תקינה כך שהAPI או דברים שבתוכו עדיין יכולים להשתנות בעתיד הקרוב (למרות שאני בספק שזה יקרה).
"מבקש את המשאב הזה – הדפדפן לא שולח את הבקשה ברשת אלא מביא אותו מייד מהזכרון שלו. על מנת לסמן למפתחים שמדובר בבקשה שלא נשלחה, היא כביכול “חוזרת” עם 304."
בוודאי שהדפדפן שולח את הבקשה, יחד עם מידע על מה שיש לו ב-cache
והשרת מחזיר לא כביכול 304 – תשתמש ב-cache שלך (מבלי שהשרת צריך לרנדר או לשלוח מחדש את אותו המשאב), או 200 – הינה המשאב מחדש, ותתעלם ממה שהיה ב-cache כי הוא לא רלוונטי
האם ניתן להכניס גם את cache.js למערך הקבצים?