فضای ذخیره سازی برای وب

گزینه های مختلفی برای ذخیره داده ها در مرورگر وجود دارد. کدام یک برای نیازهای شما بهتر است؟

اتصالات اینترنتی ممکن است در حال حرکت به صورت ورقه‌ای باشند یا وجود نداشته باشند، به همین دلیل است که پشتیبانی آفلاین و عملکرد قابل اعتماد از ویژگی‌های رایج در برنامه‌های وب پیشرفته هستند. حتی در محیط‌های بی‌سیم عالی، استفاده عاقلانه از حافظه پنهان و سایر تکنیک‌های ذخیره‌سازی می‌تواند تجربه کاربر را به میزان قابل توجهی بهبود بخشد. راه های مختلفی برای ذخیره منابع برنامه استاتیک (HTML، جاوا اسکریپت، CSS، تصاویر و غیره) و داده ها (داده های کاربر، مقالات خبری و غیره) وجود دارد. اما بهترین راه حل کدام است؟ چقدر می توانید ذخیره کنید؟ چگونه از اخراج آن جلوگیری می کنید؟

از چی استفاده کنم؟

در اینجا یک توصیه کلی برای ذخیره منابع آورده شده است:

IndexedDB و Cache Storage API در هر مرورگر مدرن پشتیبانی می شود. هر دو ناهمزمان هستند و رشته اصلی را مسدود نمی کنند. آنها از طریق شی window ، وب کارگران و کارگران خدمات قابل دسترسی هستند و استفاده از آنها را در هر نقطه از کد شما آسان می کند.

در مورد سایر مکانیسم های ذخیره سازی چطور؟

چندین مکانیسم ذخیره‌سازی دیگر در مرورگر موجود است، اما استفاده محدودی از آنها وجود دارد و ممکن است مشکلات عملکردی قابل توجهی ایجاد کنند.

SessionStorage یک تب خاص است و به طول عمر برگه اختصاص دارد. ممکن است برای ذخیره مقادیر کمی از اطلاعات مربوط به جلسه، به عنوان مثال یک کلید IndexedDB مفید باشد. باید با احتیاط استفاده شود زیرا همزمان است و رشته اصلی را مسدود می کند. به حدود 5 مگابایت محدود شده است و فقط می تواند رشته ها را شامل شود. از آنجایی که مخصوص تب است، از وب‌کارگران یا سرویس‌دهندگان قابل دسترسی نیست.

LocalStorage باید اجتناب شود زیرا همزمان است و رشته اصلی را مسدود می کند. به حدود 5 مگابایت محدود شده است و فقط می تواند رشته ها را شامل شود. LocalStorage از وب‌کارگران یا کارکنان خدمات قابل دسترسی نیست.

کوکی ها کاربردهای خود را دارند، اما نباید برای ذخیره سازی استفاده شوند. کوکی ها با هر درخواست HTTP ارسال می شوند، بنابراین ذخیره هر چیزی بیش از مقدار کمی داده، اندازه هر درخواست وب را به میزان قابل توجهی افزایش می دهد. آنها همزمان هستند و از وب سایت ها قابل دسترسی نیستند. مانند LocalStorage و SessionStorage، کوکی ها فقط به رشته ها محدود می شوند.

File System API و FileWriter API روش هایی را برای خواندن و نوشتن فایل ها در یک سیستم فایل سندباکس ارائه می کنند. در حالی که ناهمزمان است، توصیه نمی شود زیرا فقط در مرورگرهای مبتنی بر Chromium در دسترس است.

File System Access API به گونه ای طراحی شده است که خواندن و ویرایش فایل ها در سیستم فایل محلی خود را برای کاربران آسان کند. کاربر باید قبل از اینکه یک صفحه بتواند در هر فایل محلی بخواند یا بنویسد مجوز بدهد، و مجوزها در تمام جلسات باقی نمی مانند.

