SQLite Wasm trong trình duyệt, được hỗ trợ bởi Hệ thống tệp riêng tư theo nguồn gốc

Sử dụng SQLite để xử lý tất cả nhu cầu lưu trữ của bạn một cách hiệu quả trên web.

Giới thiệu về SQLite

SQLite là một hệ thống quản lý cơ sở dữ liệu quan hệ nguồn mở, nhẹ và phổ biến. Nhiều nhà phát triển sử dụng nền tảng này để lưu trữ dữ liệu theo cách có cấu trúc và dễ sử dụng. Do kích thước nhỏ và yêu cầu thấp về bộ nhớ, SQLite thường được tận dụng làm công cụ cơ sở dữ liệu trong thiết bị di động, ứng dụng dành cho máy tính và trình duyệt web.

Một trong những đặc điểm chính của SQLite là cơ sở dữ liệu không máy chủ, nghĩa là không cần một quy trình máy chủ riêng biệt để vận hành. Thay vào đó, cơ sở dữ liệu được lưu trữ trong một tệp duy nhất trên thiết bị của người dùng, giúp dễ dàng tích hợp với các ứng dụng.

Biểu trưng SQLite.

SQLite dựa trên Web assembly

Có một số phiên bản SQLite không chính thức dựa trên Web hội (Wom), cho phép sử dụng phiên bản này trong các trình duyệt web, ví dụ: sql.js. Dự án phụ WASM/JS sqlite3 là nỗ lực đầu tiên liên quan chính thức với dự án SQLite tạo các bản dựng của Wasm của thư viện, thành viên của dòng sản phẩm SQLite được hỗ trợ. Mục tiêu cụ thể của dự án này bao gồm:

  • Liên kết API sqlite3 cấp thấp càng gần với API C càng tốt về mức sử dụng.
  • API hướng đối tượng cấp cao hơn, gần giống với sql.jscách triển khai kiểu Node.js hơn, liên quan trực tiếp đến API cấp thấp. Bạn phải sử dụng API này qua cùng một luồng với API cấp thấp.
  • API dựa trên Worker nói đến các API trước đó thông qua thông báo Worker. Tính năng này được dùng trong luồng chính, với các API cấp thấp hơn được cài đặt trong luồng Worker và giao tiếp với các API đó qua thông báo của Worker.
  • Một biến thể dựa trên Promise của Worker (API Worker) ẩn hoàn toàn các khía cạnh giao tiếp giữa các luồng với người dùng.
  • Hỗ trợ lưu trữ ổn định phía máy khách bằng cách sử dụng các API JavaScript có sẵn, bao gồm cả Hệ thống tệp riêng tư gốc (OPFS).

Sử dụng SQLite Wasm với phần phụ trợ cố định của Hệ thống tệp riêng tư gốc

Cài đặt thư viện qua npm

Cài đặt gói @sqlite.org/sqlite-wasm từ npm bằng lệnh sau:

npm install @sqlite.org/sqlite-wasm

Hệ thống tệp riêng tư gốc

Hệ thống tệp riêng tư gốc (OPFS, một phần của API Truy cập hệ thống tệp) được tăng cường bằng một giao diện đặc biệt mang lại quyền truy cập rất hiệu quả vào dữ liệu. Nền tảng mới này khác với các nền tảng hiện có nhờ cung cấp quyền ghi tại chỗ và độc quyền vào nội dung của tệp. Thay đổi này cùng với khả năng đọc một cách nhất quán các nội dung sửa đổi chưa được chỉnh sửa và khả năng sử dụng của một biến thể đồng bộ trên các worker chuyên dụng, giúp cải thiện đáng kể hiệu suất và bỏ chặn các trường hợp sử dụng mới.

Như bạn có thể hình dung, điểm cuối cùng trong mục tiêu của dự án là Hỗ trợ lưu trữ lâu dài phía máy khách bằng API JavaScript có sẵn, đi kèm với các yêu cầu nghiêm ngặt về hiệu suất liên quan đến việc duy trì dữ liệu vào tệp cơ sở dữ liệu. Đây là nơi Hệ thống tệp riêng tư gốc và cụ thể hơn là phương thức createSyncAccessHandle() của các đối tượng FileSystemFileHandle phát huy tác dụng. Phương thức này trả về một Promise sẽ phân giải đối tượng FileSystemSyncAccessHandle có thể dùng để đọc đồng bộ từ và ghi vào tệp. Bản chất đồng bộ của phương thức này mang lại các lợi thế về hiệu suất, nhưng do đó, bạn chỉ có thể sử dụng phương thức này trong các Trình chạy web chuyên dụng cho các tệp trong Hệ thống tệp riêng tư gốc để không thể chặn luồng chính.

Đặt tiêu đề bắt buộc

