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

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

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

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

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

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