Sử dụng SQLite để xử lý hiệu quả mọi nhu cầu về bộ nhớ trên web.
SQLite là một hệ thống quản lý cơ sở dữ liệu quan hệ nguồn mở, nhẹ, được nhúng và phổ biến. Nhiều nhà phát triển sử dụng API 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 bộ nhớ thấp, SQLite thường được tận dụng làm công cụ cơ sở dữ liệu trong các thiết bị di động, ứng dụng máy tính và trình duyệt web.
Một trong những tính năng chính của SQLite là đây là cơ sở dữ liệu không có máy chủ, nghĩa là không yêu cầu quy trình máy chủ riêng để hoạt động. 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ào các ứng dụng.
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 (dễ) để sử dụng trong các trình duyệt web, ví dụ: sql.js. Dự án phụ sqlite3 WASM/JS là dự án đầu tiên chính thức liên kết với dự án SQLite tạo ra các bản dựng Wasm của thư viện thành viên thuộc nhóm nội dung phân phối SQLite được hỗ trợ. Các mục tiêu cụ thể của dự án này bao gồm:
- Liên kết một API sqlite3 cấp thấp gần với API C nhất khả thi về mặt sử dụng.
- Một API hướng đối tượng cấp cao hơn, tương tự như sql.js và các phương thức triển khai kiểu Node.js, giao tiếp trực tiếp với API cấp thấp. Bạn phải sử dụng API này từ cùng một luồng với API cấp thấp.
- Một API dựa trên Worker giao tiếp với các API trước đó thông qua thông báo Worker. Lớp 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 đó thông qua thông báo Worker.
- Một biến thể dựa trên Lời hứa của API Worker ẩn hoàn toàn các khía cạnh giao tiếp giữa luồng khỏi người dùng.
- Hỗ trợ lưu trữ phía máy khách một cách ổn định bằ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 Hệ thống tệp riêng tư ở nguồn gốc
Cài đặt thư viện từ 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 nền tảng đặc biệt mang lại khả năng 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ó ở chỗ 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 nhất quán các nội dung sửa đổi chưa được làm mới và khả năng có 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: Hỗ trợ lưu trữ lâu dài phía máy khách bằng các 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 lưu 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 đối tượng FileSystemFileHandle
phát huy tác dụng. Phương thức này trả về một Lời hứa phân giải thành đối tượng FileSystemSyncAccessHandle
có thể dùng để đồng bộ đọc và ghi vào tệp. Tính chất đồng bộ của phương thức này mang lại 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 bên trong Trình chạy web chuyên dụng cho các tệp trong Hệ thống tệp riêng tư của nguồn gốc để không thể chặn luồng chính.
Đặt tiêu đề bắt buộc
Trong số các tệp khác, tệp lưu trữ SQLite Wasm đã tải xuống chứa các tệp sqlite3.js
và sqlite3.wasm
, tạo nên bản dựng sqlite3 WASM/JS. Thư mục jswasm
chứa các sản phẩm chính của sqlite3 và thư mục cấp cao nhất chứa các ứng dụng minh hoạ và kiểm thử. Trình duyệt sẽ không phân phát tệp Wasm từ các URL file://
, vì vậy, mọi ứng dụng bạn tạo bằng cách này đều yêu cầu một máy chủ web và máy chủ đó phải đưa các tiêu đề sau vào phản hồi khi phân phát tệp:
Cross-Origin-Opener-Policy
được đặt thành lệnhsame-origin
, giúp tách riêng ngữ cảnh duyệt web chỉ dành cho các tài liệu có 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ệnhrequire-corp
, vì vậy, một tài liệu chỉ có thể tải tài nguyên từ cùng một nguồn gốc hoặc tài nguyên được đánh dấu rõ ràng là có thể tải từ một nguồn gốc khác.
Nguyên nhân của những 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 các yêu cầu về bảo mật của SQLite.
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ẽ thấy các thông tin sau:
Speedtest
Nhóm SQLite đã chạy một số phép đo điểm chuẩn về việc triển khai WebAssembly so với Web SQL không còn được dùng nữa. Các điểm chuẩn này cho thấy SQLite Wasm thường 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ữ Hệ thống tệp riêng tư của nguồn gốc cần chạy trong ngữ cảnh Worker. Tin vui là thư viện sẽ tự động xử lý tất cả những 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 mã trên trong bản minh hoạ. Hãy nhớ xem mã nguồn trên Glitch. Lưu ý cách 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ì phiên bản này sẽ sử dụng.
Gỡ lỗi Hệ thống tệp riêng tư của Origin
Để gỡ lỗi đầu ra Hệ thống tệp riêng của nguồn gốc SQLite Wasm, hãy sử dụng tiện ích Chrome OPFS Explorer.
Sau khi cài đặt tiện ích này, 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). Sau đó, bạn có thể kiểm tra dữ liệu mà SQLite Wasm ghi vào Hệ thống tệp gốc riêng tư.
Nếu chọn bất kỳ tệp nào trong cửa sổ Trình khám phá OPFS 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ự tin rằng SQLite Wasm thực sự hoạt động như đã hứa.
Yêu cầu trợ giúp và đưa ra ý kiến phản hồi
SQLite Wasm được cộng đồng SQLite phát triển và duy trì. Hãy tìm kiếm và đăng nội dung vào diễn đàn hỗ trợ để được trợ giúp và gửi ý kiến phản hồi. Bạn có thể xem tài liệu đầy đủ trên trang web SQLite.