Ngoài các tệp khác, tệp lưu trữ SQLite Wasm đã tải xuống chứa các tệp sqlite3.jssqlite3.wasm, tạo thành bản dựng sqlite3 WASM/JS. Thư mục jswasm chứa các tệp phân phối chính sqlite3, còn thư mục cấp cao nhất chứa các ứng dụng minh hoạ và kiểm thử. Các trình duyệt sẽ không phân phát các tệp Wasm từ các URL file://. Vì vậy, mọi ứng dụng bạn tạo bằng phương thức này đều cần có một máy chủ web và máy chủ đó phải bao gồm các tiêu đề sau đây trong phản hồi khi phân phát tệp:

  • Cross-Origin-Opener-Policy được đặt thành lệnh same-origin, lệnh này sẽ tách riêng ngữ cảnh duyệt web với các tài liệu cùng nguồn gốc. Tài liệu trên nhiều nguồn gốc không được tải trong cùng một ngữ cảnh duyệt web.
  • Cross-Origin-Embedder-Policy được đặt thành lệnh require-corp, để tài liệu chỉ có thể tải tài nguyên từ cùng một nguồn gốc, hoặc các tài nguyên được đánh dấu rõ ràng là có thể tải từ nguồn gốc khác.

Lý do của các tiêu đề này là do SQLite Wasm phụ thuộc vào SharedArrayBuffer và việc đặt các tiêu đề này là một phần trong yêu cầu về bảo mật.

Nếu kiểm tra lưu lượng truy cập bằng Công cụ cho nhà phát triển, bạn sẽ tìm thấy những thông tin sau:

Hai tiêu đề nêu trên, Cross-Origin-Nhúng-Policy và Cross-Origin-Opener-Policy, được làm nổi bật trong Công cụ của Chrome cho nhà phát triển.

Kiểm tra tốc độ

Nhóm SQLite đã chạy một số phép đo điểm chuẩn khi triển khai WebAssembly so với Web SQL không dùng nữa. Các điểm chuẩn này cho thấy SQLite Wasm thường có tốc độ nhanh như Web SQL. Đôi khi chậm hơn một chút, đôi khi nhanh hơn một chút. Xem tất cả thông tin chi tiết trên trang kết quả.

Mã mẫu bắt đầu

Như đã đề cập trước đó, SQLite Wasm với phần phụ trợ lưu trữ riêng của Hệ thống tệp gốc cần chạy từ ngữ cảnh Worker. Tin vui là thư viện sẽ tự động xử lý tất cả các việc này cho bạn và bạn có thể sử dụng thư viện ngay từ luồng chính.

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);
  }
})();

Bản minh hoạ

Xem cách hoạt động của mã ở trên trong bản minh hoạ. Hãy nhớ xem mã nguồn trên Glitch. Hãy lưu ý rằng vì sao phiên bản nhúng bên dưới không sử dụng phần phụ trợ OPFS, nhưng khi bạn mở bản minh hoạ trong một thẻ riêng thì điều này sẽ xảy ra.

Gỡ lỗi hệ thống tệp riêng tư gốc

Để gỡ lỗi cho đầu ra Hệ thống tệp riêng tư gốc của SQLite Wasm, hãy sử dụng tiện ích OPFS Explorer của Chrome.

OPFS Explorer trong Cửa hàng Chrome trực tuyến.

Sau khi cài đặt tiện ích, hãy mở Công cụ của Chrome cho nhà phát triển, chọn thẻ OPFS Explorer (Trình khám phá OPFS) là bạn đã sẵn sàng kiểm tra những gì SQLite Wasm ghi vào Hệ thống tệp riêng tư gốc.

Tiện ích OPFS Explorer của Chrome hiển thị cấu trúc Hệ thống tệp riêng tư gốc của ứng dụng minh hoạ.

Nếu nhấp vào bất kỳ tệp nào trong cửa sổ OPFS Explorer trong Công cụ cho nhà phát triển, thì bạn có thể lưu tệp đó vào ổ đĩa cục bộ. Sau đó, bạn có thể sử dụng một ứng dụng như SQLite Viewer để kiểm tra cơ sở dữ liệu, nhờ đó, bạn có thể tự đảm bảo rằng SQLite Wasm thực sự hoạt động như đã hứa.

Ứng dụng SQLite Viewer dùng để mở tệp cơ sở dữ liệu từ bản minh hoạ SQLite Wasm.

Nhận trợ giúp và cung cấp ý kiến phản hồi

SQLite Wasm do cộng đồng SQLite phát triển và duy trì. Nhận trợ giúp và đưa ra ý kiến phản hồi bằng cách tìm kiếm và đăng lên diễn đàn hỗ trợ. Tài liệu đầy đủ có trên trang web SQLite.

Xác nhận

Hình ảnh chính của Tobias Fischer trên Unsplash.