在 Node 之外使用 OG Image
发布: (2025年11月30日 GMT+8 07:38)
3 min read
原文: Dev.to
Source: Dev.to
TL;DR
演示和源码,展示如何在 Next.js、SvelteKit、Nuxt 和 AnalogJS 中让 og/image 在各种 Edge 环境下工作。
Serverless Functions
如果部署到普通的 Serverless 函数(Node.js),这些包可以直接使用:
| 框架 | 包 |
|---|---|
| Next.js | next/og 或 vercel/og |
| AnalogJS | @analogjs/content/og |
| SvelteKit | @ethercorps/sveltekit-og(可以传入 Svelte 组件) |
| Qwik | og-img |
| SolidStart | og-img |
| Astro | og-img(另见 Astro Images) |
| Nuxt | nuxt-og-image(预定义图片,无法自定义) |
| Cloudflare Workers | workers-og(无框架) |
Next.js & Vercel Edge
@vercel/og 为 Next.js 构建,可直接使用。对 pages 目录使用 vercel/og,对 app 目录的 API 端点使用 next/og。
// app/api/og/route.ts
import { ImageResponse } from 'next/og';
export const runtime = 'edge';
export async function GET() {
try {
return new ImageResponse(
(
<div
style={{
height: '100%',
width: '100%',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'white',
padding: '40px',
}}
>
<div
style={{
fontSize: 60,
fontWeight: 'bold',
color: 'black',
textAlign: 'center',
}}
>
Welcome to My Site
</div>
<div
style={{
fontSize: 30,
color: '#666',
marginTop: '20px',
}}
>
Generated with Next.js ImageResponse
</div>
</div>
),
{
width: 1200,
height: 630,
}
);
} catch (e) {
console.error((e as Error).message);
return new Response('Failed to generate the image', { status: 500 });
}
}
- Repo: https://github.com/jdgamble555/nextjs-wasm-test
- Demo: https://nextjs-wasm-test-six.vercel.app/
Next.js & Cloudflare
通过 OpenNext 将 Next.js 部署到 Cloudflare Workers。相同的 next/og API 仍可使用,并且可以通过 tw 属性使用 Tailwind 类。
// src/app/api/og/route.ts
import { ImageResponse } from 'next/og';
export async function GET() {
return new ImageResponse(
<div tw="flex h-full w-full flex-col items-center justify-center bg-white p-10">
<div tw="text-center text-[60px] font-bold text-black">
Welcome to My Site
</div>
<div tw="mt-5 text-[30px] text-gray-600">
Generated with Next.js ImageResponse and deployed to Cloudflare
</div>
</div>
);
}
- Repo: https://github.com/jdgamble555/next-cloudflare-og
- Demo: https://next-cloudflare-og.jdgamble555.workers.dev/
SvelteKit & Vercel Edge
社区维护的包装器让你可以使用 Svelte 组件 通过 @cf-wasm/og(内部实现)生成 OG 图片。
1. image-card.svelte
<script lang="ts">
const { title, website }: { title?: string; website?: string } = $props();
</script>
<div class="bg-slate-50 text-slate-700 w-full h-full flex items-center justify-center p-6">
<div class="m-1.5 p-6 w-full h-full rounded-3xl text-[72px] flex flex-col border-2 border-slate-700">
{title?.slice(0, 80) || "Default Title"}
<hr class="border border-slate-700 w-full" />
<p class="text-[52px] font-bold flex justify-center">
{website || "Default Website"}
</p>
</div>
</div>
2. image-response.ts
// src/lib/image-response.ts
import type { Component } from 'svelte';
import { render } from 'svelte/server';
import { ImageResponse as OGImageResponse } from '@cf-wasm/og';
import { html } from 'satori-html';
export const prerender = false;
export const ImageResponse = async <T extends Record<string, unknown>>(
component: Component<T>,
options?: ConstructorParameters<typeof OGImageResponse>[1],
props?: T
) => {
const result = render(component, { props });
return await OGImageResponse.async(html(result.body), options);
};
3. Edge route (/og/+server.ts)
// src/routes/og/+server.ts
import type { RequestHandler } from '@sveltejs/kit';
import { ImageResponse } from '$lib/image-response';
import ImageCard from '$lib/image-card.svelte';
export const prerender = false;
export const GET = (async ({ url }) => {
const { width, height } = Object.fromEntries(url.searchParams);
return await ImageResponse(
ImageCard,
{
width: Number(width) || 1600,
height: Number(height) || 900,
},
{
title: 'Custom OG Image',
website: 'Generated with Svelte, Vercel, and Cloudflare WASM!',
}
);
}) satisfies RequestHandler;
- Demo: https://svelte-vercel-wasm.vercel.app/
- Repo: https://github.com/jdgamble555/svelte-vercel-wasm
注意:
@ethercorps/sveltekit-og也可以在 Edge 上使用,但其打包体积目前较大。