مساحة التخزين على الويب

تتوفّر العديد من الخيارات المختلفة لتخزين البيانات في المتصفّح. أيّ منها يناسب احتياجاتك؟

قد تكون اتصالات الإنترنت غير مستقرة أو غير متوفّرة أثناء التنقل، ولهذا السبب يُعدّ توفير الدعم بلا إنترنت والأداء الموثوق من الميزات الشائعة في تطبيقات الويب التقدّمية. حتى في البيئات اللاسلكية المثالية، يمكن أن يؤدي الاستخدام الحكيم للتخزين المؤقت وتقنيات التخزين الأخرى إلى تحسين تجربة المستخدم بشكل كبير. هناك عدة طرق لتخزين موارد التطبيق الثابتة (HTML وJavaScript وCSS والصور وما إلى ذلك) والبيانات (بيانات المستخدم والمقالات الإخبارية وما إلى ذلك) في ذاكرة التخزين المؤقت. ولكن ما هو الحل الأفضل؟ ما هي سعة التخزين المتاحة لك؟ كيف يمكنك منع إزالته؟

ماذا يجب أن أستخدم؟

في ما يلي اقتراح عام لتخزين الموارد:

تتوفّر IndexedDB وOPFS وCache Storage API في كل المتصفّحات الحديثة. وهي غير متزامنة ولن تحظر سلسلة التعليمات الرئيسية (ولكن هناك أيضًا صيغة متزامنة من OPFS متاحة حصريًا في مشغّلي الويب). ويمكن الوصول إليها من عنصر window وعاملي الويب وعاملي الخدمة، ما يتيح استخدامها في أي مكان في الرمز البرمجي.

ماذا عن آليات التخزين الأخرى؟

هناك العديد من آليات التخزين الأخرى المتاحة في المتصفّح، ولكنّها ذات استخدام محدود وقد تسبّب مشاكل كبيرة في الأداء.

SessionStorage هي واجهة برمجة تطبيقات خاصة بعلامة التبويب، وتقتصر على مدة صلاحية علامة التبويب. قد يكون مفيدًا لتخزين كميات صغيرة من المعلومات الخاصة بالجلسة، مثل مفتاح IndexedDB. ويجب استخدامها بحذر لأنّها متزامنة وستحظر سلسلة التعليمات الرئيسية. ويقتصر حجمه على 5 ميغابايت تقريبًا، ويمكن أن يحتوي على سلاسل فقط. ولأنّها مخصّصة لعلامات التبويب، لا يمكن الوصول إليها من خلال مشغّلي الويب أو مشغّلي الخدمات.

يجب تجنُّب استخدام LocalStorage لأنّه متزامن وسيؤدي إلى حظر سلسلة التعليمات الرئيسية. ويقتصر حجمه على حوالي 5 ميغابايت ويمكن أن يحتوي على سلاسل فقط. لا يمكن الوصول إلى LocalStorage من خلال مشغّلي الويب أو مشغّلي الخدمات.

ملفات تعريف الارتباط لها استخداماتها، ولكن يجب عدم استخدامها للتخزين. يتم إرسال ملفات تعريف الارتباط مع كل طلب HTTP، لذا فإن تخزين أي شيء أكثر من كمية صغيرة من البيانات سيزيد بشكل كبير من حجم كل طلب ويب. وهي متزامنة، ولا يمكن الوصول إليها من خلال مشغّلي الويب. مثل LocalStorage وSessionStorage، تقتصر ملفات تعريف الارتباط على السلاسل فقط.

تم تصميم File System Access API للسماح للمستخدمين بقراءة الملفات وتعديلها على نظام الملفات على الجهاز. يجب أن يمنح المستخدم الإذن قبل أن تتمكّن الصفحة من قراءة أي ملف على الجهاز أو الكتابة فيه، ولا يتم الاحتفاظ بالأذونات على مستوى الجلسات، ما لم يتم تخزين مؤشر الملف مؤقتًا في IndexedDB. تُعدّ واجهة File System Access API الأنسب لحالات الاستخدام مثل برامج التعديل، حيث تحتاج إلى فتح ملف وتعديله ثم حفظ التغييرات في الملف.

توفّر واجهتا برمجة التطبيقات File System API وFileWriter API طرقًا لقراءة الملفات وكتابتها في نظام ملفات في وضع الحماية. على الرغم من أنّها غير متزامنة، لا يُنصح باستخدامها لأنّها متوفّرة فقط في المتصفّحات المستنِدة إلى Chromium.

ما هو حجم البيانات التي يمكنني تخزينها؟

