נפח אחסון לאינטרנט

יש הרבה אפשרויות שונות לאחסון נתונים בדפדפן. איזה מהם הכי מתאים לצרכים שלך?

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

במה כדאי להשתמש?

המלצה כללית לאחסון משאבים:

IndexedDB וה-API של Cache Storage נתמכים בכל דפדפן מודרני. שניהם אסינכרוניים, ולא יחסמו את ה-thread הראשי. אלו נגישים מהאובייקט window, מ-Web Works ומ-Service Workers, קל להשתמש בהם בכל מקום בקוד שלכם.

מה לגבי מנגנוני אחסון אחרים?

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

SessionStorage הוא ספציפי לכרטיסייה, והיקף ההרשאות שלו משך החיים של הכרטיסייה. האפשרות הזו יכולה להיות שימושית לאחסון כמויות קטנות של פעילויות באתר מידע ספציפי, כמו מפתח IndexedDB. יש להשתמש בו עם בזהירות כי הוא סינכרוני והוא יחסום את ה-thread הראשי. זה כן מוגבל ל-5MB בערך ויכול להכיל רק מחרוזות. בגלל שהכוונה היא ספציפית לכרטיסייה, הוא לא נגיש מ-Web worker או מ-Service Worker.

יש להימנע מ-LocalStorage מפני שהוא סינכרוני והוא יחסום את ה-thread הראשי. היא מוגבלת ל-5MB בערך ויכולה להכיל רק מחרוזות. אין גישה אל LocalStorage מעובדי אינטרנט או משירות ב-Google Workspace for Education.

לקובצי Cookie יש שימושים משלהם, אבל לא מומלץ להשתמש בהם לאחסון. קובצי Cookie נשלחים עם כל בקשת HTTP, כך שלמעשה הוא מאחסן יותר כמות קטנה של נתונים תגדיל באופן משמעותי את הגודל של כל בקשת אינטרנט. הם סינכרוניים ואין אליהם גישה מעובדי האינטרנט. מוצא חן בעיניי LocalStorage ו-sessionStorage, קובצי cookie מוגבלים למחרוזות בלבד.

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

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

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

אין להשתמש במטמון של האפליקציה (Application Cache) ובנתוני שימוש קיים הועברו ל-service worker ול-Cache API. זה היה הוצאה משימוש והתמיכה תוסר מדפדפנים ב לעתיד.

כמה אפשר לאחסן?

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

  • Chrome מאפשר לדפדפן לנצל עד 80% מנפח האחסון הכולל בכונן. מקור יכול תנצלו עד 60% מנפח הדיסק הכולל. אפשר להשתמש ב-StorageManager API כדי לקבוע את המכסה המקסימלית שזמינה. תוספים אחרים שמבוססים על Chromium לדפדפנים שונים,
    • במצב פרטי, Chrome מצמצם את נפח האחסון שהמקור יכול להשתמש בו לכ-5% מנפח הדיסק הכולל.
    • אם המשתמש הפעיל את האפשרות 'ניקוי קובצי cookie ונתוני אתרים לאחר סגירת כל ההגדרות' חלונות" ב-Chrome, מכסת האחסון יורדת באופן משמעותי ל- בנפח של כ-300MB.
    • למידע נוסף, ראו PR #3896 פרטים על ההטמעה של Chrome.
  • Internet Explorer 10 ואילך יכול לאחסן עד 250MB וישלח בקשה משתמש ביותר מ-10MB.
  • Firefox מאפשר לדפדפן לנצל עד 50% משטח האחסון הפנוי. eTLD+1 קבוצתי (למשל example.com, www.example.com וגם foo.bar.example.com) עשויים להשתמש ב-2GB לכל היותר. אפשר להשתמש באמצעות StorageManager API כדי לקבוע כמה מקום נותר. זמינים.
  • נראה שב-Safari (גם במחשב וגם בנייד) יש נפח אחסון של כ-1GB. מתי המגבלה מגיע, Safari ינחה את המשתמש להגדיל את המגבלה ב-200MB בהדרגה. לא מצאתי תיעוד רשמי בנושא.
    • אם PWA נוספת למסך הבית ב-Safari לנייד, נראה שהיא יוצר מאגר אחסון חדש, ושום דבר לא משותף בין ה-PWA ו-Safari לנייד. אחרי שמגיעים למכסה של PWA שמותקנת, נראה שאין דרך לבקש נפח אחסון נוסף.

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

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

