Skip to content

Load esbuild-wasm from esm.sh instead of bundling it - #78

Merged
titouanmathis merged 2 commits into
mainfrom
fix/esbuild-wasm-from-esm-sh
Aug 10, 2026
Merged

Load esbuild-wasm from esm.sh instead of bundling it#78
titouanmathis merged 2 commits into
mainfrom
fix/esbuild-wasm-from-esm-sh

Conversation

@titouanmathis

Copy link
Copy Markdown
Contributor

Problem

The playground bundles esbuild-wasm through webpack and loads its wasm with new URL('esbuild-wasm/esbuild.wasm', import.meta.url) in Iframe.ts. Under webpack 5.109+, that bare-specifier new URL(..., import.meta.url) is no longer resolved to a real asset URL — it compiles to a broken empty-module reference, so at runtime wasmURL becomes .../[object Object] (404). esbuild then fails to initialize and throws a cryptic TypeError: g[e] is not a function (caught by updateScript, logged as "script not updated due to some errors"), so the preview never runs the compiled script.

Fix

Stop bundling esbuild-wasm through webpack and load the whole dependency from esm.sh at runtime — exactly mirroring how the playground already loads modern-monaco from esm.sh:

  • scripts/shared.js reads the installed esbuild-wasm version and exposes it as an esbuild __ESBUILD_WASM_VERSION__ define (same pattern as __MODERN_MONACO_VERSION__).
  • Iframe.ts imports https://esm.sh/esbuild-wasm@<version> with a /* webpackIgnore: true */ magic comment and points wasmURL at the matching esm.sh URL. esm.sh serves the CJS API on the default export, so it is unwrapped with mod.default ?? mod.

The esbuild-wasm dependency stays in package.json — it is still used by scripts/shared.js (the build tool) and for the type-only import.

This also removes the ~11 MB wasm and the esbuild chunk from consumers' built output.

Verification

Verified end-to-end in a real browser against the @studiometa/ui playground build: the console now logs "script updated!", the preview renders, and the esbuild chunk + 11 MB wasm are gone from the output. The emitted dist/front/js/components/Iframe.js references https://esm.sh/esbuild-wasm@0.24.2 and no longer references new URL("esbuild-wasm/esbuild.wasm", ...). npm run build, oxlint, prettier -c, and the full vitest suite (153 tests) all pass.

Relation to other PRs

Independent of / stacks on top of #77 (fix/virtual-loader-exports-resolution) — a separate webpack 5.109+ resolution fix.

🤖 Generated with Claude Code

https://claude.ai/code/session_01HKLcgvaDcjK9ohA3fg7Ssq

titouanmathis and others added 2 commits August 10, 2026 11:08
The bare-specifier `new URL('esbuild-wasm/esbuild.wasm', import.meta.url)`
is no longer resolved to a real asset URL by webpack 5.109+, so the wasmURL
became `.../[object Object]` (404) and esbuild failed to initialize with a
cryptic `g[e] is not a function`, leaving the preview unable to run the
compiled script. Load the whole esbuild-wasm dependency from esm.sh at
runtime instead, mirroring how modern-monaco is loaded, with the installed
version inlined at build time via a `__ESBUILD_WASM_VERSION__` define. This
also removes the ~11 MB wasm and the esbuild chunk from consumer bundles.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKLcgvaDcjK9ohA3fg7Ssq
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKLcgvaDcjK9ohA3fg7Ssq
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 10, 2026

Copy link
Copy Markdown

Deploying studiometa-playground with  Cloudflare Pages  Cloudflare Pages

Latest commit: acc7627
Status: ✅  Deploy successful!
Preview URL: https://40571478.studiometa-playground.pages.dev
Branch Preview URL: https://fix-esbuild-wasm-from-esm-sh.studiometa-playground.pages.dev

View logs

@github-actions

Copy link
Copy Markdown

Size Change: +49 B (+0.09%)

Total Size: 54.2 kB

