From 8db8d4325cb744fae70e8fca85d2041aa1c0ad35 Mon Sep 17 00:00:00 2001 From: mushan0x0 Date: Wed, 22 Apr 2026 15:15:53 +0800 Subject: [PATCH] fix: stop bundling @vercel/og when it is unused --- .changeset/drop-unused-vercel-og.md | 9 +++++++++ .../cloudflare/src/cli/build/bundle-server.ts | 18 +++++++++++++----- 2 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 .changeset/drop-unused-vercel-og.md diff --git a/.changeset/drop-unused-vercel-og.md b/.changeset/drop-unused-vercel-og.md new file mode 100644 index 000000000..5fa628dd6 --- /dev/null +++ b/.changeset/drop-unused-vercel-og.md @@ -0,0 +1,9 @@ +--- +"@opennextjs/cloudflare": patch +--- + +Stop bundling `@vercel/og` (and its ~1.4 MiB `resvg.wasm`) when the app does not use it. + +Next.js's `externalImport` helper keeps a dynamic `import("next/dist/compiled/@vercel/og/index.edge.js")` in the emitted handler even for apps that never use `ImageResponse` / `opengraph-image`. Previously this module was marked as `external` when `useOg` was `false`, which left Wrangler to resolve and bundle it — pulling in ~800 KiB of JS plus `resvg.wasm` and pushing many Workers over the Cloudflare free-tier 3 MiB gzip limit. + +When `useOg` is `false`, the edge entry is now aliased to the existing `throw.js` shim, so the unreachable dynamic import resolves to a tiny module and the real `@vercel/og` library is no longer pulled into the Worker bundle. diff --git a/packages/cloudflare/src/cli/build/bundle-server.ts b/packages/cloudflare/src/cli/build/bundle-server.ts index 829357a1f..9e1cad3e5 100644 --- a/packages/cloudflare/src/cli/build/bundle-server.ts +++ b/packages/cloudflare/src/cli/build/bundle-server.ts @@ -113,12 +113,20 @@ export async function bundleServer(buildOpts: BuildOptions, projectOpts: Project // Apply updater updates, must be the last plugin updater.plugin, ] as Plugin[], - external: [ - "./middleware/handler.mjs", - // Do not bundle og when it is not used - ...(useOg ? [] : ["next/dist/compiled/@vercel/og/index.edge.js"]), - ], + external: ["./middleware/handler.mjs"], alias: { + // When @vercel/og is not used, alias the edge entry to a throwing shim so the + // dynamic `import("next/dist/compiled/@vercel/og/index.edge.js")` call site + // emitted by Next.js does not drag the library (~800 KiB) and its + // `resvg.wasm` (~1.4 MiB) into the Worker bundle. + ...(useOg + ? {} + : { + "next/dist/compiled/@vercel/og/index.edge.js": path.join( + buildOpts.outputDir, + "cloudflare-templates/shims/throw.js" + ), + }), // Workers have `fetch` so the `node-fetch` polyfill is not needed "next/dist/compiled/node-fetch": path.join(buildOpts.outputDir, "cloudflare-templates/shims/fetch.js"), // Workers have builtin Web Sockets