Как создать sitemap для Astro сайта

Правильная карта сайта (sitemap.xml) для Astro сайтов, как создать и обновлять для быстрой индексации.

XML-карта сайта остаётся одним из базовых инструментов технической SEO-оптимизации. Для проектов на Astro, где сборка отдаёт готовый HTML, доступно несколько способов сформировать sitemap. Разберём официальную интеграцию @astrojs/sitemap, ручной подход и специфику работы с Content Collections. Рассмотрим настройку, фильтрацию, разбивку на файлы и мониторинг индексации по состоянию на 2026 год.

Официальная интеграция @astrojs/sitemap

Astro предлагает встроенную интеграцию @astrojs/sitemap, которая добавляет генерацию карты сайта при каждом выполнении команды astro build. Пакет работает в режимах static и hybrid. В режиме server (SSR) динамическая генерация sitemap на лету не предусмотрена — потребуется ручная реализация эндпоинта.

Установка интеграции выполняется одной командой:

npx astro add sitemap

Эта инструкция загружает пакет и автоматически прописывает интеграцию в astro.config.mjs. Файл конфигурации после добавления выглядит примерно так:

import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';

export default defineConfig({
  site: 'https://example.com',
  integrations: [sitemap()]
});

Поле site обязательно. Если URL сайта не указан, интеграция выдаст предупреждение при сборке и сгенерирует sitemap с пустыми путями. После запуска astro build в директории dist (или в кастомной out-директории) появляется файл sitemap-index.xml и, при необходимости, дополнительные файлы sitemap-0.xml, если включено разбиение. Главный файл содержит ссылку на индекс или сразу перечисляет все страницы, если их менее 1000.

Интеграция автоматически исключает страницы с кодом ответа 404 и маршруты, помеченные как noindex в frontmatter. Также не попадают в sitemap динамические API-эндпоинты и маршруты, определённые без генерируемого HTML.

На проекте интернет-магазина с 500 товаров мы использовали только базовую настройку — после установки sitemap содержал все продуктовые страницы и категории. Это заняло 10 минут от установки до появления файла в dist.

Конфигурация sitemap в Astro

Метод sitemap() принимает объект опций, который управляет фильтрацией, кастомизацией полей, разбиением и приоритетами. Полный набор параметров на 2026 год включает:

ПараметрТипОписание
filterFunctionКолбэк для исключения страниц по URL или данным
serializeFunctionДобавление или изменение полей каждой записи
entryLimitNumberКоличество URL в одном файле (по умолчанию 1000)
customPagesArray<string>Явное указание дополнительных страниц
changefreqStringГлобальная частота изменения (если не задана в serialize)
priorityNumberГлобальный приоритет
lastmodDateГлобальная дата последнего изменения
i18nObjectНастройки локализации для hreflang
xhtmlBooleanДобавление ссылок на XHTML-версию (редко используется)

Далее разберём ключевые параметры подробно.

Фильтрация страниц

По умолчанию в sitemap включаются все HTML-страницы, которые Astro генерирует при сборке. Но часто требуется исключить служебные маршруты — страницы пагинации, личные кабинеты, административные разделы. Для этого используется колбэк filter.

sitemap({
  filter: (page) => !page.includes('/admin') && !page.includes('/account')
})

Аргумент page — это строка URL относительно корня сайта, например, /blog/post-1. Фильтр возвращает true для страниц, которые нужно включить. Можно также исключать страницы на основе frontmatter-полей, но для этого чаще используют другой подход — задают свойство noindex в frontmatter, и страница автоматически исключается.

В реальной практике на корпоративном сайте мы исключали страницы с результатами поиска по фильтру /search и все URL с параметрами запроса. Сами параметры Astro в sitemap не добавляет, но если динамические маршруты генерируют множество страниц, лучше прописать явный фильтр.

Кастомизация записей

Каждая запись в sitemap-файле содержит обязательный тег <loc>. Чтобы добавить <lastmod>, <changefreq> или <priority>, используется колбэк serialize. Он вызывается для каждого URL и возвращает объект с полями, которые попадут в XML.

sitemap({
  serialize: (item) => {
    // item.url — абсолютный URL страницы
    // item.lastmod — дата из Content Collections, если доступна
    return {
      url: item.url,
      lastmod: item.lastmod || new Date(),
      changefreq: 'weekly',
      priority: item.url === 'https://example.com/' ? 1.0 : 0.7,
    };
  }
})

Поля, доступные в аргументе item, зависят от источника маршрута. Если страница связана с Content Collection, то item содержит свойство lastmod, вычисленное из поля updatedDate или pubDate коллекции. Для статических страниц без коллекций lastmod будет отсутствовать, поэтому в примере выше подставляется текущая дата.

Параметры changefreq и priority носят рекомендательный характер для поисковых систем. При настройке changefreq учитывают частоту обновлений контента: для блога — weekly, для страницы контактов — monthly, для архивов — yearly. Приоритет по умолчанию 0.5, главной странице часто задают 1.0.

На проекте с блогом мы настраивали serialize так, чтобы статьи получали приоритет 0.8 и lastmod из frontmatter статьи, а статические страницы «О компании» — 0.6 с ежемесячной периодичностью.