איך אפשר לבדוק כמה נפח אחסון פנוי?

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

if (navigator.storage && navigator.storage.estimate) {
  const quota = await navigator.storage.estimate();
  // quota.usage -> Number of bytes used.
  // quota.quota -> Maximum number of bytes available.
  const percentageUsed = (quota.usage / quota.quota) * 100;
  console.log(`You've used ${percentageUsed}% of the available storage.`);
  const remaining = quota.quota - quota.usage;
  console.log(`You can write up to ${remaining} more bytes.`);
}

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

בדיקה

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

בגרסה 88 של Chrome נוספה תכונה חדשה שמאפשרת לבטל את נפח האחסון של האתר במכסת האחסון בחלונית האחסון. התכונה הזו מאפשרת לדמות מכשירים שונים ולבדוק את ההתנהגות של האפליקציות בזמינות מועטה בכונן במקרים מסוימים. עוברים אל Application ואז Storage, ומפעילים את Simulate custom storage quota, ומזינים כל מספר חוקי כדי הדמיה של מכסת האחסון.

החלונית DevTools Storage.

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

איך מטפלים חריגה מהמכסה?

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

גם IndexedDB וגם ה-Cache API יציגו DOMError בשם QuotaExceededError אם תחרגו מהמכסה הזמינה.

IndexedDB

אם המקור חרג מהמכסה שלו, ניסיונות לכתוב ל-IndexedDB נכשל. תתבצע קריאה ל-handler של העסקה onabort() כדי להעביר אירוע. האירוע יכלול DOMException במאפיין השגיאה. המערכת בודקת את שגיאה name תחזיר QuotaExceededError.

const transaction = idb.transaction(['entries'], 'readwrite');
transaction.onabort = function(event) {
  const error = event.target.error; // DOMException
  if (error.name == 'QuotaExceededError') {
    // Fallback code goes here
  }
};

Cache API

אם המקור חרג מהמכסה שלו, הוא ינסה לכתוב ל-Cache API תידחה באמצעות QuotaExceededError DOMException.

try {
  const cache = await caches.open('my-cache');
  await cache.add(new Request('/sample1.jpg'));
} catch (err) {
  if (error.name === 'QuotaExceededError') {
    // Fallback code goes here
  }
}

איך מתבצעת פינוי המקום?

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

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

כדי שנוכל להציע לכם את האפשרות הכי טובה, מדיניות הפינוי של אלה היא:

  • דפדפנים המבוססים על Chromium יתחילו להסיר נתונים כשייגמר הדפדפן של שטח, ניקוי כל נתוני האתר מהמקור שנעשה בו הכי פחות בשימוש תחילה, ואז הבאה, עד שהדפדפן יפסיק לחרוג מהמגבלה.
  • דפדפן Internet Explorer 10 ואילך לא יוציא נתונים, אלא ימנע מהמקור ולכתוב.
  • Firefox יתחיל להוציא נתונים כשמקום הדיסק הזמין יתמלא, קודם כול הנתונים של האתר יוסרו מהמקור שנעשה בו הכי פחות שימוש, ואז הבא, עד שהדפדפן יחרוג יותר מהמגבלה.
  • בעבר, Safari לא הסיר נתונים, אבל לאחרונה יישמה גרסה חדשה מגבלה של שבעה ימים על כל האחסון שניתן לכתיבה (ראו בהמשך).

החל מ-iOS ו-iPadOS 13.4 ו-Safari 13.1 ב-macOS, מכסה של שבעה ימים על כל אחסון ניתן לכתיבה בסקריפטים, כולל IndexedDB, שירות רישום עובדים ו-Cache API. כלומר, Safari יסיר את כל הפריטים מהמטמון אחרי שבעה ימים של שימוש ב-Safari, אם המשתמש לא לקיים אינטראקציה עם האתר. מדיניות הפינוי הזו לא חלה על אפליקציות מותקנות אפליקציות PWA שנוספו למסך הבית. צפייה חסימה מלאה של קובצי cookie של צד שלישי ועוד ב-WebKit לפרטים מלאים.

בונוס: למה להשתמש ב-wrapper ל-IndexedDB

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

סיכום

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

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

תודה

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

התמונה הראשית (Hero) היא של גילאומה בולדוק ביטול הפתיחה.