SQLite Wasm في المتصفّح المتوافق مع Origin Private File System

استخدم SQLite لتلبية جميع احتياجات سعة التخزين لديك بشكل فعّال على الويب.

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

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

شعار SQLite

SQLite المستند إلى WebAssembly

هناك عدد من إصدارات SQLite غير الرسمية المستندة إلى WebAssembly (Wasm)، مما يتيح استخدامها في متصفّحات الويب، على سبيل المثال، sql.js. يُعد المشروع الفرعي sqlite3 WASM/JS هو الجهد الأول المرتبط رسميًا بمشروع SQLite الذي يجعل إصدارات Wasm من المكتبة التي شكّلت أفرادًا من مجموعة مخرجات SQLite المعتمدة. تتضمن الأهداف الملموسة لهذا المشروع ما يلي:

  • ربط واجهة برمجة تطبيقات sqlite3 منخفضة المستوى أقرب ما يمكن إلى واجهة برمجة التطبيقات C من حيث الاستخدام
  • واجهة برمجة تطبيقات ذات مستوى أعلى موجّهة للكائنات، وأكثر شبهاً بواجهتَي برمجة التطبيقات sql.js و عمليات التنفيذ بأسلوب Node.js، والتي تتعامل مباشرةً مع واجهة برمجة التطبيقات ذات المستوى المنخفض يجب استخدام واجهة برمجة التطبيقات هذه من سلسلتَي الرسائل المتعلّقتَين بواجهة برمجة التطبيقات ذات المستوى المنخفض.
  • واجهة برمجة تطبيقات مستندة إلى Worker تتواصل مع واجهات برمجة التطبيقات السابقة من خلال رسائل Worker هذا الإصدار مخصّص للاستخدام في سلسلة المحادثات الرئيسية، مع تثبيت واجهات برمجة التطبيقات من المستوى الأدنى في سلسلة محادثات Worker والتواصل معها من خلال رسائل Worker.
  • أحد الصيغ المستندة إلى Promise من Worker API التي تحجب عن المستخدم تمامًا جوانب التواصل بين سلاسل المهام.
  • إتاحة مساحة تخزين دائمة من جهة العميل باستخدام واجهات برمجة تطبيقات JavaScript المتاحة، بما في ذلك Origin Private File System (OPFS)

استخدام SQLite Wasm مع الخلفية للحفاظ على ثبات نظام الملفات الخاص في Origin

تثبيت المكتبة من npm

ثبِّت الحزمة @sqlite.org/sqlite-wasm من npm باستخدام الأمر التالي:

npm install @sqlite.org/sqlite-wasm

نظام الملفات الخاص في Origin

تم تحسين نظام Origin Private File System ‏ (OPFS، وهو جزء من File System Access API) من خلال سطح مفعّل خاص يوفر إمكانية الوصول إلى البيانات بأداء عالٍ جدًا. يختلف سطح العرض الجديد عن الأسطح الحالية من خلال توفير إذن وصول حصري للكتابة في مكانها إلى محتوًى ملف. يؤدي هذا التغيير، إلى جانب إمكانية قراءة تعديلات غير مُفرَّغة باستمرار ومدى توفّر خيار متزامن في العمال المخصّصين، إلى تحسين الأداء بشكل كبير وإلغاء حظر حالات استخدام جديدة.

كما يمكنك أن تتوقّع، فإنّ النقطة الأخيرة من أهداف المشروع، وهي إتاحة التخزين الدائم من جهة العميل باستخدام واجهات برمجة تطبيقات JavaScript المتاحة، تفرض متطلبات أداء صارمة في ما يتعلّق بحفظ البيانات في ملف قاعدة البيانات. هذا هو المكان الذي يُستخدم فيه نظام ملفات Origin Private File System، وبشكل أكثر تحديدًا، أسلوب createSyncAccessHandle() الخاص بالكائنات FileSystemFileHandle. تُعرِض هذه الطريقة وعدًا يتم حلّه إلى كائن FileSystemSyncAccessHandle يمكن استخدامه للقراءة من ملف وكتابته بشكل متزامن. توفّر الطبيعة غير المتزامنة لهذه الطريقة مزايا في الأداء، ولكن بالتالي لا يمكن استخدامها إلا داخل Web Workers المخصّصة للملفات ضمن نظام الملفات الخاص في المصدر حتى لا يتم حظر سلسلة المهام الرئيسية.

ضبط الرؤوس المطلوبة

من بين الملفات الأخرى، يحتوي أرشيف SQLite Wasm الذي تم تنزيله على الملفَين sqlite3.js وsqlite3.wasm، اللذَين يشكّلان إصدار sqlite3 WASM/JS. يحتوي دليل jswasm على تسليمات sqlite3 الأساسية، بينما يحتوي دليل المستوى الأعلى على تطبيقات تجريبية واختبار. لن تعرِض المتصفّحات ملفات Wasm من عناوين URL التي تبدأ بـfile://، لذا فإنّ أي تطبيقات تنشئها باستخدام هذه الميزة تتطلّب خادم ويب، ويجب أن يتضمّن هذا الخادم الرؤوس التالية في استجابته عند عرض الملفات:

  • Cross-Origin-Opener-Policy يتم ضبطه على توجيه same-origin، الذي يعزل سياق التصفّح على المستندات من المصدر نفسه فقط. لا يتم تحميل المستندات من مصادر مختلفة في سياق التصفّح نفسه.
  • Cross-Origin-Embedder-Policy تم ضبطه على التوجيه require-corp، كي لا يتمكّن المستند من تحميل الموارد إلا من المصدر نفسه، أو الموارد التي تم وضع علامة عليها صراحةً على أنّها قابلة للتحميل من مصدر آخر.