📦 View Changed
Filename Size Change
packages/playground/dist/front/js/components/Iframe.js 1.79 kB +49 B (+2.82%)
ℹ️ View Unchanged
Filename Size
packages/playground-preview/dist/element.js 10 kB
packages/playground-preview/dist/index.js 10 kB
packages/playground/dist/front/css/app.css 4.26 kB
packages/playground/dist/front/js/app.js 139 B
packages/playground/dist/front/js/components/Editor.js 929 B
packages/playground/dist/front/js/components/Editors.js 265 B
packages/playground/dist/front/js/components/EditorVisibility.js 343 B
packages/playground/dist/front/js/components/HeaderSwitcher.js 436 B
packages/playground/dist/front/js/components/HtmlEditor.js 748 B
packages/playground/dist/front/js/components/IframeReloader.js 182 B
packages/playground/dist/front/js/components/LayoutReactive.js 616 B
packages/playground/dist/front/js/components/LayoutSwitcher.js 341 B
packages/playground/dist/front/js/components/Playground.js 1.14 kB
packages/playground/dist/front/js/components/Resizable.js 992 B
packages/playground/dist/front/js/components/ResizableCursor.js 298 B
packages/playground/dist/front/js/components/ResizableSync.js 512 B
packages/playground/dist/front/js/components/ScriptEditor.js 520 B
packages/playground/dist/front/js/components/StyleEditor.js 247 B
packages/playground/dist/front/js/components/Switcher.js 334 B
packages/playground/dist/front/js/components/ThemeSwitcher.js 456 B
packages/playground/dist/front/js/create-playground.js 196 B
packages/playground/dist/front/js/loaders/html.js 124 B
packages/playground/dist/front/js/loaders/script.js 124 B
packages/playground/dist/front/js/loaders/style.js 124 B
packages/playground/dist/front/js/store/config.js 468 B
packages/playground/dist/front/js/store/content.js 400 B
packages/playground/dist/front/js/store/header.js 573 B
packages/playground/dist/front/js/store/index.js 109 B
packages/playground/dist/front/js/store/layout.js 606 B
packages/playground/dist/front/js/store/theme.js 516 B
packages/playground/dist/front/js/utils/js/index.js 436 B
packages/playground/dist/front/js/utils/monaco.js 844 B
packages/playground/dist/front/js/utils/patch-iframe-url.js 362 B
packages/playground/dist/front/js/utils/resolve-import-map-urls.js 246 B
packages/playground/dist/front/js/utils/storage/AbstractStorageProvider.js 138 B
packages/playground/dist/front/js/utils/storage/FallbackStorageProvider.js 266 B
packages/playground/dist/front/js/utils/storage/index.js 479 B
packages/playground/dist/front/js/utils/storage/LocalStorageProvider.js 254 B
packages/playground/dist/front/js/utils/storage/MemoryStorageProvider.js 206 B
packages/playground/dist/front/js/utils/storage/MultiStorageProvider.js 307 B
packages/playground/dist/front/js/utils/storage/StorageProviderInterface.js 73 B
packages/playground/dist/front/js/utils/storage/SyncedStorageProvider.js 292 B
packages/playground/dist/front/js/utils/storage/URLStorageProvider.js 365 B
packages/playground/dist/front/js/utils/storage/WatchableStore.js 307 B
packages/playground/dist/front/js/utils/storage/ZipStorageProvider.js 271 B
packages/playground/dist/front/js/utils/twig/index.js 435 B
packages/playground/dist/index.js 154 B
packages/playground/dist/lib/plugins/PlaygroundDependenciesPlugin.js 4.36 kB
packages/playground/dist/lib/plugins/PlaygroundLoadersPlugin.js 511 B
packages/playground/dist/lib/presets/html-webpack-script-type-module.js 288 B
packages/playground/dist/lib/presets/playground.js 1.07 kB
packages/playground/dist/lib/presets/production-build.js 261 B
packages/playground/dist/lib/tailwind-config.js 509 B
packages/playground/dist/lib/utils/resolve-dependencies.js 3.04 kB
packages/playground/dist/lib/utils/resolve-public-path.js 283 B
packages/playground/dist/lib/utils/zip.js 310 B
packages/playground/dist/preset.js 190 B
packages/playground/dist/tailwind.js 113 B

compressed-size-action

@codecov

codecov Bot commented Aug 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 34.00%. Comparing base (82f3679) to head (acc7627).

Files with missing lines Patch % Lines
...kages/playground/src/front/js/components/Iframe.ts 0.00% 3 Missing ⚠️

❌ Your patch check has failed because the patch coverage (0.00%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #78      +/-   ##
==========================================
- Coverage   34.06%   34.00%   -0.07%     
==========================================
  Files          55       55              
  Lines        1133     1135       +2     
  Branches      231      232       +1     
==========================================
  Hits          386      386              
- Misses        719      721       +2     
  Partials       28       28              
Flag Coverage Δ
playground 34.00% <0.00%> (-0.07%) ⬇️
playground-preview 34.00% <0.00%> (-0.07%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@titouanmathis
titouanmathis merged commit 2a1b294 into main Aug 10, 2026
7 of 8 checks passed
@titouanmathis
titouanmathis deleted the fix/esbuild-wasm-from-esm-sh branch August 10, 2026 09:19
titouanmathis added a commit to studiometa/ui that referenced this pull request Sep 1, 2026
Moving to `@studiometa/playground` 0.4.0 left
`patches/@studiometa+playground+0.3.13.patch` pinned to a version no
longer installed, so `patch-package` failed in `postinstall` and took
`npm ci` down with it. Every CI job died at install, before running any
of this branch's code.

Both hunks shipped upstream. Loading `esbuild-wasm` from esm.sh landed in
0.3.14 via studiometa/playground#78, and resolving the package root
through `createRequire`/`realpathSync` is in 0.4.0's
`PlaygroundLoadersPlugin` — verified against the installed dist rather
than inferred. patch-package's own failure message suggests exactly this
outcome: "Maybe this means your patch file is no longer necessary."

`npm ci` now exits 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011izFBQT4AsFcD4tVZz1f7R
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.

1 participant