تخزين KV - أول وحدة مدمجة على الويب

يقول مورّدو المتصفّحات وخبراء أداء الويب بشكل أفضل خلال العقد الماضي أنّ localStorage بطيء، وعلى مطوّري الويب التوقّف عن استخدامه.

لكي نكون منصفين، الأشخاص الذين يقولون هذا ليس خطأ. localStorage هي واجهة برمجة تطبيقات متزامنة تحظر سلسلة التعليمات الرئيسية، وفي أي وقت تصل إليها، من المحتمل أن تمنع صفحتك من التفاعل.

المشكلة تكمن في أن واجهة برمجة التطبيقات localStorage بسيطة للغاية، والبديل الوحيد غير المتزامن لـ localStorage هو IndexedDB، وهي واجهة برمجة تطبيقات غير معروفة (دعنا نواجهها) بسهولة استخدامها أو الترحيب بواجهة برمجة التطبيقات.

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

لكن ماذا لو كان بإمكاني الحصول على أداء واجهة برمجة تطبيقات للتخزين غير المتزامن مع بساطة واجهة برمجة تطبيقات localStorage بدون الحاجة إلى دفع تكلفة حجم الملف؟

حسنًا، قد يكون هناك قريبًا. يختبر Chrome ميزة جديدة تُعرف باسم الوحدات المضمّنة، وأول ما نخطط لشحنه هو وحدة تخزين غير متزامنة للمفاتيح/القيم تُسمى تخزين KV.

ولكن قبل الدخول في تفاصيل وحدة تخزين KV، سأشرح ما أعنيه بالوحدات المدمجة.

ما هي الوحدات المضمّنة؟

تشبه الوحدات المضمّنة وحدات JavaScript العادية، إلا أنّها ليست ضرورية لتنزيلها لأنّها تكون مرفقة مع المتصفّح.

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

على عكس واجهات برمجة تطبيقات الويب التقليدية، لا تظهر الوحدات المضمّنة على النطاق العالمي، بل تكون متاحة فقط من خلال عمليات الاستيراد.

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

لاستيراد وحدة مدمجة، يمكنك استخدام البادئة std: متبوعة بمعرف الوحدة المضمنة. على سبيل المثال، في المتصفحات المتوافقة، يمكنك استيراد وحدة تخزين KV باستخدام الرمز التالي (راجِع أدناه كيفية استخدام رمز KV للتخزين في المتصفحات غير المتوافقة):

import storage, {StorageArea} from 'std:kv-storage';

وحدة تخزين KV

تشبه وحدة تخزين KV في بساطتها واجهة برمجة التطبيقات localStorage، ولكن شكلها أقرب إلى JavaScript Map. بدلاً من getItem() وsetItem() وremoveItem() يحتوي على get() وset() وdelete(). ويتضمّن أيضًا طُرقًا أخرى شبيهة بالخريطة ولا تتوفّر في "localStorage"، مثل keys() وvalues() وentries()، ومثل Map، ليس من الضروري أن تكون مفاتيحها سلاسل. يمكن أن تكون أي نوع قابل للتسلسل المتسلسل.

على عكس Map، تعرض جميع طرق تخزين KV إما وعود أو مكررات غير متزامنة (لأن النقطة الرئيسية في هذه الوحدة هي أنها غير متزامنة، على عكس localStorage). للاطّلاع على واجهة برمجة التطبيقات الكاملة بالتفصيل، يمكنك الرجوع إلى المواصفات.

كما لاحظت في مثال الرمز أعلاه، تتضمّن وحدة تخزين KV عملية تصدير تلقائية واحدة storage وعملية تصدير واحدة باسم StorageArea.

storage هو مثال على الفئة StorageArea يحمل الاسم 'default'، وهو ما سيستخدمه المطوِّرون غالبًا في رمز التطبيق. يتم توفير الفئة StorageArea للحالات التي تحتاج إلى عزل إضافي (مثل مكتبة تابعة لجهة خارجية تخزِّن البيانات وتريد تجنُّب التعارضات مع البيانات المخزَّنة عبر مثيل storage التلقائي). يتم تخزين بيانات StorageArea في قاعدة بيانات IndexedDB بالاسم kv-storage:${name}، حيث يكون الاسم هو اسم المثيل StorageArea.

