Skip to content

路由

Astro 使用 基于文件的路由 根据项目 src/pages/ 目录的文件布局生成构建 URL。

Astro uses file-based routing to generate your build URLs based on the file layout of your project src/pages/ directory.

Astro 使用标准 HTML <a> 元素 在路由之间导航。 没有提供特定于框架的 <Link> 组件。

Astro uses standard HTML <a> elements to navigate between routes. There is no framework-specific <Link> component provided.

src/pages/index.astro
<p>
Read more <a href="/about/">about</a> Astro!
</p>

.astro 页面组件 以及 src/pages/ 目录 自动成为你网站上的页面 中的 Markdown 和 MDX 文件(.md.mdx)。 每个页面的路由对应于 src/pages/ 目录中的路径和文件名。

.astro page components as well as Markdown and MDX Files (.md, .mdx) within the src/pages/ directory automatically become pages on your website. Each page’s route corresponds to its path and filename within the src/pages/ directory.

# Example: Static routes
src/pages/index.astro -> mysite.com/
src/pages/about.astro -> mysite.com/about
src/pages/about/index.astro -> mysite.com/about
src/pages/about/me.astro -> mysite.com/about/me
src/pages/posts/1.md -> mysite.com/posts/1

:::tip 提示 Astro 项目中没有单独的 “路由配置” 需要维护! 当你将文件添加到 src/pages/ 目录时,会自动为你创建一条新路由。 在静态构建中,你可以使用 build.format 配置选项自定义文件输出格式。 :::

Astro 页面文件可以在其文件名中指定动态路由参数以生成多个匹配的页面。 例如,src/pages/authors/[author].astro 为你博客上的每位作者生成一个简介页面。 author 成为你可以从页面内部访问的参数。

An Astro page file can specify dynamic route parameters in its filename to generate multiple, matching pages. For example, src/pages/authors/[author].astro generates a bio page for every author on your blog. author becomes a parameter that you can access from inside the page.

在 Astro 默认的静态输出模式下,这些页面是在构建时生成的,因此你必须预先确定获取相应文件的 author 列表。 在 SSR 模式下,将根据请求为任何匹配的路由生成页面。

In Astro’s default static output mode, these pages are generated at build time, and so you must predetermine the list of authors that get a corresponding file. In SSR mode, a page will be generated on request for any route that matches.

由于所有路由都必须在构建时确定,因此动态路由必须导出 getStaticPaths(),该 getStaticPaths() 返回具有 params 属性的对象数组。 这些对象中的每一个都会生成相应的路由。

Because all routes must be determined at build time, a dynamic route must export a getStaticPaths() that returns an array of objects with a params property. Each of these objects will generate a corresponding route.

[dog].astro 在其文件名中定义了动态 dog 参数,因此 getStaticPaths() 返回的对象必须在其 params 中包含 dog。 然后页面可以使用 Astro.params 访问该参数。

[dog].astro defines the dynamic dog parameter in its filename, so the objects returned by getStaticPaths() must include dog in their params. The page can then access this parameter using Astro.params.

src/pages/dogs/[dog].astro
---
export function getStaticPaths() {
return [
{params: {dog: 'clifford'}},
{params: {dog: 'rover'}},
{params: {dog: 'spot'}},
];
}
const { dog } = Astro.params;
---
<div>Good dog, {dog}!</div>

这将生成三个页面: /dogs/clifford/dogs/rover/dogs/spot,分别显示对应的狗名。

This will generate three pages: /dogs/clifford, /dogs/rover, and /dogs/spot, each displaying the corresponding dog name.

文件名可以包含多个参数,这些参数必须全部包含在 getStaticPaths() 中的 params 对象中:

The filename can include multiple parameters, which must all be included in the params objects in getStaticPaths():

src/pages/[lang]-[version]/info.astro
---
export function getStaticPaths () {
return [
{params: {lang: 'en', version: 'v1'}},
{params: {lang: 'fr', version: 'v2'}},
];
}
const { lang, version } = Astro.params;
---
...

