使用 SQLite 處理網頁上的所有儲存需求,確保效能。
SQLite 是常見的開放原始碼輕量型嵌入式關聯資料庫管理系統。許多開發人員會使用這項服務,以結構化且易於使用的方式儲存資料。SQLite 體積小巧,記憶體需求不高,因此常做為行動裝置、桌上型應用程式和網頁瀏覽器的資料庫引擎。
SQLite 的主要功能之一是無伺服器資料庫,也就是說,不需要獨立的伺服器程序即可運作。資料庫會儲存在使用者裝置的單一檔案中,方便整合到應用程式。
以 Web Assembly 為基礎的 SQLite
目前有許多以 Web Assembly (Wasm) 為基礎的非官方 SQLite 版本,可供網頁瀏覽器使用,例如 sql.js。sqlite3 WASM/JS 子專案是第一個與 SQLite 專案正式相關的專案,可讓程式庫的 Wasm 建構作業成為支援的 SQLite 交付項目系列成員。這項專案的具體目標包括:
- 繫結低階 sqlite3 API,在用法方面盡可能接近 C 語言。
- 這個物件導向 API 屬於較高層級,與 sql.js 和 Node.js 樣式的實作更為相似,可直接與低階 API 通訊。這個 API 必須與低階 API 使用相同的執行緒。
- 以 Worker 為基礎的 API,可透過 Worker 訊息與先前的 API 通訊。這個版本適用於主執行緒,較低層級的 API 會安裝在 Worker 執行緒中,並透過 Worker 訊息與這些 API 通訊。
- Worker API 的 Promise 型變體,可完全向使用者隱藏跨執行緒通訊層面。
- 使用可用的 JavaScript API (包括 Origin Private File System (OPFS)) 支援用戶端持續性儲存空間。
搭配 Origin Private File System 持續性後端使用 SQLite Wasm
從 npm 安裝程式庫
使用下列指令,從 npm 安裝 @sqlite.org/sqlite-wasm 套件:
npm install @sqlite.org/sqlite-wasm
來源私有檔案系統
來源私有檔案系統 (OPFS,屬於 File System Access API) 經過擴增後,可提供特殊介面,讓您以極高的效能存取資料。這個新介面與現有介面不同,可提供檔案內容的專屬寫入存取權,並直接在檔案中寫入內容。這項變更加上持續讀取未排清的修改內容,以及專用工作人員提供的同步變體,大幅提升了效能,並解鎖了新的用途。
如您所想,專案目標的最後一點「使用可用的 JavaScript API 支援持續性用戶端儲存空間」,對將資料保存到資料庫檔案有嚴格的效能要求。這時,來源私有檔案系統 (更具體來說,是 FileSystemFileHandle
物件的 createSyncAccessHandle()
方法) 就能派上用場。這個方法會傳回 Promise,該 Promise 會解析為 FileSystemSyncAccessHandle
物件,可用於同步讀取及寫入檔案。這個方法的同步性質可提升效能,但因此只能在專用的網頁工作人員中使用,適用於 Origin Private File System 中的檔案,因此主執行緒不會遭到封鎖。
設定必要標頭
下載的 SQLite Wasm 封存檔包含 sqlite3.js
和 sqlite3.wasm
檔案,這些檔案構成 sqlite3 WASM/JS 建構版本。jswasm
目錄包含核心 sqlite3 交付項目,頂層目錄則包含示範和測試應用程式。瀏覽器不會從 file://
網址提供 Wasm 檔案,因此您使用這項功能建構的任何應用程式都需要網路伺服器,且該伺服器在提供檔案時,必須在回應中加入下列標頭:
Cross-Origin-Opener-Policy
設為same-origin
指令, 可將瀏覽內容專門隔離至相同來源的文件。 系統不會在相同的瀏覽環境中載入跨來源文件。Cross-Origin-Embedder-Policy
設為require-corp
指令,因此文件只能從相同來源載入資源,或從明確標示為可從其他來源載入的資源。
這些標頭的原因是 SQLite Wasm 依附於 SharedArrayBuffer
,而設定這些標頭是其安全性需求的一部分。
如果您使用開發人員工具檢查流量,應該會看到下列資訊:
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 後端,但如果您在獨立分頁中開啟這個範例,就會使用 OPFS 後端。
偵錯來源私有檔案系統
如要對 SQLite Wasm 的 Origin Private File System 輸出內容進行偵錯,請使用 OPFS Explorer Chrome 擴充功能。
安裝擴充功能後,開啟 Chrome 開發人員工具,選取「OPFS Explorer」分頁,即可檢查 SQLite Wasm 寫入 Origin Private File System 的內容。
如果您在開發人員工具的 OPFS 檔案總管視窗中選取任何檔案,可以將其儲存至本機磁碟。接著,您可以使用 SQLite Viewer 等應用程式檢查資料庫,確認 SQLite Wasm 確實如預期運作。
取得協助及提供意見
SQLite Wasm 由 SQLite 社群開發及維護。如要取得協助及提供意見,請在支援論壇中搜尋及發布貼文。如需完整說明文件,請前往 SQLite 網站。