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

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

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

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

הלוגו של SQLite.

‫SQLite שמבוסס על Web Assembly

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

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

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

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

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

npm install @sqlite.org/sqlite-wasm

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

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

כפי שאפשר להבין, הנקודה האחרונה ביעדי הפרויקט, תמיכה באחסון נתונים בצד הלקוח באופן קבוע באמצעות JavaScript API זמינים, מגיעה עם דרישות ביצועים מחמירות לגבי שמירת נתונים בקובץ מסד הנתונים. כאן נכנס לתמונה Origin Private File System, ובאופן ספציפי יותר, השיטה createSyncAccessHandle() של אובייקטים FileSystemFileHandle. השיטה הזו מחזירה Promise שמקבל ערך של אובייקט 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);
  }
})();

הדגמה (דמו)

אפשר לראות את הקוד שלמעלה בפעולה בהדגמה. מומלץ לעיין בקוד המקור ב-GitHub. שימו לב שהגרסה המוטמעת שלמטה לא משתמשת בעורף של OPFS, אבל אם תפתחו את ההדגמה בכרטיסייה נפרדת היא כן תשתמש בו.

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

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

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

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

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

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

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

קבלת עזרה ומתן משוב

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