Fix Cloudflare OG: ship .wasm as module imports, not inlined bytes#1
Open
scottmessinger wants to merge 3 commits into
Open
Fix Cloudflare OG: ship .wasm as module imports, not inlined bytes#1scottmessinger wants to merge 3 commits into
scottmessinger wants to merge 3 commits into
Conversation
The esbuild `binary` loader embedded resvg/yoga `.wasm` as a Uint8Array in
dist. At runtime resvg/yoga then received raw bytes and called
`WebAssembly.instantiate(bytes)`, which Cloudflare's workerd forbids
("Wasm code generation disallowed by embedder").
Mark `.wasm` as external so the imports survive into dist as real ES module
imports, and ship `vendors/` alongside `dist/`. The downstream bundler
(Vite + @astrojs/cloudflare) then compiles them into precompiled
`WebAssembly.Module` instances at deploy time, which workerd accepts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Fixes Cloudflare Workers OG image generation by switching the build from inlining .wasm files to leaving them as ES module imports that the downstream bundler can compile into precompiled WebAssembly.Module instances (required by workerd, which disallows runtime wasm compilation).
Changes:
bin/esbuild.js: mark.wasmasexternalso imports remain real ES module imports indist/index.jsinstead of being copied/inlined.package.json: shipvendors/so the emitted../vendors/*.wasmimport paths resolve from the installed package, and add apreparescript so the build runs after install.
Reviewed changes
Copilot reviewed 1 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| packages/workers-og/bin/esbuild.js | Replaces the .wasm loader config with external: ["*.wasm"] plus an explanatory comment. |
| packages/workers-og/package.json | Includes vendors in published files and adds a prepare script invoking pnpm build. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
OG image generation fails on Cloudflare Workers with:
src/og.tsalready does the right thing — it imports the resvg/yoga wasm as modules and callsinitWasm(resvgWasm as WebAssembly.Module)/initYoga(yogaWasm). Butbin/esbuild.jsusedloader: { ".wasm": "binary" }, which embeds each.wasmas aUint8Arrayin the publisheddist. At runtime resvg/yoga therefore receive raw bytes and callWebAssembly.instantiate(bytes), which Cloudflare'sworkerdforbids (it disallows compiling wasm at runtime — only precompiledWebAssembly.Modules may be instantiated).Fix
bin/esbuild.js: mark.wasmasexternalinstead of inlining it asbinary. The imports now survive intodist/index.jsas real ES module imports (import … from "../vendors/*.wasm").package.json: shipvendors/alongsidedist/so those import paths resolve from the installed package.The downstream bundler (Vite +
@astrojs/cloudflare) then compiles these.wasmimports into precompiledWebAssembly.Moduleinstances at deploy time, whichworkerdaccepts.dist/index.jsdrops from ~2.2 MB to ~393 KB now that the wasm is no longer base64-inlined.Verification
Consumed from the marketing site (Astro +
@astrojs/cloudflare):resvg.*.wasm/yoga.*.wasmas separate module files and the server chunk imports them — no inlined bytes.🤖 Generated with Claude Code