DevGang
Авторизоваться

Генерация динамических открытых графиков и изображений Twitter в Next.js

Живая демо-версия / Скачать

Привет, читатели блога dev-gang! В этой статье мы увидим, как создавать динамические изображения Open Graph и Twitter с помощью Next.js. Этот метод позволяет нам создавать персонализированные предварительные просмотры наших статей при их публикации в социальных сетях, что повышает взаимодействие с вашей аудиторией.

Динамические изображения будут включать в себя заранее подготовленный фон и текст, соответствующий заголовку страницы. Кроме того, мы добавим информацию об авторе страницы, как показано на изображении предварительного просмотра выше.

Что делает этот подход интригующим, так это его способность генерировать изображения «на лету» при каждом совместном использовании страницы. Это означает, что мы можем предложить индивидуальный предварительный просмотр для каждой статьи без необходимости создавать отдельные изображения для каждой.

Это стало возможным благодаря функции динамического создания изображений Open Graph, представленной в Next.js версии 13.3, и новому API метаданных. Вкратце, он включает в себя генерацию изображений с использованием кода (в нашем случае TSX, HTML и CSS) с помощью библиотек @vercel/og (уже интегрированных в маршрутизатор приложений) и Satori. Сатори преобразует HTML и CSS в SVG, а затем resvg-js преобразует SVG в изображение PNG. Все это всего за несколько миллисекунд!

Давайте начнем!

Создание новой страницы в вашем приложении Next.js

Поскольку мы используем маршрутизатор приложений, вам нужно всего лишь создать новую папку в каталоге app и дать ей имя, соответствующее желаемому пути к странице. Например, давайте рассмотрим app/social-preview. В этой папке создайте новый файл с именем page.tsx и включите следующий код:

 export const metadata = {
    title: 'Social Metadata - Cruip Tutorials',
    description:
      "A guide on how to optimize SEO with static and dynamic metatags using Next.js 13's new Metadata API.",
  }

  import Banner from '@/components/banner'

  export default function SocialPreviewPage() {
    return (
      <>
        <main className="relative min-h-screen flex flex-col justify-center bg-slate-900 overflow-hidden">
          <div className="w-full max-w-6xl mx-auto px-4 md:px-6 py-24">
            <div className="text-center">

              <div className="font-extrabold text-3xl md:text-4xl [text-wrap:balance] bg-clip-text text-transparent bg-gradient-to-r from-slate-200/60 to-50% to-slate-200">Generate Dynamic Open Graph and Twitter Images in Next.js</div>
              <p className="text-lg text-slate-500 mt-4">Share this page on Facebook and Twitter to see the preview image</p>

            </div>
          </div>
        </main>

      </>
    )
  }

На данный момент мы сосредоточены на настройке заголовка; содержание страницы не имеет решающего значения на данном этапе. Цель состоит в том, чтобы понять концепцию динамического создания изображений.

Генерация динамического текста

Прежде чем расширять объект metadata, мы создадим маршрут API, который будет служить конечной точкой для динамической генерации текста. Создайте папку с именем og внутри каталога API. Внутри него создайте файл с именем Route.tsx и добавьте этот код:

import { ImageResponse } from 'next/server'

  export const runtime = 'edge'

  export async function GET(request: Request) {
    const interExtrabold = fetch(
      new URL('../../../public/Inter-ExtraBold.ttf', import.meta.url)
    ).then((res) => res.arrayBuffer())

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

      const hasTitle = searchParams.has('title')
      const title = hasTitle
        ? searchParams.get('title')?.slice(0, 100)
        : 'Default title'

      return new ImageResponse(
        (
          <div
            style={{
              backgroundImage: 'url(https://cruip-tutorials-next.vercel.app/social-card-bg.jpg)',
              backgroundSize: '100% 100%',
              height: '100%',
              width: '100%',
              display: 'flex',
              flexDirection: 'column',
              alignItems: 'flex-start',
              justifyContent: 'center',
              fontFamily: 'Inter',
              padding: '40px 80px',
            }}
          >
            <div
              style={{
                fontSize: 60,
                fontWeight: 800,
                letterSpacing: '-0.025em',
                lineHeight: 1,
                color: 'white',
                marginBottom: 24,
                whiteSpace: 'pre-wrap',
              }}
            >
              {title}
            </div>
            <img
              width="203"
              height="44"
              src={`https://cruip-tutorials-next.vercel.app/author.png`}
            />
          </div>
        ),
        {
          width: 1200,
          height: 630,
          fonts: [
            {
              name: 'Inter',
              data: await interExtrabold,
              style: 'normal',
              weight: 800,
            },
          ],        
        },
      )
    } catch (e: any) {
      console.log(`${e.message}`)
      return new Response(`Failed to generate the image`, {
        status: 500,
      })
    }
  }

Этот код создает функцию GET, которая возвращает объект ImageResponse. Конструктор ImageResponse генерирует динамическое изображение из JSX и CSS. Изображение будет состоять из фонового изображения, заголовка и изображения, содержащего информацию об авторе.