这将生成 /en-v1/info/fr-v2/info

This will generate /en-v1/info and /fr-v2/info.

参数可以包含在路径的单独部分中。 例如,文件 src/pages/[lang]/[version]/info.astro 与上面的 getStaticPaths() 相同,将生成路由 /en/v1/info/fr/v2/info

Parameters can be included in separate parts of the path. For example, the file src/pages/[lang]/[version]/info.astro with the same getStaticPaths() above will generate the routes /en/v1/info and /fr/v2/info.

📚 了解有关 getStaticPaths() 的更多信息。

📚 Learn more about getStaticPaths().

Related recipe: 添加国际化功能

如果你的 URL 路由需要更大的灵活性,你可以在 .astro 文件名中使用 剩余参数 ([...path]) 来匹配任何深度的文件路径:

If you need more flexibility in your URL routing, you can use a rest parameter ([...path]) in your .astro filename to match file paths of any depth:

src/pages/sequences/[...path].astro
---
export function getStaticPaths() {
return [
{params: {path: 'one/two/three'}},
{params: {path: 'four'}},
{params: {path: undefined }}
]
}
const { path } = Astro.params;
---
...

这将生成 /sequences/one/two/three/sequences/four/sequences。 (将其余参数设置为 undefined 可以使其匹配顶层页面。)

This will generate /sequences/one/two/three, /sequences/four, and /sequences. (Setting the rest parameter to undefined allows it to match the top level page.)

其余参数可与 其他命名参数 一起使用。 例如,GitHub 的文件查看器可以用以下动态路由表示:

Rest parameters can be used with other named parameters. For example, GitHub’s file viewer can be represented with the following dynamic route:

/[org]/[repo]/tree/[branch]/[...file]

在此示例中,对 /withastro/astro/tree/main/docs/public/favicon.svg 的请求将被拆分为以下命名参数:

In this example, a request for /withastro/astro/tree/main/docs/public/favicon.svg would be split into the following named parameters:

{
org: 'withastro',
repo: 'astro',
branch: 'main',
file: 'docs/public/favicon.svg'
}

在以下示例中,剩余参数 ([...slug]) 和 getStaticPaths()props 功能为不同深度的 slugs 生成页面。

In the following example, a rest parameter ([...slug]) and the props feature of getStaticPaths() generate pages for slugs of different depths.

src/pages/[...slug].astro
---
export async function getStaticPaths() {
const pages = [
{
slug: undefined,
title: "Astro Store",
text: "Welcome to the Astro store!",
},
{
slug: "products",
title: "Astro products",
text: "We have lots of products for you",
},
{
slug: "products/astro-handbook",
title: "The ultimate Astro handbook",
text: "If you want to learn Astro, you must read this book.",
},
];
return pages.map(({ slug, title, text }) => {
return {
params: { slug },
props: { title, text },
};
});
}
const { title, text } = Astro.props;
---
<html>
<head>
<title>{title}</title>
</head>
<body>
<h1>{title}</h1>
<p>
{text}
</p>
</body>
</html>

SSR 模式 中,动态路由的定义方式相同: 在文件名中包含 [param][...path] 括号以匹配任意字符串或路径。 但由于路由不再提前构建,因此页面将被提供给任何匹配的路由。 由于这些不是 “static” 路由,因此不应使用 getStaticPaths

In SSR mode, dynamic routes are defined the same way: include [param] or [...path] brackets in your file names to match arbitrary strings or paths. But because the routes are no longer built ahead of time, the page will be served to any matching route. Since these are not “static” routes, getStaticPaths should not be used.

src/pages/resources/[resource]/[id].astro
---
const { resource, id } = Astro.params;
---
<h1>{resource}: {id}</h1>

此页面将为 resourceid 的任意值提供服务: resources/users/1resources/colors/blue

This page will be served for any value of resource and id: resources/users/1, resources/colors/blue, etc.

