mirror of
https://github.com/cloudflare/vinext.git
synced 2026-05-09 08:25:34 +02:00
[PR #356] [MERGED] feat(og): add @next/og / @vercel/og support with Cloudflare Workers compatibility #508
Labels
No labels
enhancement
enhancement
good first issue
help wanted
nextjs-tracking
nextjs-tracking
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/vinext#508
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/cloudflare/vinext/pull/356
Author: @james-elicx
Created: 3/8/2026
Status: ✅ Merged
Merged: 3/8/2026
Merged by: @james-elicx
Base:
main← Head:opencode/proud-pixel📝 Commits (5)
6ea29acfeat(og): add @next/og support with Cloudflare Workers compatibility4031c1crefactor(og): generalize fetch+import.meta.url asset inlining, drop WASM lazy-init patch028476afix(og): inline readFileSync assets from @vercel/og node build8c5c9f0refactor(og): address code review feedbackdb47446refactor(og): use replaceAll instead of split().join()📊 Changes
6 files changed (+407 additions, -16 deletions)
View changed files
➕
examples/app-router-cloudflare/app/api/og/route.tsx(+47 -0)📝
packages/vinext/src/index.ts(+174 -9)📝
packages/vinext/src/shims/og.tsx(+6 -6)📝
playwright.config.ts(+7 -1)➕
tests/e2e/og-image.spec.ts(+126 -0)➕
tests/fixtures/app-basic/app/api/og/route.tsx(+47 -0)📄 Description
Summary
Adds first-class
@next/og(OG image generation) support to vinext, including full compatibility with Cloudflare Workers in both dev (cloudflare-dev) and production (cloudflare-workers) modes.Problem
@vercel/og's edge build (dist/index.edge.js) loads its fallback font at module init time using:In Cloudflare Workers,
import.meta.urlis the string"worker"— not a real URL — sonew URL(...)throwsTypeError: Invalid URL stringand the Worker fails to start before serving any request.A secondary issue was that Vite's esbuild pre-bundler would cache
@vercel/ogbefore our transform hook ran, causing the uncached module to be served into a Node.js context whereWebAssembly.instantiate()is blocked.Fix
vinext:og-inline-fetch-assetstransform plugin (enforce: "pre"):Matches any
fetch(new URL("./asset", import.meta.url)).then(res => res.arrayBuffer())expression — regardless of filename — and replaces it with an inline base64 IIFE that reads the file from disk at Vite transform time and decodes it synchronously. This eliminates the runtime fetch entirely and works in all environments.This is intentionally general: it handles any font version bump in
@vercel/og, additional fonts, and any other library using the same pattern.@vercel/ogadded tooptimizeDeps.exclude(global,rsc, andssrenvironments): prevents Vite's esbuild pre-bundler from caching the module before the transform hook runs. With this in place, the module always flows through our transform and executes inside workerd whereWebAssembly.instantiate()is fully supported — no WASM workarounds needed.vinext:og-assetsbuild plugin: copiesresvg.wasmto the RSC output directory for production builds (the font is now inlined, so only the WASM needs to be present as a file).Tests
app/api/og/route.tsx) in bothexamples/app-router-cloudflareandtests/fixtures/app-basic, accepting a?title=query paramtests/e2e/og-image.spec.ts) with 6 tests:content-type: image/png?title=Hellocustom title worksapp-router,cloudflare-workers, andcloudflare-dev🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.