Commit Graph

4 Commits

Author SHA1 Message Date
Jerry Zhao 0394b98633 test(og): pass POSIX-style ids to the og-font-patch transform fixture (#1925) 2026-06-11 23:00:00 +01:00
James Anderson 5db85cb6eb perf(og): dedupe resvg/yoga wasm in server bundle (#1801)
* fix(og): dedupe resvg/yoga wasm in server bundle

vinext shipped each @vercel/og WASM module twice — once per loader
strategy — even though only one strategy runs at runtime, wasting
~1.4 MiB per build.

resvg.wasm was emitted as a hashed asset by the `import("./resvg.wasm?module")`
path (used by workerd) AND copied as a second byte-identical root file
purely for the Node.js disk-read fallback. yoga.wasm was emitted as a
hashed asset AND inlined as a ~95 KiB base64 blob in index.edge for the
Node.js fallback.

This change makes each WASM ship exactly once, with every loader path
resolving to the single emitted file:

- og-font-patch (index.ts): drop the yoga base64 preamble and switch the
  Node.js yoga fallback to a disk read (node:fs + new URL), mirroring resvg.
- og-assets.ts: in generateBundle, when the bundler already emitted the
  WASM asset, rewrite the `new URL("./x.wasm", import.meta.url)` fallback
  reference to point at the emitted sibling asset; only copy a root file in
  writeBundle when no asset was emitted.

The dedup decision keys off whether the bundler emitted the asset, never
the deploy target, so it benefits Node/self-hosted builds too. No platform
detection.

* fix(og): keep chunk sourcemap in sync on wasm fallback rewrite

Use magic-string (already a dependency) for the generateBundle fallback-URL
rewrite so the chunk's sourcemap stays valid after the edit, instead of a
blind string replace that invalidated chunk.map.

Also extract copyMissingOgWasm() as a dependency-injected helper and make the
copy-fallback test hermetic: yoga.wasm is not shipped by @vercel/og (it is
synthesized from base64 by the og-font-patch transform), so the prior test
only passed when a previous build had left yoga.wasm in node_modules.

* test(og): cover cross-directory fallback rewrite; document cross-hook state

Address bonk review observations: add a test asserting the path.posix.relative
rewrite produces a directory-relative ref when the chunk and emitted asset live
in different dirs (the main behavioral win), and document the generateBundle->
writeBundle dedupedBases dependency.
2026-06-07 00:42:51 +00:00
James Anderson 3f287ff5ab chore: remove useless code assertion tests and snaps (#1023)
* chore: remove useless code assertion tests and snaps

* .
2026-05-02 19:54:31 +00:00
Nathan Nguyen 750d8a44e4 fix: use dynamic WASM imports in og-font-patch for Node.js compat (#644)
* fix: use dynamic WASM imports in og-font-patch for Node.js compat

Replace static `import X from "./X.wasm?module"` (workerd-only) with
dynamic `import()` + catch fallback so the same build output runs on
both Cloudflare Workers and Node.js (`vinext start`).

- Yoga WASM (~70KB): dynamic import with inline base64 fallback
- Resvg WASM (~1.3MB): dynamic import with disk-read fallback via
  new URL() + readFileSync + WebAssembly.compile

Fixes #642

* fix: move resvg new URL() inside catch handler for workerd compat

In workerd, import.meta.url is "worker" (not a valid URL base), so
new URL("./resvg.wasm", import.meta.url) at the top level throws
TypeError at module load time. Move it inside the .catch() handler
which only runs on Node.js where import.meta.url is a file:// URL.

* refactor: address review — remove dead atob branch, async readFile, dedup tests

- Remove unreachable atob/Uint8Array fallback in yoga Node.js path
  (mod === null only on Node.js where Buffer always exists)
- Use fs.promises.readFile instead of readFileSync for resvg disk
  fallback (non-blocking, idiomatic in async chain)
- Deduplicate test transforms with shared beforeAll
- Remove unnecessary IIFE in test setup
- Add assertions for Buffer.from and async readFile
2026-03-23 08:59:59 +00:00