في ما يلي مثال على كيفية استخدام وحدة تخزين KV في الرمز:

import storage from 'std:kv-storage';

const main = async () => {
  const oldPreferences = await storage.get('preferences');

  document.querySelector('form').addEventListener('submit', async () => {
    const newPreferences = Object.assign({}, oldPreferences, {
      // Updated preferences go here...
    });

    await storage.set('preferences', newPreferences);
  });
};

main();

ماذا لو كان المتصفح لا يتوافق مع وحدة مضمّنة؟

إذا كنت على دراية باستخدام وحدات JavaScript الأصلية في المتصفحات، فأنت على الأرجح تعرف أن استيراد أي شيء بخلاف عنوان URL سيؤدي إلى خطأ (على الأقل حتى الآن). وstd:kv-storage ليس عنوان URL صالحًا.

وهذا يثير السؤال: هل علينا الانتظار إلى أن تتوافق جميع المتصفحات مع الوحدات المضمّنة قبل أن نتمكّن من استخدامها في الرمز؟ لحسن الحظ، فإن الإجابة هي لا!

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

استيراد الخرائط

يُعدّ استيراد الخرائط في الأساس آلية يستطيع من خلالها المطوّرون استيراد المعرّفات إلى معرّف بديل واحد أو أكثر.

تُعدّ هذه الطريقة فعّالة لأنّها تمنحك طريقة (في وقت التشغيل) لتغيير طريقة عمل المتصفّح لمعرّف استيراد معيّن على مستوى تطبيقك بالكامل.

في حالة الوحدات المدمجة، يسمح لك ذلك بالرجوع إلى رمز polyfill للوحدة في رمز تطبيقك، ولكن يمكن للمتصفح الذي يدعم الوحدة المدمجة تحميل هذا الإصدار بدلاً من ذلك.

إليك كيفية الإعلان عن خريطة استيراد لتنفيذ هذا الإجراء مع وحدة تخزين KV:

<!-- The import map is inlined into your page -->
<script type="importmap">
{
  "imports": {
    "/path/to/kv-storage-polyfill.mjs": [
      "std:kv-storage",
      "/path/to/kv-storage-polyfill.mjs"
    ]
  }
}
</script>

<!-- Then any module scripts with import statements use the above map -->
<script type="module">
  import storage from '/path/to/kv-storage-polyfill.mjs';

  // Use `storage` ...
</script>

النقطة الأساسية في التعليمة البرمجية أعلاه هي أن عنوان URL /path/to/kv-storage-polyfill.mjs يتم تعيينه إلى موردين مختلفين: std:kv-storage ثم عنوان URL الأصلي مرة أخرى، /path/to/kv-storage-polyfill.mjs.

وبالتالي، عندما يصادف المتصفّح عبارة استيراد تشير إلى عنوان URL هذا (/path/to/kv-storage-polyfill.mjs)، يحاول أولاً تحميل std:kv-storage، وإذا لم يتم ذلك، سيعاود تحميل /path/to/kv-storage-polyfill.mjs.

ومرة أخرى، يكمن السر هنا في أن المتصفح لا يحتاج إلى دعم استيراد الخرائط أو الوحدات المدمجة لكي تعمل هذه التقنية لأن عنوان URL الذي يتم تمريره إلى عبارة الاستيراد هو عنوان URL لرمز polyfill. polyfill ليس في الواقع احتياطيًا، بل هو الافتراضي. تعد الوحدة المدمجة عبارة عن تحسين تدريجي!

ماذا عن المتصفحات التي لا تدعم الوحدات على الإطلاق؟

لاستخدام استيراد الخرائط لتحميل الوحدات المضمنة بشكل مشروط، يجب أن تستخدم فعليًا عبارات import، مما يعني أيضًا أنه عليك استخدام النصوص البرمجية للوحدات، أي <script type="module">.