باختصار، الكثير، على الأقل بضع مئات من الميغابايت، وربما مئات الغيغابايت أو أكثر. تختلف عمليات تنفيذ المتصفّح، ولكنّ مقدار مساحة التخزين المتاحة يعتمد عادةً على مقدار مساحة التخزين المتاحة على الجهاز.

  • يسمح Chrome للمتصفّح باستخدام ما يصل إلى %80 من إجمالي مساحة القرص. يمكن أن يستخدم المصدر ما يصل إلى %60 من إجمالي مساحة القرص. يمكنك استخدام StorageManager API لتحديد الحد الأقصى المتاح للحصة. قد تختلف المتصفّحات الأخرى المستندة إلى Chromium.
    • في وضع التصفّح المتخفي، يقلّل Chrome مقدار مساحة التخزين التي يمكن أن يستخدمها المصدر إلى %5 تقريبًا من إجمالي مساحة القرص.
    • إذا فعّل المستخدم خيار "محو ملفات تعريف الارتباط وبيانات المواقع الإلكترونية عند إغلاق جميع النوافذ" في Chrome، سيتم تقليل مساحة التخزين المتوفّرة بشكل كبير إلى 300 ميغابايت تقريبًا كحدّ أقصى.
  • يسمح Firefox للمتصفّح باستخدام ما يصل إلى %50 من مساحة القرص الخالية. يمكن لمجموعة eTLD+1 (مثل example.com وwww.example.com وfoo.bar.example.com) استخدام ما يصل إلى 2 غيغابايت. يمكنك استخدام StorageManager API لتحديد مقدار المساحة التي لا تزال متاحة.
  • يبدو أنّ Safari (على كلّ من أجهزة الكمبيوتر المكتبي والأجهزة الجوّالة) يسمح بحوالي 1 غيغابايت. عند الوصول إلى الحدّ الأقصى، سيطلب Safari من المستخدم زيادة الحدّ الأقصى بمقدار 200 ميغابايت. لم أتمكّن من العثور على أي مستندات رسمية حول هذا الموضوع.
    • إذا تمت إضافة تطبيق ويب تقدّمي إلى الشاشة الرئيسية على متصفّح Safari للأجهزة الجوّالة، يتم إنشاء حاوية تخزين جديدة، ولا تتم مشاركة أي بيانات بين تطبيق الويب التقدّمي ومتصفّح Safari للأجهزة الجوّالة. بعد بلوغ الحصة المحدّدة لتطبيق ويب تقدّمي مثبَّت، لا يبدو أنّ هناك أي طريقة لطلب مساحة تخزين إضافية.