修改 SSR 的 [...slug] 示例

Section titled 修改 SSR 的 [...slug] 示例

由于 SSR 页面无法使用 getStaticPaths(),因此它们无法接收属性。 通过查找对象中 slug 参数的值,可以将 前面的例子 适配为 SSR 模式。 如果路由位于根 (”/”),则 slug 参数将为 undefined。 如果对象中不存在该值,我们将重定向到 404 页面。

Because SSR pages can’t use getStaticPaths(), they can’t receive props. The previous example can be adapted for SSR mode by looking up the value of the slug param in an object. If the route is at the root (”/”), the slug param will be undefined. If the value doesn’t exist in the object, we redirect to a 404 page.

src/pages/[...slug].astro
---
const pages = [
{
slug: undefined,
title: 'Astro Store',
text: 'Welcome to the Astro store!',
},
{
slug: 'products',
title: 'Astro products',
text: 'We have lots of products for you',
},
{
slug: 'products/astro-handbook',
title: 'The ultimate Astro handbook',
text: 'If you want to learn Astro, you must read this book.',
}
];
const { slug } = Astro.params;
const page = pages.find((page) => page.slug === slug);
if (!page) return Astro.redirect("/404");
const { title, text } = page;
---
<html>
<head>
<title>{title}</title>
</head>
<body>
<h1>{title}</h1>
<p>
{text}
</p>
</body>
</html>

有时,你需要将读者重定向到新页面,要么是因为站点结构发生了永久性更改,要么是为了响应登录到经过身份验证的路由等操作。

Sometimes you will need to redirect your readers to a new page, either permanently because your site structure has changed or in response to an action such as logging in to an authenticated route.

你可以在 Astro 配置中定义 将用户重定向到永久移动的页面 的规则。 或者,动态重定向用户,因为他们使用你的网站。

You can define rules to redirect users to permanently-moved pages in your Astro config. Or, redirect users dynamically as they use your site.

Added in: astro@2.9.0

你可以使用 redirects 值在 Astro 配置中指定永久重定向的映射。 对于大多数重定向,这是旧路由到新路由的映射:

You can specify a mapping of permanent redirects in your Astro config with the redirects value. For most redirects, this is a mapping of an old route to the new route:

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
redirects: {
'/old-page': '/new-page'
}
});

这些重定向遵循与基于文件的路由相同的规则。 只要新旧路由包含相同的参数,就允许动态路由,例如:

These redirects follow the same rules as file-based routes. Dynamic routes are allowed as long as both the new and old routes contain the same parameters, for example:

{
"/blog/[...slug]": "/articles/[...slug]"
}

使用 SSR 或静态适配器,你还可以提供一个对象作为值,允许你除了新的 destination 之外还指定 status 代码:

Using SSR or a static adapter, you can also provide an object as the value, allowing you to specify the status code in addition to the new destination:

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
redirects: {
'/old-page': {
status: 302,
destination: '/new-page'
}
}
});

运行 astro build 时,Astro 默认会输出带有 元刷新 标签的 HTML 文件。 支持的适配器将使用重定向写出主机的配置文件。

When running astro build, Astro will output HTML files with the meta refresh tag by default. Supported adapters will instead write out the host’s configuration file with the redirects.

状态码默认为 301。 如果构建为 HTML 文件,服务器不会使用状态代码。

The status code is 301 by default. If building to HTML files the status code is not used by the server.

Astro 全局上,Astro.redirect 方法允许你动态重定向到另一个页面。 你可以在通过从 cookie 获取会话来检查用户是否登录后执行此操作。

On the Astro global, the Astro.redirect method allows you to redirect to another page dynamically. You might do this after checking if the user is logged in by getting their session from a cookie.

src/pages/account.astro
---
import { isLoggedIn } from '../utils';
const cookie = Astro.request.headers.get('cookie');
// If the user is not logged in, redirect them to the login page
if (!isLoggedIn(cookie)) {
return Astro.redirect('/login');
}
---
<html>
<!-- Page here... -->
</html>

