From 8bbe84485867f17bb41e95fe7aae3a815303b5a1 Mon Sep 17 00:00:00 2001 From: Kacper Kula Date: Sun, 3 May 2026 15:27:39 +0100 Subject: [PATCH] fix: passing wasm between workers to reduce bundle size --- esbuild.config.mjs | 30 ++----------------- .../database/sqlocal/sqlocalDatabaseProxy.ts | 4 ++- .../database/sqlocal/sqlocalWorkerDatabase.ts | 15 ++++++---- 3 files changed, 14 insertions(+), 35 deletions(-) diff --git a/esbuild.config.mjs b/esbuild.config.mjs index b58689d..a53fc52 100644 --- a/esbuild.config.mjs +++ b/esbuild.config.mjs @@ -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: { diff --git a/src/modules/database/sqlocal/sqlocalDatabaseProxy.ts b/src/modules/database/sqlocal/sqlocalDatabaseProxy.ts index 9a8129f..af83b59 100644 --- a/src/modules/database/sqlocal/sqlocalDatabaseProxy.ts +++ b/src/modules/database/sqlocal/sqlocalDatabaseProxy.ts @@ -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; diff --git a/src/modules/database/sqlocal/sqlocalWorkerDatabase.ts b/src/modules/database/sqlocal/sqlocalWorkerDatabase.ts index f7c1085..5b246fc 100644 --- a/src/modules/database/sqlocal/sqlocalWorkerDatabase.ts +++ b/src/modules/database/sqlocal/sqlocalWorkerDatabase.ts @@ -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();