SQLite Wasm בדפדפן שמגובה על ידי מערכת הקבצים הפרטית של Origin

שימוש ב-SQLite כדי לטפל בכל צורכי האחסון שלכם באינטרנט בצורה יעילה.

SQLite היא מערכת פופולרית לניהול מסדי נתונים יחסיים מוטמעים, קלה ובקוד פתוח. מפתחים רבים משתמשים בו כדי לאחסן נתונים באופן מובנה וקל לשימוש. בגלל הגודל הקטן והדרישות הנמוכות של הזיכרון, SQLite משמש לעתים קרובות כמנוע מסדי נתונים במכשירים ניידים, באפליקציות למחשב ובדפדפני אינטרנט.

אחת מהתכונות העיקריות של SQLite היא שהוא מסד נתונים ללא שרת, כלומר לא נדרש תהליך שרת נפרד כדי להפעיל אותו. במקום זאת, מסד הנתונים מאוחסן בקובץ יחיד במכשיר של המשתמש, כך שקל לשלב אותו באפליקציות.

הלוגו של SQLite.

SQLite שמבוסס על Web Assembly

יש כמה גרסאות לא רשמיות של SQLite שמבוססות על Web Assembly ‏ (Wasm), שמאפשרות להשתמש בה בדפדפני אינטרנט, למשל sql.js. פרויקט המשנה sqlite3 WASM/JS הוא המאמץ הראשון שמשויך באופן רשמי לפרויקט SQLite, והוא יוצר גרסאות build של הספרייה ב-Wasm שהן חלק ממשפחת המוצרים הנתמכים של SQLite. היעדים הספציפיים של הפרויקט כוללים:

  • קישור של ממשק API ברמה נמוכה של sqlite3, שדומה לממשק C ככל האפשר מבחינת השימוש.
  • ממשק API ברמה גבוהה יותר שמבוסס על אובייקטים, דומה יותר ל-sql.js ול-הטמעות בסגנון Node.js, שמדבר ישירות ל-API ברמה נמוכה. צריך להשתמש ב-API הזה מאותו חוט שבו משתמשים ב-API ברמה הנמוכה.
  • ממשק API מבוסס-Worker שמדבר עם ממשקי ה-API הקודמים באמצעות הודעות Worker. הוא מיועד לשימוש בשרשור הראשי, כאשר ממשקי ה-API ברמה נמוכה יותר מותקנים בשרשור של Worker, והשיחה איתם מתבצעת באמצעות הודעות של Worker.
  • וריאנט מבוסס-Promise של Worker API שמסתיר לחלוטין מהמשתמש את היבטי התקשורת בין השרשור.
  • תמיכה באחסון מתמיד בצד הלקוח באמצעות ממשקי API זמינים של JavaScript, כולל מערכת הקבצים הפרטית של גרסת המקור (OPFS).

שימוש ב-SQLite Wasm עם הקצה העורפי של Origin Private File System לשימור נתונים

התקנת הספרייה מ-npm

מתקינים את החבילה @sqlite.org/sqlite-wasm מ-npm באמצעות הפקודה הבאה:

npm install @sqlite.org/sqlite-wasm

מערכת הקבצים הפרטית של המקור

מערכת הקבצים הפרטית של המקור (OPFS, חלק מ-File System Access API) משולבת עם ממשק מיוחד שמאפשר גישה יעילה מאוד לנתונים. הממשק החדש שונה מהממשקים הקיימים בכך שהוא מציע גישה בלעדית לכתיבה במקום לתוכן של הקובץ. השינוי הזה, יחד עם היכולת לקרוא באופן עקבי שינויים שלא בוצעה להם שטיפה (flush) והזמינות של וריאנט סינכרוני בעובדים ייעודיים, משפרים באופן משמעותי את הביצועים ומאפשרים לטפל בתרחישים חדשים של שימוש.