多个路由可以匹配同一个 URL 路径。 例如,这些路由中的每一个都将匹配 /posts/create

It’s possible for multiple routes to match the same URL path. For example each of these routes would match /posts/create:

  • Directorysrc/pages/
    • Directoryposts/
      • create.astro
      • [pid].astro
      • […slug].astro

Astro 需要知道应该使用哪条路由来构建页面。 为此,它根据以下规则对它们进行排序:

Astro needs to know which route should be used to build the page. To do so, it sorts them according to the following rules:

  • 没有路径参数的静态路由将优先于所有其他路由
  • 使用命名参数的动态路由优先于其余参数
  • 预渲染动态路由优先于服务器动态路由
  • 其余参数具有最低优先级
  • 端点始终优先于页面
  • 平局按字母顺序解决

鉴于上面的示例,以下是规则如何将请求的 URL 与用于构建 HTML 的路由相匹配的几个示例:

Given the example above, here are a few examples of how the rules will match a requested URL to the route used to build the HTML:

  • pages/posts/create.astro - 将构建 /posts/create
  • pages/posts/[pid].astro - 将构建 /posts/1/posts/abc 等,但不会构建 /posts/create
  • pages/posts/[...slug].astro - 将构建 /posts/1/2/posts/a/b/c 等,但不会构建 /posts/create/posts/1/posts/abc

重定向也遵循相同的规则,但优先级排在最后; 如果存在基于文件的路由和具有相同路由优先级的重定向,则选择基于文件的路由。

Redirects also follow the same rules, but are prioritized last; if there is a file-based route and a redirect with the same route priority level, the file-based route is chosen.

Astro 支持针对需要拆分为多个页面的大量数据的内置分页。 Astro 将生成常见的分页属性,包括上一页/下一页 URL、总页数等。

Astro supports built-in pagination for large collections of data that need to be split into multiple pages. Astro will generate common pagination properties, including previous/next page URLs, total number of pages, and more.

分页路由名称应使用与标准动态路由相同的 [bracket] 语法。 例如,文件名 /astronauts/[page].astro 将生成 /astronauts/1/astronauts/2 等的路由,其中 [page] 是生成的页码。

Paginated route names should use the same [bracket] syntax as a standard dynamic route. For instance, the file name /astronauts/[page].astro will generate routes for /astronauts/1, /astronauts/2, etc, where [page] is the generated page number.

你可以使用 paginate() 函数为值数组生成这些页面,如下所示:

You can use the paginate() function to generate these pages for an array of values like so:

src/pages/astronauts/[page].astro
---
export async function getStaticPaths({ paginate }) {
const astronautPages = [{
astronaut: 'Neil Armstrong',
}, {
astronaut: 'Buzz Aldrin',
}, {
astronaut: 'Sally Ride',
}, {
astronaut: 'John Glenn',
}];
// Generate pages from our array of astronauts, with 2 to a page
return paginate(astronautPages, { pageSize: 2 });
}
// All paginated data is passed on the "page" prop
const { page } = Astro.props;
---
<!--Display the current page number. Astro.params.page can also be used!-->
<h1>Page {page.currentPage}</h1>
<ul>
<!--List the array of astronaut info-->
{page.data.map(({ astronaut }) => <li>{astronaut}</li>)}
</ul>

这会生成以下页面,每个页面包含 2 个项目:

  • /astronauts/1 - 第 1 页: 显示 “尼尔阿姆斯特朗” 和 “巴兹·奥尔德林”
  • /astronauts/2 - 第 2 页: 显示 “Sally Ride” 和 “约翰·格伦”

当你使用 paginate() 函数时,每个页面将通过 page 属性传递其数据。 page 属性有许多有用的属性,但以下是重点:

  • page.data - 包含传递给 paginate() 函数的页面数据片段的数组
  • page.url.next - 链接到该集中的下一页
  • page.url.prev - 链接到集合中的上一页