في الوقت الحالي، يدعم أكثر من 80% من المتصفحات استخدام الوحدات، وبالنسبة إلى المتصفحات التي لا تتوافق معها، يمكنك استخدام أسلوب الوحدات/nounit لعرض حزمة قديمة. يُرجى العِلم أنّه عند إنشاء إصدار nomodule، عليك تضمين جميع رموز polyfill لأنّك تعرف أنّ المتصفحات التي لا تتوافق مع الوحدات لن تتوافق بالتأكيد مع الوحدات المدمجة.

عرض توضيحي حول مساحة تخزين KV

للتوضيح أنّه من الممكن استخدام الوحدات المدمجة مع الاستمرار في استخدام المتصفّحات القديمة، أنشأنا عرضًا توضيحيًا يتضمّن جميع الأساليب الموضّحة أعلاه، ويتم تشغيله في جميع المتصفّحات حاليًا:

  • إنّ المتصفّحات التي تتيح الوحدات وتستورد الخرائط والوحدة المضمّنة لا تحمِّل أي رموز غير ضرورية.
  • إنّ المتصفحات التي تتوافق مع الوحدات وتستورد الخرائط ولكنها لا تتيح استخدام الوحدة المدمجة، تحمِّل رمز polyfill للتخزين KV (عبر برنامج تحميل الوحدة في المتصفح).
  • إنّ المتصفحات التي تتوافق مع الوحدات ولكن لا تتيح استيراد خرائط الاستيراد تحمِّل أيضًا رمز polyfill الخاص بمساحة تخزين KV (عبر أداة تحميل الوحدات في المتصفّح).
  • إنّ المتصفّحات التي لا تتيح إطلاقًا وحدات تخزين رموز KV تحصل على رمز polyfill الخاص بمساحة تخزين KV في حِزمتها القديمة (التي يتم تحميلها من خلال <script nomodule>).

تتم استضافة العرض التوضيحي على Glitch، لذا يمكنك الاطّلاع على مصدره. لديّ أيضًا شرح تفصيلي لعملية التنفيذ في ملف README. لا تتردد في إلقاء نظرة إذا كنت مهتمًا بمعرفة كيف تم بناؤها.

للاطّلاع على الوحدة الأصلية المدمجة عمليًا، يجب تحميل العرض التوضيحي في الإصدار 74 من Chrome أو الإصدارات الأحدث مع تفعيل علامة الميزات التجريبية للنظام الأساسي للويب (chrome://flags/#enable-experimental-web-platform-features).

يمكنك التحقق من تحميل الوحدة المضمنة لأنك لن ترى النص البرمجي polyfill في لوحة المصدر في أدوات مطوّري البرامج، وبدلاً من ذلك، سترى إصدار الوحدة المضمنة (حقيقة طريفة: يمكنك فحص رمز المصدر للوحدة أو حتى وضع نقاط التوقف فيها!):

مصدر وحدة تخزين KV في &quot;أدوات مطوري البرامج في Chrome&quot;

يُرجى إرسال ملاحظاتك إلينا

من المفترض أن تعطيك هذه المقدمة لمحة عن ما يمكن تحقيقه باستخدام الوحدات المدمجة. ونأمل أن تكون متحمسًا لهذا الأمر! يسعدنا أن يجرّب المطوّرون وحدة تخزين KV (بالإضافة إلى جميع الميزات الجديدة التي تمت مناقشتها هنا) وإطلاعنا على ملاحظاتهم.

في ما يلي روابط GitHub التي يمكنك من خلالها تقديم ملاحظات لنا عن كل ميزة من الميزات المذكورة في هذه المقالة:

إذا كان موقعك الإلكتروني يستخدم حاليًا "localStorage"، يجب محاولة التبديل إلى واجهة برمجة التطبيقات KV Storage API لمعرفة ما إذا كانت تستوفي كل احتياجاتك. وإذا اشتركت في نسخة تجريبية من مساحة التخزين KV، يمكنك تفعيل هذه الميزات حاليًا. من المفترض أن يستفيد جميع المستخدمين من أداء أفضل لمساحة التخزين، ولن يضطر مستخدمو الإصدار 74 من Chrome والإصدارات الأحدث إلى دفع أي تكلفة إضافية للتنزيل.