WebSQL نباید استفاده شود و استفاده موجود باید به IndexedDB منتقل شود. پشتیبانی تقریباً از تمام مرورگرهای اصلی حذف شده است. W3C حفظ مشخصات Web SQL را در سال 2010 متوقف کرد ، بدون اینکه برنامه ای برای به روز رسانی بیشتر برنامه ریزی شده باشد.

Application Cache نباید استفاده شود و استفاده موجود باید به Service Workers و Cache API منتقل شود. منسوخ شده است و در آینده پشتیبانی از مرورگرها حذف خواهد شد.

چقدر می توانم ذخیره کنم؟

به طور خلاصه، مقدار زیادی ، حداقل چند صد مگابایت، و به طور بالقوه صدها گیگابایت یا بیشتر. پیاده سازی مرورگرها متفاوت است، اما میزان فضای ذخیره سازی موجود معمولاً بر اساس میزان فضای ذخیره سازی موجود در دستگاه است.

  • کروم به مرورگر اجازه می دهد تا 80 درصد از کل فضای دیسک را استفاده کند. یک مبدا می تواند تا 60 درصد از کل فضای دیسک را استفاده کند. می توانید از StorageManager API برای تعیین حداکثر سهمیه موجود استفاده کنید. سایر مرورگرهای مبتنی بر Chromium ممکن است متفاوت باشند.
    • در حالت ناشناس، Chrome مقدار فضای ذخیره‌سازی را که یک منبع می‌تواند استفاده کند به تقریباً 5 درصد از کل فضای دیسک کاهش می‌دهد.
    • اگر کاربر «پاک کردن کوکی‌ها و داده‌های سایت هنگام بستن همه پنجره‌ها» را در Chrome فعال کرده باشد، سهمیه فضای ذخیره‌سازی به میزان قابل توجهی به حداکثر تقریباً 300 مگابایت کاهش می‌یابد.
    • برای جزئیات در مورد پیاده سازی Chrome به PR #3896 مراجعه کنید.
  • اینترنت اکسپلورر 10 و جدیدتر می تواند تا 250 مگابایت ذخیره کند و زمانی که بیش از 10 مگابایت استفاده شده باشد از کاربر درخواست می کند.
  • فایرفاکس به مرورگر اجازه می دهد تا 50 درصد از فضای خالی دیسک را استفاده کند. یک گروه eTLD+1 (به عنوان مثال، example.com ، www.example.com و foo.bar.example.com ) ممکن است تا 2 گیگابایت استفاده کند . می‌توانید از StorageManager API برای تعیین میزان فضای موجود استفاده کنید.
  • به نظر می رسد سافاری (هم دسکتاپ و هم موبایل) حدود 1 گیگابایت اجازه می دهد. هنگامی که به حد مجاز رسید، سافاری از کاربر درخواست می کند و محدودیت را در 200 مگابایت افزایش می دهد. من نتوانستم هیچ سند رسمی در این مورد پیدا کنم.
    • اگر یک PWA به صفحه اصلی در سافاری موبایل اضافه شود، به نظر می‌رسد که یک محفظه ذخیره‌سازی جدید ایجاد می‌کند و چیزی بین PWA و سافاری موبایل به اشتراک گذاشته نمی‌شود. هنگامی که سهمیه برای یک PWA نصب شده به دست آمد، به نظر نمی رسد راهی برای درخواست فضای ذخیره اضافی وجود داشته باشد.

در گذشته، اگر یک سایت از آستانه مشخصی از داده های ذخیره شده فراتر می رفت، مرورگر از کاربر می خواست که اجازه استفاده از داده های بیشتری را بدهد. به عنوان مثال، اگر منبع بیش از 50 مگابایت استفاده می‌کرد، مرورگر از کاربر می‌خواهد تا حداکثر 100 مگابایت را ذخیره کند، سپس دوباره با افزایش 50 مگابایت درخواست می‌کند.