src/pages/astronauts/[page].astro
---
// Paginate same list of { astronaut } objects as the previous example
export async function getStaticPaths({ paginate }) { /* ... */ }
const { page } = Astro.props;
---
<h1>Page {page.currentPage}</h1>
<ul>
{page.data.map(({ astronaut }) => <li>{astronaut}</li>)}
</ul>
{page.url.prev ? <a href={page.url.prev}>Previous</a> : null}
{page.url.next ? <a href={page.url.next}>Next</a> : null}
interface Page<T = any> {
/** result */
data: T[];
/** metadata */
/** the count of the first item on the page, starting from 0 */
start: number;
/** the count of the last item on the page, starting from 0 */
end: number;
/** total number of results */
total: number;
/** the current page number, starting from 1 */
currentPage: number;
/** number of items per page (default: 25) */
size: number;
/** number of last page */
lastPage: number;
url: {
/** url of the current page */
current: string;
/** url of the previous page (if there is one) */
prev: string | undefined;
/** url of the next page (if there is one) */
next: string | undefined;
};
}

分页的更高级用例是 嵌套分页。 这是分页与其他动态路由参数结合使用的情况。 你可以使用嵌套分页按某些属性或标签对分页集合进行分组。

A more advanced use-case for pagination is nested pagination. This is when pagination is combined with other dynamic route params. You can use nested pagination to group your paginated collection by some property or tag.

例如,如果你想按某个标签对分页 Markdown 帖子进行分组,则可以通过创建与以下 URL 匹配的 /src/pages/[tag]/[page].astro 页面来使用嵌套分页:

For example, if you want to group your paginated Markdown posts by some tag, you would use nested pagination by creating a /src/pages/[tag]/[page].astro page that would match the following URLS:

  • /red/1 (标签=红色)
  • /red/2 (标签=红色)
  • /blue/1 (标签=蓝色)
  • /green/1 (标签=绿色)

嵌套分页的工作原理是从 getStaticPaths() 返回一组 paginate() 结果,每个分组一个。

Nested pagination works by returning an array of paginate() results from getStaticPaths(), one for each grouping.

在下面的示例中,我们将实现嵌套分页来构建上面列出的 URL:

In the following example, we will implement nested pagination to build the URLs listed above:

src/pages/[tag]/[page].astro
---
export async function getStaticPaths({ paginate }) {
const allTags = ['red', 'blue', 'green'];
const allPosts = await Astro.glob('../../posts/*.md');
// For every tag, return a paginate() result.
// Make sure that you pass `{params: {tag}}` to `paginate()`
// so that Astro knows which tag grouping the result is for.
return allTags.flatMap((tag) => {
const filteredPosts = allPosts.filter((post) => post.frontmatter.tag === tag);
return paginate(filteredPosts, {
params: { tag },
pageSize: 10
});
});
}
const { page } = Astro.props;
const params = Astro.params;

你可以通过在页面或目录名称前添加下划线 (_) 来排除页面或目录的构建。 带有 _ 前缀的文件不会被路由识别,也不会被放入 dist/ 目录中。

You can exclude pages or directories from being built by prefixing their names with an underscore (_). Files with the _ prefix won’t be recognized by the router and won’t be placed into the dist/ directory.

你可以使用它来暂时禁用页面,也可以将测试、实用程序和组件放在与其相关页面相同的文件夹中。

You can use this to temporarily disable pages, and also to put tests, utilities, and components in the same folder as their related pages.

在此示例中,仅 src/pages/index.astrosrc/pages/posts/post1.md 将构建为页面路由和 HTML 文件。

In this example, only src/pages/index.astro and src/pages/posts/post1.md will be built as page routes and HTML files.

  • Directorysrc/pages/
    • Directory_hidden-directory/
      • page1.md
      • page2.md
    • _hidden-page.astro
    • index.astro
    • Directoryposts/
      • _SomeComponent.astro
      • _utils.js
      • post1.md