添加Vercel OG:带有边缘功能的Astro Project的图像生成
#javascript #edge #vercel

previous blog post中,我提到我正在使用Next.js项目来运行@vercel/og逻辑来生成我的OG:我的博客文章的图像。
现在不再需要这一点,我想出了如何在我的Astro博客项目(此网站; - )中运行此操作。

为此需要进行一些更改。
我的下一个项目中的原始代码看起来像这样:

// /pages/api/og.jsx

import { ImageResponse } from '@vercel/og';

export const config = {
  runtime: 'experimental-edge',
};

const font = fetch(new URL('../../assets/Inter.ttf', import.meta.url)).then(
  res => res.arrayBuffer()
);

export default async function handler(req) {
  const fontData = await font;

  try {
    const { searchParams } = new URL(req.url);

    // ?title=<title>
    const hasTitle = searchParams.has('title');
    const title = hasTitle
      ? searchParams.get('title')?.slice(0, 200)
      : 'My default title';

    return new ImageResponse(
      (
        <div
          style={{
            background: 'white',
            width: '100%',
            height: '100%',
            display: 'flex',
            textAlign: 'center',
            alignItems: 'center',
            justifyContent: 'center',
            flexDirection: 'column',
            fontFamily: 'Inter',
            backgroundImage:
              'radial-gradient(circle at 25px 25px, lightgray 2%, transparent 0%), radial-gradient(circle at 75px 75px, lightgray 2%, transparent 0%)',
            backgroundSize: '100px 100px',
          }}
        >
          <div
            style={{
              width: '80%',
              display: 'flex',
              flexDirection: 'column',
              textAlign: 'center',
              alignItems: 'center',
            }}
          >
            <p style={{ fontSize: 32 }}>Thomas Ledoux&apos;s blog</p>
            <p style={{ fontSize: 64 }}>{title}</p>
          </div>
        </div>
      ),
      {
        width: 1200,
        height: 600,
        fonts: [
          {
            name: 'Inter',
            data: fontData,
            style: 'normal',
          },
        ],
      }
    );
  } catch (e) {
    console.log(`${e.message}`);
    return new Response(`Failed to generate the image`, {
      status: 500,
    });
  }
}

如您所见,JSX代码被用于构建我的OG:Image。
在Next内部的/api文件夹中使用JSX代码在Next.js Projects部署到Vercel。
在部署到Vercel(例如Astro)的其他框架上,这是not possible
尝试此操作时,我会收到以下错误消息:vc-file-system:api/og.js:25:8: ERROR: The JSX syntax extension is not currently enabled

所以我必须在API函数内使用JSX解决方法。
幸运的是,ImageResponse函数还允许使用"React-elements-like" objects
使用上面链接上提供的示例,我在Astro Project内部创建了以下边缘API路由:

// /api/og.js

import { ImageResponse } from '@vercel/og';

export const config = {
  runtime: 'experimental-edge',
};

const font = fetch(new URL('../assets/Inter.ttf', import.meta.url)).then(res =>
  res.arrayBuffer()
);

export default async function handler(req) {
  const fontData = await font;

  try {
    const { searchParams } = new URL(req.url);

    // ?title=<title>
    const hasTitle = searchParams.has('title');
    const title = hasTitle
      ? searchParams.get('title')?.slice(0, 200)
      : 'My default title';

    const html = {
      type: 'div',
      props: {
        children: [
          {
            type: 'div',
            props: {
              style: {
                width: '80%',
                display: 'flex',
                flexDirection: 'column',
                textAlign: 'center',
                alignItems: 'center',
              },
              children: [
                {
                  type: 'p',
                  props: {
                    style: { fontSize: 32 },
                    children: 'Blog by Thomas Ledoux',
                  },
                },
                {
                  type: 'p',
                  props: {
                    style: { fontSize: 64 },
                    children: title,
                  },
                },
              ],
            },
          },
        ],
        style: {
          background: 'white',
          width: '100%',
          height: '100%',
          display: 'flex',
          textAlign: 'center',
          alignItems: 'center',
          justifyContent: 'center',
          flexDirection: 'column',
          fontFamily: 'Inter',
          backgroundImage:
            'radial-gradient(circle at 25px 25px, lightgray 2%, transparent 0%), radial-gradient(circle at 75px 75px, lightgray 2%, transparent 0%)',
          backgroundSize: '100px 100px',
        },
      },
    };

    return new ImageResponse(html, {
      width: 1200,
      height: 600,
      fonts: [
        {
          name: 'Inter',
          data: fontData,
          style: 'normal',
        },
      ],
    });
  } catch (e) {
    console.log(`${e.message}`);
    return new Response(`Failed to generate the image`, {
      status: 500,
    });
  }
}

现在,我希望API路线被Vercel捡起。
默认情况下,Astro Build命令将不会在根目录中选择这些API路由(因为它们是(vercel build命令)[https://github.com/withastro/astro/issues/5451#issuecomment-1339720682])的一部分。
因此,为了在用例中使用此功能,我切换到使用(vercel cli)[https://vercel.com/docs/cli]来构建和部署我的项目。
使用npm i -g vercel全球安装CLI后,我可以运行vercel build在本地构建我的项目,然后运行vercel deploy --prebuilt以直接部署本地创建的构建构建。

我还选择禁用推送到我的git存储库的自动部署,因为我现在通过CLI进行部署。
禁用自动部署是通过在根目录中添加vercel.json文件完成的,其中包含以下内容:

{
  "git": {
    "deploymentEnabled": false
  }
}

希望这可以帮助其他想要在其Astro项目中使用无服务器/边缘API功能的人。
可以找到源代码here