في السابق، إذا تجاوز موقع إلكتروني حدًا معيّنًا من البيانات المخزّنة، كان المتصفّح يطلب من المستخدم منح الإذن لاستخدام المزيد من البيانات. على سبيل المثال، إذا استخدم المصدر أكثر من 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.`);
}

يجب رصد الأخطاء المتعلقة بتجاوز الحصة (انظر أدناه). في بعض الحالات، يمكن أن تتجاوز الحصة المتاحة مقدار مساحة التخزين المتاحة فعليًا.

فحص

أثناء عملية التطوير، يمكنك استخدام أدوات مطوّري البرامج في المتصفّح لفحص أنواع مساحات التخزين المختلفة ومحو جميع البيانات المخزَّنة.

تمت إضافة ميزة جديدة في Chrome 88 تتيح لك إلغاء مساحة التخزين المتوفّرة للموقع الإلكتروني في "لوحة التخزين". تتيح لك هذه الميزة محاكاة أجهزة مختلفة واختبار سلوك تطبيقاتك في حالات انخفاض مساحة القرص المتوفّرة. انتقِل إلى التطبيق ثم مساحة التخزين، وفعِّل مربّع الاختيار محاكاة مساحة التخزين المخصّصة والمتوفرة، وأدخِل أي رقم صالح لمحاكاة مساحة التخزين المتوفّرة.

كيفية التعامل مع تجاوز الحصة؟

ماذا يجب أن تفعل عند تجاوز الحصة؟ والأهم من ذلك، يجب دائمًا رصد أخطاء الكتابة ومعالجتها، سواء كانت 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 في إزالة البيانات عندما تنفد مساحة المتصفّح، وذلك من خلال محو جميع بيانات الموقع الإلكتروني من المصدر الأقل استخدامًا أولاً، ثم المصدر التالي، إلى أن يتوقف المتصفّح عن تجاوز الحدّ الأقصى.
  • سيبدأ Firefox في إزالة البيانات عندما تمتلئ مساحة القرص المتاحة، ويمحو جميع بيانات الموقع الإلكتروني من المصدر الأقل استخدامًا أولاً، ثم المصدر التالي، إلى أن يصبح المتصفّح غير متجاوز للحدّ الأقصى.
  • لم يكن Safari يطرد البيانات في السابق، ولكنه نفذ مؤخرًا حدًا جديدًا لمدة سبعة أيام على جميع وحدات التخزين القابلة للكتابة (انظر أدناه).

بدءًا من الإصدار iOS وiPadOS 13.4 وSafari 13.1 على نظام التشغيل macOS، هناك حد أقصى لمدة سبعة أيام على جميع مساحات التخزين القابلة للكتابة في النصوص البرمجية، بما في ذلك IndexedDB وتسجيل مشغّل الخدمات وواجهة برمجة التطبيقات Cache API. وهذا يعني أنّ Safari سيحذف كل المحتوى من ذاكرة التخزين المؤقت بعد سبعة أيام من استخدام Safari إذا لم يتفاعل المستخدم مع الموقع الإلكتروني. لا تسري سياسة الإخلاء هذه على تطبيقات الويب التقدّمية (PWA) المثبَّتة التي تمت إضافتها إلى الشاشة الرئيسية. يمكنك الاطّلاع على مقالة الحظر الكامل لملفات تعريف الارتباط الخارجية والمزيد في مدوّنة WebKit للحصول على التفاصيل الكاملة.

حِزم التخزين

تتمثّل الفكرة الأساسية من Storage Buckets API في منح المواقع الإلكترونية إمكانية إنشاء حِزم تخزين متعدّدة، حيث يمكن للمتصفّح اختيار حذف كل حزمة بشكل مستقل عن الحِزم الأخرى. يتيح ذلك للمطوّرين تحديد أولوية الإخلاء لضمان عدم حذف البيانات الأكثر أهمية.

مكافأة: لماذا يجب استخدام برنامج تضمين لـ IndexedDB؟

‫IndexedDB هي واجهة برمجة تطبيقات منخفضة المستوى تتطلّب إعدادًا كبيرًا قبل الاستخدام، وقد يكون ذلك صعبًا بشكل خاص لتخزين البيانات ذات التعقيد المنخفض. وعلى عكس معظم واجهات برمجة التطبيقات الحديثة المستندة إلى الوعود، فإنّها تستند إلى الأحداث. تخفي برامج تضمين Promise مثل idb لواجهة IndexedDB بعض الميزات الفعّالة، ولكن الأهم من ذلك أنّها تخفي الآليات المعقّدة (مثل المعاملات وإصدارات المخططات) التي تأتي مع مكتبة IndexedDB.

ميزة إضافية: SQLite Wasm

بعد إيقاف Web SQL نهائيًا وإزالتها من Chrome، عملت Google مع المشرفين على قاعدة بيانات SQLite الرائجة لتقديم بديل لـ Web SQL استنادًا إلى SQLite. يمكنك الاطّلاع على SQLite Wasm في المتصفّح المستند إلى نظام الملفات الخاص بالمصدر للحصول على تفاصيل حول كيفية استخدامه.

الخاتمة

لقد ولت أيام التخزين المحدود ومطالبة المستخدم بتخزين المزيد والمزيد من البيانات. يمكن للمواقع الإلكترونية تخزين جميع الموارد والبيانات التي تحتاجها للتشغيل بشكل فعال. باستخدام StorageManager API، يمكنك تحديد مقدار المساحة المتاحة لك ومقدار المساحة التي استخدمتها. وباستخدام مساحة التخزين الدائمة، يمكنك حماية البيانات من الإزالة ما لم يزِلها المستخدم.

مراجع إضافية

شكرًا

نتوجّه بالشكر إلى "جاريد غودمان" و"فيل والتون" و"إيجي كيتامورا" و"دانيال ميرفي" و"داروين هوانغ" و"جوش بيل" و"مارين كرويسلبرينك" و"فيكتور كوستان" على مراجعة هذا الدليل. نشكر "إيجي كيتامورا" و"آدي عثماني" و"مارك كوهين" الذين كتبوا المقالات الأصلية التي يستند إليها هذا المحتوى. كتب "إيجي" أداة مفيدة تُسمى Browser Storage Abuser، وكانت مفيدة في التحقّق من السلوك الحالي. يتيح لك تخزين أكبر قدر ممكن من البيانات والاطّلاع على حدود مساحة التخزين في المتصفّح. نشكر "فرانسوا بوفورت" الذي بحث في Safari لمعرفة حدود مساحة التخزين، و"توماس شتاينر" على إضافة معلومات حول نظام الملفات الخاص بالمصدر، وحِزم التخزين، وSQLite Wasm، وتحديث المحتوى بشكل عام في عام 2024.