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

בעזרת SQLite תוכלו לנהל את כל צורכי האחסון שלכם ביעילות באינטרנט.

מידע על SQLite

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

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

הלוגו של SQLite.

SQLite על סמך Web Assembly

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

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

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

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

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

npm install @sqlite.org/sqlite-wasm

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

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

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

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

בין הקבצים האחרים, ארכיון SQLite Wasm שהורדתם מכיל את הקבצים sqlite3.js ו-sqlite3.wasm, שמרכיבים את ה-build של 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.

בדיקת מהירות

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

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

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

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 שבו מוצג מבנה מערכת הקבצים הפרטית המקורית של אפליקציית ההדגמה.

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

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

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

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

אישורים

תמונה ראשית (Hero) מאת Tobias Fischer ב-UnFlood.