امروزه اکثر مرورگرهای مدرن از کاربر درخواستی نمی کنند و به سایت اجازه می دهند تا از سهمیه اختصاص داده شده خود استفاده کند. به نظر می‌رسد که استثنا 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 هنوز در همه مرورگرها اجرا نشده است، بنابراین باید قبل از استفاده از آن قابلیت شناسایی آن را داشته باشید. حتی زمانی که در دسترس است، همچنان باید خطاهای بیش از سهمیه را دریافت کنید (به زیر مراجعه کنید). در برخی موارد، این امکان وجود دارد که سهمیه موجود بیش از مقدار واقعی فضای ذخیره‌سازی موجود باشد.

بازرسی کنید

در طول توسعه، می توانید از DevTools مرورگر خود برای بررسی انواع مختلف ذخیره سازی استفاده کنید و به راحتی تمام داده های ذخیره شده را پاک کنید.

ویژگی جدیدی در Chrome 88 اضافه شد که به شما امکان می‌دهد سهمیه فضای ذخیره‌سازی سایت را در قسمت Storage Pane لغو کنید. این ویژگی به شما این امکان را می دهد که دستگاه های مختلف را شبیه سازی کنید و رفتار برنامه های خود را در سناریوهای در دسترس بودن دیسک کم آزمایش کنید. به Application سپس Storage بروید، کادر بررسی Simulate custom storage quota را فعال کنید و هر عدد معتبری را برای شبیه سازی سهمیه ذخیره سازی وارد کنید.

پنجره DevTools Storage.

در حین کار بر روی این مقاله، من یک ابزار ساده نوشتم تا سعی کنم تا حد امکان به سرعت از فضای ذخیره سازی استفاده کنم. این یک راه سریع و آسان برای آزمایش مکانیسم های مختلف ذخیره سازی است، و ببینید وقتی از تمام سهمیه خود استفاده می کنید چه اتفاقی می افتد.

چگونه می توان از سهمیه گذشت؟

وقتی از سهمیه عبور می کنید چه باید بکنید؟ مهمتر از همه، شما همیشه باید خطاهای نوشتن را، چه QuotaExceededError یا چیز دیگری، دریافت و مدیریت کنید. سپس، بسته به طراحی اپلیکیشن خود، تصمیم بگیرید که چگونه آن را مدیریت کنید. به عنوان مثال، محتوایی را که برای مدت طولانی به آن دسترسی پیدا نکرده‌اید، حذف کنید، داده‌ها را بر اساس اندازه حذف کنید، یا راهی برای کاربران فراهم کنید تا انتخاب کنند چه چیزی را می‌خواهند حذف کنند.

هر دو IndexedDB و Cache API هر دو یک DOMError به نام QuotaExceededError زمانی که شما از سهمیه موجود فراتر رفته اید پرتاب می کنند.

IndexedDB

اگر مبدا از سهمیه خود فراتر رفته باشد، تلاش برای نوشتن در IndexedDB ناموفق خواهد بود. کنترل کننده 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
  }
}

اخراج چگونه کار می کند؟

فضای ذخیره سازی وب به دو سطل "بهترین تلاش" و "مداوم" طبقه بندی می شود. بهترین تلاش به این معنی است که فضای ذخیره‌سازی می‌تواند توسط مرورگر بدون ایجاد وقفه در کاربر پاک شود، اما برای داده‌های طولانی مدت یا حیاتی دوام کمتری دارد. وقتی فضای ذخیره‌سازی کم است، فضای ذخیره‌سازی دائمی به‌طور خودکار پاک نمی‌شود. کاربر باید این حافظه را به صورت دستی (از طریق تنظیمات مرورگر) پاک کند.

به‌طور پیش‌فرض، داده‌های یک سایت (شامل IndexedDB، Cache API، و غیره) در دسته بهترین تلاش قرار می‌گیرند، به این معنی که اگر سایتی درخواست ذخیره‌سازی دائمی نکرده باشد، مرورگر ممکن است داده‌های سایت را بنا به صلاحدید خود حذف کند، برای مثال، زمانی که فضای ذخیره‌سازی دستگاه کم است. .