Интернационализация и многоязычные sitemap

Если сайт поддерживает несколько языков и использует встроенную маршрутизацию Astro с локалями, sitemap должен содержать атрибуты hreflang. Это помогает поисковым системам понять соответствие языковых версий. Интеграция @astrojs/sitemap поддерживает i18n через опцию i18n.

import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';

export default defineConfig({
  site: 'https://example.com',
  i18n: {
    defaultLocale: 'en',
    locales: { en: 'en-US', de: 'de-DE', fr: 'fr-FR' }
  },
  integrations: [
    sitemap({
      i18n: {
        defaultLocale: 'en',
        locales: { en: 'en-US', de: 'de-DE', fr: 'fr-FR' }
      }
    })
  ]
});

При такой настройке для каждой страницы, имеющей переводы, в sitemap добавляются элементы:

<url>
  <loc>https://example.com/en/about</loc>
  <xhtml:link rel="alternate" hreflang="en-US" href="https://example.com/en/about"/>
  <xhtml:link rel="alternate" hreflang="de-DE" href="https://example.com/de/about"/>
  <xhtml:link rel="alternate" hreflang="fr-FR" href="https://example.com/fr/about"/>
  <xhtml:link rel="alternate" hreflang="x-default" href="https://example.com/en/about"/>
</url>

Важно, чтобы названия локалей в i18n совпадали с кодами, используемыми в URL, например en для английской версии. Ошибкой будет указать en-US в locales, а в пути использовать /en/. Интеграция сама сопоставляет локали по префиксам путей. Если конфигурация i18n не задана, hreflang не генерируется.

На проекте с тремя языками мы настраивали sitemap именно через этот объект. Проблем не возникло, проверка в Google Search Console показала корректное распознавание языковых версий. Убедитесь, что canonical URL страниц тоже указывает на правильную локаль, чтобы избежать конфликтов.

Ручная генерация sitemap

Бывают ситуации, когда возможностей интеграции недостаточно: нужно включить динамические маршруты из внешнего API, добавить нестандартные поля или генерировать sitemap в процессе выполнения запроса (SSR). В таких случаях создают эндпоинт вручную — файл src/pages/sitemap.xml.ts (или .js).

Astro обрабатывает такие маршруты как серверные эндпоинты. Они могут возвращать XML-контент с заголовком application/xml. Это даёт полный контроль над содержимым.

export async function GET({ site }) {
  const pages = [
    { url: '/', lastmod: '2026-03-15' },
    { url: '/about', lastmod: '2025-12-01' },
    { url: '/blog', lastmod: '2026-04-10' }
  ];

  const sitemap = `

${pages.map(page => `
  
    ${new URL(page.url, site).href}
    ${page.lastmod}
  `).join('')}
`;

  return new Response(sitemap, {
    headers: { 'Content-Type': 'application/xml' }
  });
}

В примере выше используется синтаксис Astro API Routes. Функция GET получает объект контекста со свойством site, определённым в astro.config.mjs. С помощью этого собираются абсолютные URL.

Для сайтов с Content Collections можно импортировать коллекции напрямую и формировать список URL. Например, для блога:

import { getCollection } from 'astro:content';

export async function GET({ site }) {
  const posts = await getCollection('blog');
  const pages = posts.map(post => ({
    url: `/blog/${post.slug}`,
    lastmod: post.data.updatedDate || post.data.pubDate
  }));
  // ... генерация XML
}

Основной недостаток ручного подхода — необходимость самостоятельно поддерживать формат и обновлять список страниц при добавлении новых маршрутов. Поэтому в большинстве случаев используют штатную интеграцию, а ручной метод оставляют для специфичных задач: стартовых лендингов с нестандартной структурой или SSR-приложений с динамическим контентом.

Sitemap и Content Collections

В проектах на Astro контент часто хранится в коллекциях (блог, проекты). Интеграция @astrojs/sitemap умеет автоматически определять дату последнего изменения страницы на основе полей pubDate и updatedDate из frontmatter каждой записи.

Если в коллекции определена схема с этими полями, Astro при построении маршрута передаёт в serialize значение item.lastmod. Разработчику не нужно вручную вычислять дату через Git.

// src/content/config.ts
import { defineCollection, z } from 'astro:content';

const blog = defineCollection({
  schema: z.object({
    title: z.string(),
    pubDate: z.date(),
    updatedDate: z.date().optional(),
    category: z.string().optional()
  })
});

export const collections = { blog };

Когда в serialize возвращают lastmod: item.lastmod, для каждой статьи дата будет либо из updatedDate, либо из pubDate, если первая не задана. Это исключает ситуацию, когда обновлённая статья сохраняет старую дату в sitemap.

На нескольких сайтах с блогом мы не писали ни строчки дополнительного кода для этого — достаточно было настроить схему и использовать базовый serialize с пробрасыванием item.lastmod. Точность дат повысила скорость переиндексации обновлённых материалов в Яндексе и Bing.

Настройка entryLimit и разбивка больших sitemap на файлы

Стандарт sitemap ограничивает размер одного файла: максимум 50 000 URL и не более 50 МБ. Если сайт содержит больше страниц, карта сайта разбивается на несколько файлов, а индексный файл ссылается на каждый из них. Интеграция @astrojs/sitemap управляет этим через параметр entryLimit.

По умолчанию entryLimit равен 1000. Это консервативное значение: при таком пороге генерируется индексный файл sitemap-index.xml, а сами записи распределяются по файлам sitemap-0.xml, sitemap-1.xml и так далее. Увеличивая лимит до 5000 или 10000, можно сократить количество файлов, но нужно следить за размером каждого.

sitemap({
  entryLimit: 5000
})

На проекте с каталогом 15 000 товаров и динамической генерацией страниц фильтров мы использовали entryLimit: 10000. Это дало два файла плюс индекс. Проверка в Google Search Console показала корректную обработку и отсутствие ошибок размера. Однако с ростом числа страниц рекомендуется ограничиться 5000, чтобы поисковые роботы не упирались в лимиты при загрузке одного файла на медленных соединениях.

Индексный файл выглядит так:



  
    https://example.com/sitemap-0.xml
  
  
    https://example.com/sitemap-1.xml
  

Если сайт содержит менее 1000 страниц (или меньше установленного лимита), индексный файл не создаётся — сразу отдаётся sitemap-index.xml с полным списком URL. При использовании ручного sitemap индексацию и разбиение нужно реализовывать самостоятельно.

Деплой и мониторинг sitemap в поисковых системах

После выполнения astro build готовый sitemap попадает в папку dist (или настроенную outDir). Для статических хостингов (Vercel, Netlify, Cloudflare Pages) этот файл раздаётся как обычный ресурс. В проектах с mode: 'hybrid' sitemap генерируется на этапе сборки для статических страниц, а SSR-страницы в него не попадают — их нужно добавлять вручную или использовать серверный эндпоинт.

Обязательный шаг после деплоя — указать путь к sitemap в файле robots.txt. В Astro можно добавить строчку вручную в папке public/robots.txt:

Sitemap: https://example.com/sitemap-index.xml

Если используется ручной robots.txt, убедитесь, что он не блокирует доступ к sitemap. Некоторые проекты генерируют robots.txt динамически через интеграции.

После публикации sitemap отправляют на проверку в Google Search Console и Яндекс.Вебмастер. В GSC переходят в раздел «Файлы Sitemap», вставляют адрес sitemap-index.xml и нажимают «Отправить». Статистика по обработанным URL появляется в течение нескольких часов.

Для ускорения индексации новых или обновлённых страниц в 2026 году протокол IndexNow поддерживается Яндексом, Bing, Naver и экспериментально Google. Astro не имеет встроенной интеграции, но можно добавить вызов IndexNow API в процесс CI/CD или через серверный маршрут. В этом случае URL отправляются напрямую поисковикам без ожидания переобхода. Если нет желания настраивать интеграцию вручную, можно воспользоваться сторонними сервисами. Например, Index-Now.ru позволяет отправлять URL в Яндекс, Google и Bing через единый интерфейс. После публикации нового поста на Astro-блоге достаточно передать список ссылок — индексация запускается в течение нескольких секунд. Подобные сервисы экономят время при частом обновлении контента.

Дополнительная информация о поисковой оптимизации Astro-сайтов собрана в статьях Astro — SEO и индексация и SEO-оптимизация Astro сайта. Там разбираются метатеги, структура заголовков, производительность и Core Web Vitals с показателем INP.

Частые вопросы

Можно ли исключить страницу из sitemap через frontmatter, не трогая конфиг?

Да. Если в frontmatter страницы добавить noindex: true, интеграция @astrojs/sitemap автоматически пропустит этот маршрут. Атрибут работает даже без дополнительного фильтра в конфигурации.

Почему sitemap не появляется при сборке на локальной машине?

Проверьте, что в astro.config.mjs задано поле site с корректным URL. Без него интеграция не сможет сформировать абсолютные ссылки. Также убедитесь, что используется режим static или hybrid. В SSR sitemap не генерируется автоматически.

Как добавить в sitemap страницы, которые не генерирует Astro (например, старые URL с другого фреймворка)?

Для этого в параметрах интеграции предусмотрен массив customPages. Передайте в него список URL-путей, например ['/old-page', '/legacy/about']. Они попадут в карту сайта наравне с остальными. Значения lastmod и прочих полей можно задать в serialize.

Обновляется ли sitemap при обновлении отдельной страницы без полной пересборки?

В статическом режиме sitemap формируется только во время astro build. При инкрементальной генерации (ISR) в режиме hybrid карта сайта не обновляется до следующей полной сборки. Для динамического обновления реализуют ручной эндпоинт, который на лету собирает актуальные маршруты.

Где проверить, что sitemap прошёл валидацию?

После отправки в Google Search Console проверьте статус в разделе «Файлы Sitemap». Успешно обработанные записи помечаются зелёной галочкой с количеством обнаруженных URL. Дополнительно можно открыть файл в браузере — отсутствие ошибок парсинга и корректная структура XML означают, что sitemap валиден.