AstroJuniorCoding

Как работает файловая маршрутизация в Astro? Как создавать динамические маршруты?

Каждый файл в src/pages/ становится маршрутом: статические файлы — напрямую, динамические сегменты задаются через [param].astro и требуют getStaticPaths() в SSG; spread-маршруты [...slug].astro ловят любую вложенность.

Файловая маршрутизация в Astro

Astro использует файловую систему как единственный источник маршрутов. Каждый файл в директории src/pages/ становится маршрутом. Это работает для .astro, .md, .mdx, а также .ts/.js для API-маршрутов.

Статические маршруты

  • src/pages/index.astro/
  • src/pages/about.astro/about
  • src/pages/blog/index.astro/blog
  • src/pages/blog/first-post.md/blog/first-post

Динамические маршруты

Сегмент в квадратных скобках создаёт динамический параметр. В режиме SSG обязателен getStaticPaths():

---
// src/pages/blog/[slug].astro
export async function getStaticPaths() {
  const posts = [
    { slug: 'hello-world', title: 'Hello World' },
    { slug: 'astro-routing', title: 'Маршрутизация в Astro' },
  ];

  return posts.map(post => ({
    params: { slug: post.slug },
    props:  { title: post.title },
  }));
}

const { slug } = Astro.params;  // 'hello-world'
const { title } = Astro.props;  // 'Hello World'
---

<h1>{title}</h1>

Spread-маршруты (catch-all)

[...slug].astro перехватывает любое количество сегментов пути:

---
// src/pages/docs/[...slug].astro
export async function getStaticPaths() {
  return [
    { params: { slug: 'getting-started' } },           // /docs/getting-started
    { params: { slug: 'guides/installation' } },        // /docs/guides/installation
    { params: { slug: undefined } },                    // /docs/
  ];
}

const { slug } = Astro.params; // 'guides/installation'
---

API-маршруты (Endpoints)

Файлы .ts и .js в src/pages/ становятся API-эндпоинтами:

// src/pages/api/users/[id].ts
import type { APIRoute } from 'astro';

export const GET: APIRoute = async ({ params, request }) => {
  const userId = params.id;
  const user = await fetchUser(userId);

  if (!user) {
    return new Response(JSON.stringify({ error: 'Not found' }), {
      status: 404,
      headers: { 'Content-Type': 'application/json' },
    });
  }

  return new Response(JSON.stringify(user), {
    headers: { 'Content-Type': 'application/json' },
  });
};

export const POST: APIRoute = async ({ request }) => {
  const body = await request.json();
  // ...
  return new Response(JSON.stringify({ success: true }));
};

Редиректы в конфиге

// astro.config.mjs
export default defineConfig({
  redirects: {
    '/old-blog': '/blog',
    '/old-blog/[slug]': '/blog/[slug]',
  },
});

Приоритет маршрутов

При конфликте маршрутов Astro применяет порядок приоритетов: статические > динамические с параметром > spread-маршруты. Например, /blog/about совпадёт со статическим about.astro, а не с [slug].astro.

Подводные камни

  • Забытый getStaticPaths — динамический маршрут без этой функции в SSG-режиме вызовет ошибку сборки.
  • Регистр имён файлов — файловая система macOS нечувствительна к регистру, Linux — чувствительна; About.astro и about.astro могут конфликтовать в production.
  • Spread undefined для корня[...slug].astro не перехватит /docs/ без явного { slug: undefined } в getStaticPaths.
  • API-маршруты и CORS — CORS-заголовки не добавляются автоматически; нужно возвращать их в каждом Response.
  • Конфликт .astro и .md маршрутов — если существуют /blog.astro и /blog/index.md одновременно, один из маршрутов будет проигнорирован.
  • Динамические маршруты в SSR — в режиме output: 'server' getStaticPaths не нужен, но Astro.params может быть undefined, если маршрут обращается к несуществующему параметру.
  • Вложенные динамические сегменты[category]/[slug].astro работает, но оба параметра должны быть в одном файле; создание отдельных файлов для каждого уровня не поддерживается.

Common mistakes

  • Забыть getStaticPaths() в статическом режиме и удивляться ошибке билда.
  • Не учитывать приоритет статического маршрута над динамическим.
  • Возвращать огромный массив путей без пагинации и убивать время билда.

What the interviewer is testing

  • Понимает соответствие файл -> URL.
  • Знает синтаксис [param] и [...rest].
  • Умеет объяснить разницу маршрутизации в static и server режимах.

Sources

Related topics