سیاست تخلیه برای بهترین تلاش عبارت است از:

  • مرورگرهای مبتنی بر Chromium زمانی که فضای مرورگر تمام شود شروع به حذف داده‌ها می‌کنند و ابتدا همه داده‌های سایت را از مبدأ که اخیراً استفاده شده است پاک می‌کنند، سپس بعدی را تا زمانی که مرورگر دیگر از حد مجاز خارج نشود.
  • اینترنت اکسپلورر 10+ داده‌ها را خارج نمی‌کند، اما از نوشتن مبدا جلوگیری می‌کند.
  • وقتی فضای دیسک موجود پر شود، فایرفاکس شروع به حذف داده‌ها می‌کند، و ابتدا همه داده‌های سایت را از مبدأ کمتر استفاده شده پاک می‌کند، سپس بعدی را تا زمانی که مرورگر دیگر از حد مجاز خارج نشود.
  • Safari قبلاً داده‌ها را خارج نمی‌کرد، اما اخیراً یک سقف هفت روزه جدید را در تمام فضای ذخیره‌سازی قابل نوشتن پیاده‌سازی کرده است (به زیر مراجعه کنید).

با شروع iOS و iPadOS 13.4 و Safari 13.1 در macOS، محدودیت هفت روزه برای تمام فضای ذخیره‌سازی قابل نوشتن اسکریپت، از جمله IndexedDB، ثبت نام در سرویس‌کار، و Cache API وجود دارد. این بدان معناست که اگر کاربر با سایت تعامل نداشته باشد، سافاری پس از هفت روز استفاده از سافاری، تمام محتوا را از حافظه پنهان خارج می‌کند. این خط مشی اخراج برای PWA های نصب شده که به صفحه اصلی اضافه شده اند اعمال نمی شود . برای جزئیات کامل، مسدود کردن کوکی‌های شخص ثالث و موارد دیگر را در وبلاگ WebKit ببینید.

امتیاز: چرا از یک پوشش برای IndexedDB استفاده کنید

IndexedDB یک API سطح پایین است که قبل از استفاده به تنظیمات قابل توجهی نیاز دارد، که می تواند به ویژه برای ذخیره داده های ساده دردناک باشد. بر خلاف اکثر API های مبتنی بر وعده های مدرن، مبتنی بر رویداد است. بسته‌بندی‌های Promise مانند idb برای IndexedDB برخی از ویژگی‌های قدرتمند را پنهان می‌کنند، اما مهم‌تر از آن، ماشین‌های پیچیده (مانند تراکنش‌ها، نسخه‌سازی طرحواره) که با کتابخانه IndexedDB ارائه می‌شود را پنهان می‌کنند.

نتیجه

دوران ذخیره سازی محدود و ترغیب کاربر به ذخیره اطلاعات بیشتر و بیشتر گذشته است. سایت ها می توانند به طور موثر تمام منابع و داده هایی را که برای اجرا نیاز دارند ذخیره کنند. با استفاده از StorageManager API می توانید تعیین کنید که چه مقدار در دسترس شما است و چه مقدار استفاده کرده اید. و با ذخیره سازی دائمی ، مگر اینکه کاربر آن را حذف کند، می توانید از آن در برابر تخلیه محافظت کنید.

منابع اضافی

با تشکر

تشکر ویژه از جرید گودمن، فیل والتون، ایجی کیتامورا، دانیل مورفی، داروین هوانگ، جاش بل، مارین کروسلبرینک و ویکتور کوستان برای بررسی این مقاله. با تشکر از ایجی کیتامورا، آدی عثمانی و مارک کوهن که مقالات اصلی را نوشتند که این بر اساس آن است. Eiji ابزار مفیدی به نام Browser Storage Abuser نوشت که در اعتبارسنجی رفتار فعلی مفید بود. این به شما امکان می دهد تا حد امکان داده ها را ذخیره کنید و محدودیت های ذخیره سازی را در مرورگر خود مشاهده کنید. با تشکر از فرانسوا بوفور که در Safari جستجو کرد تا محدودیت‌های ذخیره‌سازی آن را مشخص کند.

تصویر قهرمان توسط Guillaume Bolduc در Unsplash است.