概述
在提供多语言博客文章后,当更改语言时,文本会发生变化,但缩略图不会,因此,当内容是英文而图片是韩文时,看起来很别扭。因此,我需要动态生成图片,于是我研究并找到了 vercel 提供的一个库。
在 Next.js 中设置动态 OG 图像
通过 Vercel 的@vercel/og
库,Next.js 支持动态生成 OG 图像。该功能通过Vercel 函数进行计算和执行。
安装
- 应用程序路由器项目:无需安装其他软件包(内置)
import { ImageResponse } from "next/og"
- 页面路由器项目:
npm i @vercel/og
使用命令安装import { ImageResponse } from "@vercel/og
基本用法
造型
像创建组件一样创建组件。这是一个 API,因为它是使用 JSX 语法创建的,但你需要创建一个文件扩展名为jsx
或tsx
的文件。
您可以像下面这样直接插入样式来创建、
return new ImageResponse(
<div
style={{
height: '100%',
width: '100%',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fff',
fontSize: 32,
fontWeight: 600,
}}
>
<div style={{ marginTop: 40 }}>Hello, World</div>
</div>
)
tw
道具来应用 tailwindCSS 语法。
return new ImageResponse(
<div
tw="h-full w-full flex flex-col items-center justify-center bg-white text-xl font-bold"
>
<div tw="mt-10">Hello, World</div>
</div>
)
页路由器项目
/pages/api/og.tsx
路径,并编写以下内容
import { NextRequest } from "next/server";
import { ImageResponse } from "@vercel/og";
export const config = {
runtime: "edge",
};
export default async function handler(request: NextRequest) {
const { searchParams } = request.nextUrl;
const title = searchParams.get("title");
return new ImageResponse(
(
<div tw="flex flex-col w-full h-full items-center justify-center bg-white">
<div tw="bg-gray-50 flex w-full">
<div tw="flex flex-col md:flex-row w-full py-12 px-4 md:items-center justify-between p-8">
<h2 tw="flex flex-col text-3xl sm:text-4xl font-bold tracking-tight text-gray-900 text-left">
{title}
</h2>
<div tw="mt-8 flex md:mt-0">
<div tw="flex rounded-md shadow">
<a tw="flex items-center justify-center rounded-md border border-transparent bg-indigo-600 px-5 py-3 text-base font-medium text-white">
시작하기
</a>
</div>
<div tw="ml-3 flex rounded-md shadow">
<a tw="flex items-center justify-center rounded-md border border-transparent bg-white px-5 py-3 text-base font-medium text-indigo-600">
더 알아보기
</a>
</div>
</div>
</div>
</div>
</div>
),
{
width: 1200,
height: 630,
},
);
}
由于 Pages Routrer 不支持 Node.js 运行时,因此必须额外应用以下设置,以便 Vercel 函数在 Edge 运行时中运行。
export const config = {
runtime: "edge",
};
应用路由器项目
/app/api/og/route.tsx
文件,并写入以下内容Pages 路由器和 App 路由器的唯一区别在于路径和编写方式,但返回的值是相同的。
export async function GET(request: NextRequest) {
const { searchParams } = request.nextUrl;
const title = searchParams.get("title");
// 이하 생략...
}
正如您在代码中看到的,您可以通过searchParams
动态获取和显示值。
const title = searchParams.get("title");
因此,当您调用以下应用程序接口时,您将在浏览器中看到以下内容/api/og?title=WOW
添加自定义字体
为了让外观更 OG,我们来添加自定义字体。鉴于字体文件位于/public/fonts/
下,我们可以这样写
import { NextRequest } from "next/server";
import { ImageResponse } from "next/og";
import { join } from "path";
import { readFileSync } from "fs";
export async function GET(request: NextRequest) {
// 생략...
const fontPath = join(process.cwd(), "public", "fonts", "WONTitle.ttf");
const fontData = readFileSync(fontPath);
return new ImageResponse(
(
<div>
// 생략...
</div>
),
{
width: 1200,
height: 630,
fonts: [
{
name: "WONTitle",
data: fontData,
},
],
},
);
}
添加图片
你也可以通过导入图片来添加图片。如果存在外部 URL,可以直接输入;如果有本地可用的图片,可以像下面这样使用它
const logoPath = join(
process.cwd(),
"public",
"images",
"logo",
`${logo}.png`,
);
const logoBuffer = readFileSync(logoPath);
const logoBase64 = `data:image/png;base64,${logoBuffer.toString("base64")}`;
// ... 생략
return new ImageResponse((
<img
alt="og thumbnail"
tw="absolute -translate-x-1/2 -translate-y-1/2 "
src={logoBase64}
width={logoWidth}
height={logoHeight}
style={{
opacity: 0.6,
}}
/>), ...)
结果
我们现在可以动态生成样式相同但不同语言文本不同的缩略图。以前我每次都要进入图片编辑器创建缩略图,现在我想我再也不用这样做了。
🔎参见