כפי שאפשר לדמיין, הנקודה האחרונה ביעדים של הפרויקט, תמיכה באחסון עקבי בצד הלקוח באמצעות ממשקי API זמינים של JavaScript, כרוכה בדרישות ביצועים מחמירות לגבי שמירת נתונים בקובץ מסד הנתונים. כאן נכנסת לתמונה מערכת הקבצים הפרטית של המקור, ובאופן ספציפי יותר, השיטה createSyncAccessHandle() של אובייקטים מסוג FileSystemFileHandle. השיטה הזו מחזירה Promise שמתבצעת בו פתרון לאובייקט FileSystemSyncAccessHandle שאפשר להשתמש בו כדי לקרוא ולכתוב בקובץ באופן סינכרוני. הטבע הסינכרוני של השיטה הזו מביא יתרונות בביצועים, אבל לכן אפשר להשתמש בה רק בWeb Workers ייעודיים לקבצים במערכת הקבצים הפרטית של המקור, כדי שהשרשור הראשי לא ייחסם.

הגדרת הכותרות הנדרשות

בין היתר, קובץ הארכיון של SQLite Wasm שהורדתם מכיל את הקבצים sqlite3.js ו-sqlite3.wasm, שמרכיבים את ה-build של sqlite3 WASM/JS. הספרייה jswasm מכילה את פריטי היעד של sqlite3, והספרייה ברמה העליונה מכילה אפליקציות הדגמה ואפליקציות בדיקה. הדפדפנים לא יציגים קובצי Wasm מכתובות URL מסוג file://, לכן כל אפליקציה שתיצרו באמצעות ה-Wasm תצטרך שרת אינטרנט, והשרת הזה יצטרך לכלול את הכותרות הבאות בתגובה שלו כשהקבצים יוצגו:

הסיבה לכותרות האלה היא ש-SQLite Wasm תלוי ב-SharedArrayBuffer, והגדרת הכותרות האלה היא חלק מדרישות האבטחה שלו.

אם בודקים את התנועה באמצעות DevTools, אמורים להופיע הפרטים הבאים:

שתי הכותרות שצוינו למעלה, Cross-Origin-Embedder-Policy ו-Cross-Origin-Opener-Policy, מודגשות בכלי הפיתוח ל-Chrome.

Speedtest

צוות SQLite ביצע כמה בדיקות ביצועים בהטמעת WebAssembly שלו בהשוואה ל-Web SQL שהוצא משימוש. מדדי הביצועים האלה מראים שבדרך כלל SQLite Wasm מהיר בערך כמו Web SQL. לפעמים זה איטי יותר, ולפעמים מהיר יותר. כל הפרטים מופיעים בדף התוצאות.

דוגמת קוד לתחילת העבודה

כפי שצוין קודם, צריך להריץ את SQLite Wasm עם הקצה העורפי של מערכת הקבצים הפרטית של המקור (Origin) בתור הקשר של 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, אבל כשפותחים את הדמו בכרטיסייה נפרדת, כן נעשה בו שימוש.

ניפוי באגים במערכת הקבצים הפרטית של המקור

כדי לנפות באגים בפלט של מערכת הקבצים הפרטית של המקור ב-SQLite Wasm, משתמשים בתוסף OPFS Explorer ל-Chrome.

OPFS Explorer בחנות האינטרנט של Chrome.

אחרי התקנת התוסף, פותחים את כלי הפיתוח של Chrome, בוחרים בכרטיסייה OPFS Explorer ומוכנים לבדוק מה SQLite Wasm כותב למערכת הקבצים הפרטית של המקור.

תוסף OPFS Explorer ל-Chrome שבו מוצגת המבנה של מערכת הקבצים הפרטית של המקור (Origin) באפליקציית הדגמה.

אם בוחרים אחד מהקבצים בחלון OPFS Explorer בכלי הפיתוח, אפשר לשמור אותו בדיסק המקומי. לאחר מכן תוכלו להשתמש באפליקציה כמו SQLite Viewer כדי לבדוק את מסד הנתונים, וכך לוודא ש-SQLite Wasm פועל כמובטח.

אפליקציית SQLite Viewer שמשמשת לפתיחת קובץ מסד נתונים מהדמו של SQLite Wasm.

קבלת עזרה ושליחת משוב

קהילת SQLite אחראית לפיתוח ולתחזוקה של SQLite Wasm. אתם יכולים לקבל עזרה ולשלוח משוב על ידי חיפוש בפורום התמיכה ופרסום הודעות בו. התיעוד המלא זמין באתר של SQLite.