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"، واختَر علامة التبويب مستكشف OPFS، وسيكون بإمكانك بعد ذلك فحص ما تكتبه SQLite Wasm في نظام الملفات الخاص بمصدر البيانات.

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

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

تطبيق SQLite Viewer المستخدَم لفتح ملف قاعدة بيانات من العرض التقديمي لـ SQLite Wasm

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

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