يرجع سبب ظهور هذه العناوين إلى أنّ SQLite Wasm يعتمد على SharedArrayBuffer، وإعداد هذه العناوين هو جزء من متطلبات الأمان.

في حال فحص الزيارات باستخدام أدوات مطوّري البرامج، من المفترض أن تظهر لك ملفوظات العميل التالية:

عنوانا السياسة المذكورَين أعلاه، Cross-Origin-Embedder-Policy وCross-Origin-Opener-Policy، مميّزان في "أدوات مطوّري البرامج في Chrome"

Speedtest

أجرى فريق SQLite بعض معايير الأداء على عملية تنفيذ WebAssembly مقارنةً بـ Web SQL التي تم إيقافها نهائيًا. تُظهر معايير الأداء هذه أنّ SQLite Wasm هو بشكل عام أسرع من Web SQL. في بعض الأحيان يكون أبطأ قليلاً، وفي بعض الأحيان يكون أسرع قليلاً. يمكنك الاطّلاع على كل التفاصيل في صفحة النتائج.

عيّنة تعليمات برمجية للبدء

كما ذكرنا سابقًا، يجب تشغيل SQLite Wasm مع Origin Private File System في الخلفية من سياق Worker. والخبر السار هو أنّه تهتم المكتبة تلقائيًا بكل هذه الإجراءات نيابةً عنك ويمكنك استخدامها مباشرةً من سلسلة المحادثات الرئيسية.

import { sqlite3Worker1Promiser } from '@sqlite.org/sqlite-wasm';

(async () => {
  try {
    console.log('Loading and initializing SQLite3 module...');

    const promiser = await new Promise((resolve) => {
      const _promiser = sqlite3Worker1Promiser({
        onready: () => {
          resolve(_promiser);
        },
      });
    });

    console.log('Done initializing. Running demo...');

    let response;

    response = await promiser('config-get', {});
    console.log('Running SQLite3 version', response.result.version.libVersion);

    response = await promiser('open', {
      filename: 'file:worker-promiser.sqlite3?vfs=opfs',
    });
    const { dbId } = response;
    console.log(
      'OPFS is available, created persisted database at',
      response.result.filename.replace(/^file:(.*?)\?vfs=opfs$/, '$1'),
    );

    await promiser('exec', { dbId, sql: 'CREATE TABLE IF NOT EXISTS t(a,b)' });
    console.log('Creating a table...');

    console.log('Insert some data using exec()...');
    for (let i = 20; i <= 25; ++i) {
      await promiser('exec', {
        dbId,
        sql: 'INSERT INTO t(a,b) VALUES (?,?)',
        bind: [i, i * 2],
      });
    }

    console.log('Query data with exec()');
    await promiser('exec', {
      dbId,
      sql: 'SELECT a FROM t ORDER BY a LIMIT 3',
      callback: (result) => {
        if (!result.row) {
          return;
        }
        console.log(result.row);
      },
    });

    await promiser('close', { dbId });
  } catch (err) {
    if (!(err instanceof Error)) {
      err = new Error(err.result.message);
    }
    console.error(err.name, err.message);
  }
})();

عرض توضيحي

يمكنك الاطّلاع على الرمز أعلاه في الإصدار التجريبي. احرص على الاطّلاع على رمز المصدر على Glitch. يُرجى العِلم أنّ الإصدار المضمَّن أدناه لا يستخدم الواجهة الخلفية OPFS، ولكن عندما تفتح العرض التوضيحي في علامة تبويب منفصلة.

تصحيح أخطاء نظام الملفات الخاص في Origin

لتصحيح أخطاء مخرجات Origin Private File System في SQLite Wasm، استخدِم إضافة Chrome الخاصة بملف OPFS Explorer.

OPFS Explorer في &quot;سوق Chrome الإلكتروني&quot;

بعد تثبيت الإضافة، افتح "أدوات مطوّري البرامج في Chrome"، واختَر علامة التبويب مستكشف نظام ملفات Origin الخاص، وسيكون بإمكانك بعد ذلك فحص ما تكتبه SQLite Wasm في نظام ملفات Origin الخاص.

إضافة OPFS Explorer في Chrome تعرض بنية Origin Private File System للتطبيق التجريبي

إذا حددت أيًّا من الملفات في نافذة OPFS Explorer في "أدوات مطوري البرامج"، يمكنك حفظه على القرص المحلي. يمكنك بعد ذلك استخدام تطبيق مثل SQLite Viewer لفحص قاعدة البيانات، ما يتيح لك التأكّد من أنّ SQLite Wasm يعمل على النحو المتوقّع.

تطبيق SQLite Viewer يُستخدم لفتح ملف قاعدة بيانات من الإصدار التجريبي من SQLite Wasm.

الحصول على المساعدة وتقديم الملاحظات

يتم تطوير SQLite Wasm وصيانتها من قِبل منتدى SQLite. يمكنك الحصول على المساعدة و تقديم الملاحظات من خلال البحث في منتدى الدعم والنشر فيه. تتوفّر المستندات الكاملة على موقع SQLite الإلكتروني.