Build seekdb for WebAssembly
Compile seekdb with Emscripten into a WebAssembly engine that runs inside a browser page, together with its JavaScript API and a browser SQL shell.
Prerequisites
- macOS or Linux host
- Emscripten 6.0.12, the version in
deps/init/wasm/emscripten-version, with itsemcconPATH rustup, Python 3.12 or later andcurlonPATH- Node.js 24 or later to run the tests
- At least 20 GB of free disk space recommended for dependencies, the SDK and build directories
Build
Activate the pinned Emscripten SDK, prepare dependencies, then build with Bazel:
# emcc must come from the pinned Emscripten SDK.
export EMSCRIPTEN=/path/to/emsdk/upstream/emscripten
export PATH="$EMSCRIPTEN:$PATH"
python3 build.py init --wasm
python3 build.py build --config=wasm seekdb
init --wasm prepares host dependencies, the pinned Rust toolchain, Wasm base libraries, adapted headers and the Emscripten sysroot in deps/wasm. Subsequent builds need only the final build command. Bazel builds and caches the remaining source libraries and Rust libraries. Set SEEKDB_WASM_DEPS for both commands only if you need a different SDK directory; it does not select the target platform.
The engine and its JS, HTML and CSS assets are in build/bin/src/wasm/dist/. python3 build.py clean clears Bazel build outputs and preserves deps/wasm.
Build directory contents
seekdb_wasm_database.mjsandseekdb_wasm_database.wasm: the engine, its Rust libraries and third-party libraries linked into one module, with Emscripten's JavaScript runtimedatabase.mjs: the JavaScript API, with thedatabase-worker.mjs,worker-server.mjs,runtime-host.mjs,storage-cleanup-worker.mjsandmysql-*.mjsmodules it loadsshell.html,shell.css,shell.mjsandshell-*.mjs: the browser SQL shellengine-version.mjs: the engine version shown by the shell
Serve these files from localhost or over HTTPS with Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp, and .wasm as application/wasm: the engine's threads need SharedArrayBuffer. Opened as file:// URLs, they do not work.
Use it in a page
Serve the shell from the build directory and open the URL it prints:
The shell's commands and storage modes are described in docs/webassembly-shell.md.
A page uses the engine through Database, which runs it in a Worker and speaks the MySQL protocol to it in memory:
import {Database} from './database.mjs';
const db = await Database.open({
moduleURL: new URL('./seekdb_wasm_database.mjs', import.meta.url),
wasmURL: new URL('./seekdb_wasm_database.wasm', import.meta.url),
storage: 'opfs', // or 'memory', the default
});
const session = await db.connect();
const text = new TextDecoder();
for await (const event of session.query('SELECT VERSION()')) {
if (event.kind === 'row') console.log(event.values.map(v => v === null ? null : text.decode(v)));
}
await session.close();
await db.close();
storage: 'memory'keeps the data directory in Wasm memory and starts empty on every open.storage: 'opfs'keeps it in theseekdbdirectory of the origin private file system, needs OPFS and Web Locks, and can be open in only one page of an origin at a time.queryyieldscolumns,rowandcompleteevents. Row values are each column's text bytes asUint8Array, ornullfor SQL NULL.- Each
Database.openstarts a new Worker and engine.close()waits for the engine to shut down and keeps OPFS data;discard()terminates the Worker at once and, for OPFS, removes the stored files;Database.clearPersistentStorage()removes the stored OPFS files without opening an engine. - No TCP port is opened: connect through
connect().