* test: add static export E2E tests (#564)
Add Playwright E2E tests for `output: "export"` static builds covering
both App Router and Pages Router. Includes a lightweight static file
server with path traversal protection, proper error handling, and
startup validation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Update tests/e2e/static-export/serve-static.mjs
Co-authored-by: ask-bonk[bot] <249159057+ask-bonk[bot]@users.noreply.github.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: ask-bonk[bot] <249159057+ask-bonk[bot]@users.noreply.github.com>
* chore: migrate to vite plus
* Disable typeAware and typeCheck
* Update CI
* Fix CI
* Fix test
* Clean
* Run test with vp
* Try revert
* react: false In test
* Fix test
* Revert "Try revert"
This reverts commit 009da10473.
* Update
* Update
* Try revert ci changes
* revert
* Run vp migrate
* Disable typeAware and typeCheck for now
* Better resolve for test
* Use vp dev instead of vite
* Update expect
* Fix NormalizeManifestModuleId
* Try increase timeout
* Update to use vp
* Try new check
* Bring back npx vp
* Migrate CI
* Make next-intl resolvable
* Update
* Update
* Update
* add oxfmt formatter: config, scripts, CI, editor setup, docs
* rebuild lockfile
* fix: add Format to required checks list, remove dead ignore pattern
* run fmt
* add format to agents.md again
* feat(og): add @next/og support with Cloudflare Workers compatibility
- Add vinext:og-font-fix transform plugin that patches @vercel/og/dist/index.edge.js
at Vite transform time: inlines the fallback font as base64 (avoids fetch() with
import.meta.url which breaks in workerd) and defers WASM init to first use (avoids
WebAssembly.instantiate() being blocked in Node.js module runner)
- Add @vercel/og to optimizeDeps.exclude so Vite's esbuild pre-bundler doesn't cache
the module before the transform hook runs
- Add vinext:og-assets build plugin that copies font/WASM assets to RSC output dir
- Add /app/api/og route to app-router-cloudflare example and app-basic fixture
- Add shared Playwright e2e spec (tests/e2e/og-image.spec.ts) asserting PNG validity,
correct 1200x630 dimensions, param-driven content, and determinism
- Register og-image.spec.ts in app-router, cloudflare-workers, and cloudflare-dev
Playwright projects (18 tests total, all passing)
* refactor(og): generalize fetch+import.meta.url asset inlining, drop WASM lazy-init patch
Replace the @vercel/og-specific vinext:og-font-fix plugin with a general
vinext:og-inline-fetch-assets plugin that:
- Matches ANY fetch(new URL('./asset', import.meta.url)).then(res => res.arrayBuffer())
pattern, not just the hardcoded noto-sans filename
- Resolves each asset relative to the module's on-disk path (via the transform id)
and inlines it as base64 — works for any font version or additional assets
- Applies to any library using this pattern, not just @vercel/og
Also removes the WASM lazy-init patch: now that @vercel/og is in optimizeDeps.exclude,
the module runs through workerd (not the Node.js pre-bundler cache) where
WebAssembly.instantiate() works fine. The lazy-init workaround was only needed
when the pre-bundler cache bypassed the transform hook.
The og-assets build plugin is updated to only copy resvg.wasm (not the font,
which is now inlined and will no longer appear in the bundle by filename).
* fix(og): inline readFileSync assets from @vercel/og node build
The production RSC bundle resolves @vercel/og under the 'import' export
condition, getting dist/index.node.js instead of dist/index.edge.js.
The node build loads font and WASM via fs.readFileSync(fileURLToPath(
new URL('./file', import.meta.url))), which breaks after bundling because
import.meta.url points to the bundle output file, not the dist/ dir.
Extend vinext:og-inline-fetch-assets with a second regex pattern that
matches readFileSync(fileURLToPath(new URL(...))) and replaces it with
Buffer.from('<base64>', 'base64'), inlining both noto-sans font and
resvg.wasm at transform time. This eliminates the ENOENT errors seen
in the production build CI tests.
* refactor(og): address code review feedback
- Remove Fix 1 (font inlining) from vinext:og-font-patch — it was dead
code since vinext:og-inline-fetch-assets (earlier in the plugin array)
already handles the same fetch(new URL(...)) pattern generically. Only
Fix 2 (yoga WASM extraction) remains in og-font-patch.
- Use split().join() instead of String.replace() in both Pattern 1 and
Pattern 2 loops of og-inline-fetch-assets. String.replace(string, ...)
only replaces the first occurrence; split().join() replaces all of them,
which matters for libraries that may use the same pattern multiple times.
* refactor(og): use replaceAll instead of split().join()