Шаги следующие:

  • Включение собственного шрифта (Inter Extrabold) из общедоступного каталога.
  • Определение константы title для хранения заголовка страницы. Если в URL-адресе существует параметр title, он используется; в противном случае по умолчанию используется «default title».
  • Проектируем структуру с помощью CSS в соответствии с рекомендациями Сатори.
  • Указание размера изображения 1200x630 пикселей.
  • Добавление Inter Extrabold в массив шрифтов.

Вызов обработчика маршрута в page.tsx запустит генерацию динамического изображения.

Определение полей OpenGraph и Twitter

Теперь мы можем расширить объект метаданных, добавив поля openGraph и twitter. Эти поля содержат метаданные, специально предназначенные для платформ социальных сетей.

Сначала настройте метаданные для Open Graph:

  openGraph: {
    title: "Generate Dynamic Open Graph and Twitter Images in Next.js",
    description:
      "A guide on how to optimize SEO with static and dynamic metatags using Next.js 13's new Metadata API.",
    type: "article",
    url: "https://cruip-tutorials-next.vercel.app/social-preview",
    images: [
      {
        url: "https://cruip-tutorials-next.vercel.app/api/og?title=Generate Dynamic Open Graph and Twitter Images in Next.js",
      },
    ],
  }

Далее мы продолжим работу с метаданными для Twitter Card:

  twitter: {
    card: "summary_large_image",
    title: "Generate Dynamic Open Graph and Twitter Images in Next.js",
    description:
      "A guide on how to optimize SEO with static and dynamic metatags using Next.js 13's new Metadata API.",
    images: [
      "https://cruip-tutorials-next.vercel.app/api/og?title=Generate Dynamic Open Graph and Twitter Images in Next.js",
    ],
  }

Обратите внимание, как мы вызываем конечную точку /api/og для запуска генерации динамического изображения. В этом случае мы передаем заголовок страницы в качестве параметра, но мы можем передать любой параметр, который захотим.

Объект метаданных будет выглядеть следующим образом:

export const metadata = {
    title: 'Social Metadata - Cruip Tutorials',
    description:
      "A guide on how to optimize SEO with static and dynamic metatags using Next.js 13's new Metadata API.",
    openGraph: {
      title: "Generate Dynamic Open Graph and Twitter Images in Next.js",
      description:
        "A guide on how to optimize SEO with static and dynamic metatags using Next.js 13's new Metadata API.",
      type: "article",
      url: "https://cruip-tutorials-next.vercel.app/social-preview",
      images: [
        {
          url: "https://cruip-tutorials-next.vercel.app/api/og?title=Generate Dynamic Open Graph and Twitter Images in Next.js",
        },
      ],
    },
    twitter: {
      card: "summary_large_image",
      title: "Generate Dynamic Open Graph and Twitter Images in Next.js",
      description:
        "A guide on how to optimize SEO with static and dynamic metatags using Next.js 13's new Metadata API.",
      images: [
        "https://cruip-tutorials-next.vercel.app/api/og?title=Generate Dynamic Open Graph and Twitter Images in Next.js",
      ],
    },
  }

И вот конечный результат:

Просто поделитесь ссылкой на страницу в Twitter или Facebook, чтобы увидеть предварительный просмотр в действии!

Стилизация содержимого изображения с помощью Tailwind CSS

Хотя Satori все еще является экспериментальной функцией, для стилизации содержимого изображения можно использовать CSS-классы Tailwind. Мы большие поклонники фреймворков Css, о чем свидетельствуют наши шаблоны Tailwind, поэтому нам пришлось попробовать!

Satori позволяет нам определять CSS-классы Tailwind в двух выделенных атрибутах. Следовательно, мы можем добиться того же результата, используя следующий код:

import { ImageResponse } from 'next/server'

  export const runtime = 'edge'

  export async function GET(request: Request) {
    const interExtrabold = fetch(
      new URL('../../../public/Inter-ExtraBold.ttf', import.meta.url)
    ).then((res) => res.arrayBuffer())

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

      const hasTitle = searchParams.has('title')
      const title = hasTitle
        ? searchParams.get('title')?.slice(0, 100)
        : 'Default title'

      return new ImageResponse(
        (
          <div
            tw="h-full w-full flex flex-col align-start justify-center py-10 px-20"
            style={{
              backgroundImage: 'url(https://cruip-tutorials-next.vercel.app/social-card-bg.jpg)',
              backgroundSize: '100% 100%',
              fontFamily: 'Inter',
            }}
          >
            <div
              tw="text-6xl font-extrabold text-white tracking-tight leading-none mb-6 whitespace-pre-wrap"
            >
              {title}
            </div>
            <img
              width="203"
              height="44"
              src={`https://cruip-tutorials-next.vercel.app/author.png`}
            />
          </div>
        ),
        {
          width: 1200,
          height: 630,
          fonts: [
            {
              name: 'Inter',
              data: await interExtrabold,
              style: 'normal',
              weight: 800,
            },
          ],        
        },
      )
    } catch (e: any) {
      console.log(`${e.message}`)
      return new Response(`Failed to generate the image`, {
        status: 500,
      })
    }
  }

Источник:

#NestJS
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу