Как работает файловая маршрутизация в 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→/aboutsrc/pages/blog/index.astro→/blogsrc/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 режимах.