Skip to content

fix(pglite): only build asset URLs when PGlite loads the assets - #1175

Merged
tdrz merged 1 commit into
electric-sql:mainfrom
steelydylan:fix/lazy-asset-urls
Oct 30, 2026
Merged

tdrz merged 1 commit into
electric-sql:mainfrom
steelydylan:fix/lazy-asset-urls

Conversation

@steelydylan

Copy link
Copy Markdown
Contributor

Problem

The esbuild section of the bundler docs says to pass pgliteWasmModule, initdbWasmModule and fsBundle when PGlite cannot find its own files. This does not work when the bundle has no usable import.meta.url. For example, esbuild replaces import.meta with {} in IIFE output, so import.meta.url is undefined.

PGlite still builds these URLs even when all three options are passed:

  • new URL('../release/pglite.data', import.meta.url) in PGlite#init, before it checks options.fsBundle
  • new URL('../release/pglite.wasm', import.meta.url) in the instantiateWasm callback, before it checks options.pgliteWasmModule
  • new URL('../release/initdb.wasm', import.meta.url) in the instantiateWasm callback of initdb

new URL('./x', undefined) throws, so PGlite.create() fails with TypeError: Failed to construct 'URL': Invalid URL even though the URL is never used.

Fix

The URLs are now built only when PGlite needs to load the file:

  • pglite.data: the new URL(...) moved into the branch that calls getFsBundle.
  • pglite.wasm and initdb.wasm: instantiateWasm in pglite-utils now takes a function that returns the URL. It returns early when a module is passed and only calls the function otherwise. pglite-utils is private and these are its only two callers.

The new URL('...', import.meta.url) expressions are unchanged, so bundlers that rewrite this pattern (Vite, webpack, Rollup) still find them. The background downloads in startArtifactDownload were already guarded by the options and are not changed.

Tests

I added tests/targets/web/chromium-iife-bundle.test.web.js. It bundles dist/index.js with esbuild as an IIFE, loads it in Chromium through Playwright, passes the three options as the docs describe, and runs SELECT 1. It serves files with page.route, so it does not depend on the http-server used by the other web tests. esbuild is added as a dev dependency of @electric-sql/pglite. It is the same version tsup already uses, so the lockfile only gets a new importer entry.

  • Without the fix the test fails with TypeError: Failed to construct 'URL': Invalid URL. With the fix it passes.
  • chromium-memory.test.web.js still passes.
  • pnpm test:basic (329 passed, 1 skipped), pnpm test:node, pnpm stylecheck and pnpm typecheck pass.

I used the release/ files from the latest main CI run (pglite-interim-build-files-node-v22.x) and did not rebuild the WASM. I only ran the Chromium web tests locally, not Firefox or WebKit.

A patch changeset is included.

@tdrz tdrz left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@tdrz
tdrz merged commit 1cf7e86 into electric-sql:main Oct 30, 2026
14 of 17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants