Добавляем sitemap.xml в Next.js приложение
9 мин.

Добавляем sitemap.xml в Next.js приложение

Важным элементом SEO-оптимизации является наличие файла sitemap.xml. В этой статье вы узнаете, что такое sitemap.xml и как добавить его в свое приложение на Next.js.

Что такое sitemap.xml?

Sitemap.xml - это файл формата Sitemaps XML format, который сообщает поисковым системам (например Google или Yandex), какие страницы есть на вашем сайте и как часто они обновляются.

Этот файл должен находиться в корневой папке вашего сайта, и обычно доступен по адресу:

домен.зона/sitemap.xml

Например, sitemap.xml этого блога лежит по адресу https://alexeybaranov.dev/sitemap.xml и выглядит следующим образом:

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://alexeybaranov.dev/</loc>
    <lastmod>2025-03-13T12:07:00.337Z</lastmod>
    <changefreq>daily</changefreq>
    <priority>0.7</priority>
  </url>
  ...
</urlset>

Более подробную информацию о том как как поисковые системы обрабатывают файлы sitemap.xml можно найти в справке от Яндекса или документации Google.

Первый способ: Добавляем статический файл

Первый способ - очень простой. Next.js из коробки умеет отдавать статические файлы, например изображения, добавленные в папку public в корне проекта.

Этот же подход можно использовать для добавления файла sitemap.xml. Всё что необходимо сделать - добавить файл в папку public.

Подробнее про работу со статикой и папку public можно почитать в официальной документации Next.js.

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

Альтернативный способ добавления статического файла

Начиная с версии 13.3 Next.js умеет корректно обрабатывать статический файл sitemap.xml лежащий в корне папки app.

Подробнее в документации.

Второй способ: Динамическая генерация sitemap.xml

Для того чтобы динамически создавать файл sitemap.xml необходимо в папку app добавить файл robots.js или robots.ts, который будет возвращать объект типа MetadataRoute.Sitemap.

import { MetadataRoute } from "next";

import { URL_BASE } from "@/lib/constants";

export default function sitemap(): MetadataRoute.Sitemap {
  return [
    {
      url: `${URL_BASE}/`,
      lastModified: new Date(),
      changeFrequency: "daily",
      priority: 0.7,
    },
    {
      url: `${URL_BASE}/about/`,
      lastModified: new Date(),
      changeFrequency: "daily",
      priority: 0.7,
    },
    {
      url: `${URL_BASE}/posts/`,
      lastModified: new Date(),
      changeFrequency: "daily",
      priority: 0.7,
    },
  ];
}

Данный код сгенерирует файл со следующим содержимым:

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://alexeybaranov.dev/</loc>
    <lastmod>2025-03-13T12:07:00.337Z</lastmod>
    <changefreq>daily</changefreq>
    <priority>0.7</priority>
  </url>
  <url>
    <loc>https://alexeybaranov.dev/about/</loc>
    <lastmod>2025-03-13T12:07:00.337Z</lastmod>
    <changefreq>daily</changefreq>
    <priority>0.7</priority>
    </url>
  <url>
    <loc>https://alexeybaranov.dev/posts/</loc>
    <lastmod>2025-03-13T12:07:00.337Z</lastmod>
    <changefreq>daily</changefreq>
    <priority>0.7</priority>
  </url>
</urlset>

Генерация Image Sitemaps

Так же, начиная с 15 версии в Next.js есть встроенная возможность генерировать Image Sitemaps. Для этого надо всего лишь добавить свойство images (см. спецификацию) к странице.

import { MetadataRoute } from "next";

import { URL_BASE } from "@/lib/constants";

export default function sitemap(): MetadataRoute.Sitemap {
  return [
    {
      url: `${URL_BASE}/`,
      lastModified: new Date(),
      changeFrequency: "daily",
      priority: 0.7,
      images: ["https://alexeybaranov.dev/assets/blog/authors/avatar.webp"],
    },
  ];
}

В результате получим следующий файл:

<urlset
  xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
  xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"
>
  <url>
    <loc>https://alexeybaranov.dev/</loc>
    <image:image>
      <image:loc>https://alexeybaranov.dev/assets/blog/authors/avatar.webp</image:loc>
    </image:image>
    <lastmod>2025-03-13T12:07:00.337Z</lastmod>
    <changefreq>daily</changefreq>
    <priority>0.7</priority>
  </url>
</urlset>

Генерация Video Sitemaps

Так же, начиная с 15 версии в Next.js есть встроенная возможность генерировать Video Sitemaps. Для этого надо всего лишь добавить свойство videos (см. спецификацию) к странице.

import { MetadataRoute } from "next";

import { URL_BASE } from "@/lib/constants";

export default function sitemap(): MetadataRoute.Sitemap {
  return [
    {
      url: `${URL_BASE}/posts/yandex-gpt-intro/`,
      lastModified: new Date(),
      changeFrequency: "daily",
      priority: 0.7,
      videos: [
        {
          title: "Название видео",
          thumbnail_loc:
            "https://alexeybaranov.dev/assets/blog/yandex-gpt-intro/cover.webp",
          description: "Это описание видео",
        },
      ],
    },
  ];
}

В результате получим следующий файл:

<urlset
  xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
  xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"
>
  <url>
    <loc>https://alexeybaranov.dev/posts/yandex-gpt-intro/</loc>
    <video:video>
      <video:title>Название видео</video:title>
      <video:thumbnail_loc>https://alexeybaranov.dev/assets/blog/yandex-gpt-intro/cover.webp</video:thumbnail_loc>
      <video:description>Это описание видео</video:description>
    </video:video>
    <lastmod>2025-03-13T12:07:00.337Z</lastmod>
    <changefreq>daily</changefreq>
    <priority>0.7</priority>
  </url>
</urlset>

Генерация локализованных Sitemaps

В Next.js есть встроенная возможность добавлять ссылки на версии страниц на другом языке при генерации sitemap.xml. Для этого надо всего лишь добавить свойство alternates (см. спецификацию) к странице.

import { MetadataRoute } from "next";

import { URL_BASE } from "@/lib/constants";

export default function sitemap(): MetadataRoute.Sitemap {
  return [
    {
      url: `${URL_BASE}/`,
      lastModified: new Date(),
      changeFrequency: "daily",
      priority: 0.7,
      alternates: {
        languages: {
          en: `${URL_BASE}/en/`,
          fr: `${URL_BASE}/fr/`,
        },
      },
    },
  ];
}

В результате получим следующий файл:

<urlset
  xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
  xmlns:xhtml="http://www.w3.org/1999/xhtml"
>
  <url>
    <loc>https://alexeybaranov.dev/</loc>
    <xhtml:link
      rel="alternate"
      hreflang="en"
      href="https://alexeybaranov.dev/en/"/>
    <xhtml:link
      rel="alternate"
      hreflang="fr"
      href="https://alexeybaranov.dev/fr/"/>
    <lastmod>2025-03-13T12:07:00.337Z</lastmod>
    <changefreq>daily</changefreq>
    <priority>0.7</priority>
  </url>
</urlset>

Спецификация MetadataRoute.Sitemap

Вот полная спецификация MetadataRoute.Sitemap, взятая из официального репозитория на Github.

type Sitemap = Array<{
  url: string;
  lastModified?: string | Date | undefined;
  changeFrequency?:
    | "always"
    | "hourly"
    | "daily"
    | "weekly"
    | "monthly"
    | "yearly"
    | "never"
    | undefined;
  priority?: number | undefined;
  alternates?:
    | {
        languages?: Languages<string> | undefined;
      }
    | undefined;
  images?: string[] | undefined;
  videos?: Videos[] | undefined;
}>;

export type Videos = {
  title: string;
  thumbnail_loc: string;
  description: string;
  content_loc?: string | undefined;
  player_loc?: string | undefined;
  duration?: number | undefined;
  expiration_date?: Date | string | undefined;
  rating?: number | undefined;
  view_count?: number | undefined;
  publication_date?: Date | string | undefined;
  family_friendly?: "yes" | "no" | undefined;
  restriction?: Restriction | undefined;
  platform?: Restriction | undefined;
  requires_subscription?: "yes" | "no" | undefined;
  uploader?:
    | {
        info?: string | undefined;
        content?: string | undefined;
      }
    | undefined;
  live?: "yes" | "no" | undefined;
  tag?: string | undefined;
};

Альтернативные решения

Так же есть несколько альтернативных решений для генерации sitemap.xml в виде npm-пакетов. Например пакет next-sitemap.

Бонус: Валидация sitemap.xml

Для того чтобы удостовериться что содержимое sitemap.xml валидно и будет работать как и задумано, можно воспользоваться несколькими бесплатными инструментами:

На этом всё! 🎉

Подписывайтесь на мой Youtube канал, Telegram и на сообщество Вконтакте 🙂

Поделиться

Поддержать автора

Вам может быть интересно:

Добавляем robots.txt в Next.js приложение

Добавляем robots.txt в Next.js приложение

5 мин.

Инструкция по добавлению robots.txt в Next.js приложение...

Подключение счётчика Яндекс Метрики к Next.js приложению

Подключение счётчика Яндекс Метрики к Next.js приложению

5 мин.

Рассказ о том как я счётчик Яндекс Метрики к блогу подключал...