fix: passing wasm between workers to reduce bundle size

This commit is contained in:
Kacper Kula 2026-05-03 15:27:39 +01:00
parent 2bb056f616
commit 8bbe844858
3 changed files with 14 additions and 35 deletions

View file

@ -98,34 +98,8 @@ const workerPlugin = {
}));
build.onLoad({ filter: /.*/, namespace: 'sqlocal-worker-code' }, async () => {
// Create a plugin for the worker that resolves virtual imports
const workerVirtualPlugin = {
name: 'worker-virtual',
setup(build) {
// Handle virtual WASM URL for wa-sqlite
build.onResolve({ filter: /^virtual:wa-sqlite-wasm-url$/ }, args => ({
path: args.path,
namespace: 'wa-sqlite-wasm-url',
}));
build.onLoad({ filter: /.*/, namespace: 'wa-sqlite-wasm-url' }, async () => {
const wasmPath = join(process.cwd(), 'node_modules/wa-sqlite/dist/wa-sqlite-async.wasm');
const wasmContents = readFileSync(wasmPath);
const wasmBase64 = wasmContents.toString('base64');
return {
contents: `
const wasmBase64 = "${wasmBase64}";
const wasmBinary = Uint8Array.from(atob(wasmBase64), c => c.charCodeAt(0));
export default wasmBinary;
`,
loader: 'js',
};
});
}
};
// Build sqlocal worker code
// WASM binary is NOT embedded in the worker — it's passed from the main thread via Comlink
const result = await esbuild.build({
entryPoints: ['src/modules/database/sqlocal/sqlocalWorkerDatabase.ts'],
bundle: true,
@ -133,7 +107,7 @@ const workerPlugin = {
format: 'iife',
target: 'es2020',
external: ['fs', 'path', 'obsidian'],
plugins: [wasmPlugin, workerVirtualPlugin, polyfillNode({
plugins: [wasmPlugin, polyfillNode({
})],
minify: process.argv[2] === 'production',
define: {

View file

@ -3,6 +3,8 @@ import * as Comlink from 'comlink';
import { SqlocalWorkerDatabase } from "./sqlocalWorkerDatabase";
import { ColumnDefinition } from "../../../utils/types";
import { sanitise } from "../../../utils/sanitiseColumn";
// @ts-ignore
import wasmBinary from 'virtual:wa-sqlite-wasm-url';
/**
* Main-thread proxy for SqlocalWorkerDatabase.
@ -49,7 +51,7 @@ export class SqlocalDatabaseProxy {
const instance = await new DatabaseWrap(this.dbName);
await instance.connect();
await instance.connect(wasmBinary);
this.db = instance;
this.isConnected = true;

View file

@ -5,10 +5,6 @@ import { IDBBatchAtomicVFS } from 'wa-sqlite/src/examples/IDBBatchAtomicVFS.js';
import { ColumnDefinition } from "../../../utils/types";
import { sanitise } from "../../../utils/sanitiseColumn";
// Get the WASM URL from the virtual module
// @ts-ignore
import wasmBinary from 'virtual:wa-sqlite-wasm-url';
/**
* Retry an async operation with exponential backoff
* @param operation - The async operation to retry
@ -70,6 +66,7 @@ export class SqlocalWorkerDatabase {
private isConnected = false;
private vfsRegistered = false;
private isRecreating = false;
private wasmBinary?: Uint8Array;
constructor(private readonly dbName: string) {
}
@ -109,8 +106,12 @@ export class SqlocalWorkerDatabase {
return this.sqlite3;
}
if (!this.wasmBinary) {
throw new Error('SqlocalWorkerDatabase: wasmBinary not provided. Call connect() with the WASM binary.');
}
try {
const asyncModule = await SQLiteAsyncESMFactory({ wasmBinary, locateFile: (file: string) => file });
const asyncModule = await SQLiteAsyncESMFactory({ wasmBinary: this.wasmBinary, locateFile: (file: string) => file });
// Use Factory to get the actual sqlite3 API
this.sqlite3 = SQLite.Factory(asyncModule);
@ -140,11 +141,13 @@ export class SqlocalWorkerDatabase {
}
}
async connect() {
async connect(wasmBinary: Uint8Array) {
if (this.isConnected) {
return Promise.resolve();
}
this.wasmBinary = wasmBinary;
try {
// Initialize SQLite
await this.initializeSQLite();