Pular para o conteúdo

Roteamento

Astro utiliza roteamento baseado em arquivos para gerar as URLs da sua build com base na disposição dos arquivos do diretório src/pages/ de seu projeto.

Astro usa elementos <a> padrões do HTML para navegar entre rotas. Não há um componente <Link> específico do framework sendo providenciado.

src/pages/index.astro
<p>Leia mais <a href="/sobre/">sobre</a> Astro!</p>

Componentes de página .astro assim como arquivos Markdown e MDX (.md, .mdx) dentro do diretório src/pages/ automaticamente se tornam páginas no seu website. A rota de cada página corresponde ao seu caminho e nome de arquivo no diretório src/pages/.

# Exemplo: Rotas estáticas
src/pages/index.astro -> meusite.com/
src/pages/sobre.astro -> meusite.com/sobre
src/pages/sobre/index.astro -> meusite.com/sobre
src/pages/sobre/mim.astro -> meusite.com/sobre/mim
src/pages/postagens/1.md -> meusite.com/postagens/1

Um arquivo de página Astro pode especificar parâmetros de rota dinâmicos em seu nome de arquivo para gerar múltiplas páginas correspondentes. Por exemplo, src/pages/autores/[autor].astro gera uma página de biografia para cada autor no seu blog. autor se torna um parâmetro que você pode acessar de dentro da página.

No modo estático padrão do Astro, essas páginas são geradas em tempo de build, e logo, você precisa predeterminar a lista de autores que ganham um arquivo correspondente. No modo SSR, uma página será gerada na requisição para qualquer rota que corresponde.

Por conta de todas as rotas precisarem ser determinadas em tempo de build, uma rota dinâmica precisa exportar um getStaticPaths() que retorna um array de objetos com uma propriedade params. Cada um desses objetos irá gerar uma rota correspondente.

[cachorro].astro define o parâmetro dinâmico cachorro em seu nome de arquivo, então os objetos retornados por getStaticPaths() devem incluir cachorro em suas params. A página pode então acessar esse parâmetro utilizando Astro.params.

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

Isso irá gerar três páginas: /cachorros/clifford, /cachorros/rover, and /cachorros/spot, cada uma mostrando o nome do cachorro correspondente.

O nome do arquivo pode incluir múltiplos parâmetros, sendo que todos precisam ser inclusos nos objetos params em getStaticPaths():

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

Isso irá gerar /en-v1/info e /fr-v2/info.

Parâmetros podem ser incluídos em partes separadas do caminho. Por exemplo, o arquivo src/pages/[lingua]/[versao]/info.astro com o mesmo getStaticPaths() acima irá gerar as rotas /en/v1/info e /fr/v2/info.

📚 Leia mais sobre getStaticPaths().

Se você precisa de mais flexibilidade no roteamento de sua URL, você pode utilizar um parâmetro rest ([...caminho]) no nome do seu arquivo .astro para corresponder caminhos de arquivo de qualquer profundidade:

src/pages/sequencias/[...caminho].astro
---
export function getStaticPaths() {
return [
{params: {caminho: 'um/dois/três'}},
{params: {caminho: 'quatro'}},
{params: {caminho: undefined }}
]
}
const { caminho } = Astro.params;
---
...

Isso irá gerar /sequencias/um/dois/três, /sequencias/quatro e /sequencias. (Definir o parâmetro rest como undefined o permite corresponder a página de nível superior.)

Parâmetros rest podem ser utilizados com outros parâmetros nomeados. Por exemplo, o visualizador de arquivos do GitHub pode ser representado com a seguinte rota dinâmica:

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

Nesse exemplo, uma requisição a /withastro/astro/tree/main/docs/public/favicon.svg seria dividida nos seguintes parâmetros nomeados:

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

Exemplo: Páginas dinâmicas em múltiplos níveis

Seção intitulada Exemplo: Páginas dinâmicas em múltiplos níveis

No exemplo a seguir, um parâmetro rest ([...slug]) e a funcionalidade props de getStaticPaths() geram páginas para slugs de diferentes profundidades.

src/pages/[...slug].astro
---
export async function getStaticPaths() {
const paginas = [
{
slug: undefined,
titulo: "Loja Astro",
texto: "Bem-vindo à loja Astro!",
},
{
slug: "produtos",
titulo: "Produtos Astro",
texto: "Nós temos vários produtos para você",
},
{
slug: "produtos/manual-astro",
titulo: "O manual definitivo do Astro",
texto: "Se você quer aprender Astro, você precisa ler esse livro.",
},
];
return paginas.map(({ slug, titulo, texto }) => {
return {
params: { slug },
props: { titulo, texto },
};
});
}
const { titulo, texto } = Astro.props;
---
<html>
<head>
<title>{titulo}</title>
</head>
<body>
<h1>{titulo}</h1>
<p>{texto}</p>
</body>
</html>

No modo SSR, rotas dinâmicas são definidas da mesma forma: inclua colchetes [param] ou [...path] no nome de seus arquivos para corresponder a strings ou caminhos arbitrários. Porém, já que as rotas não são mais construídas com antecedência, a página será servida para qualquer rota correspondente. Já que essas não são rotas “estáticas”, getStaticPaths não deve ser utilizado.

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

A página será servida para qualquer valor de recurso e id: recursos/usuarios/1, recursos/cores/azul, etc.

Modificando o exemplo [...slug] para SSR

Seção intitulada Modificando o exemplo [...slug] para SSR

Já que páginas SSR não podem utilizar getStaticPaths(), elas não podem receber props. O exemplo anterior pode ser adaptado para funcionar com SSR ao olhar para o valor do parâmetro slug em um objeto. Se a rota está na raiz (”/”), o parâmetro slug será undefined. Se o valor não existe no objeto, nós redirecionamos para uma página de 404.

src/pages/[...slug].astro
---
const paginas = [
{
slug: undefined,
titulo: "Loja Astro",
texto: "Bem-vindo à loja Astro!",
},
{
slug: "produtos",
titulo: "Produtos Astro",
texto: "Nós temos vários produtos para você",
},
{
slug: "produtos/manual-astro",
titulo: "O manual definitivo do Astro",
texto: "Se você quer aprender Astro, você precisa ler esse livro.",
},
];
const { slug } = Astro.params;
const pagina = paginas.find((pagina) => pagina.slug === slug);
if (!pagina) return Astro.redirect("/404");
const { titulo, texto } = pagina;
---
<html>
<head>
<title>{titulo}</title>
</head>
<body>
<h1>{titulo}</h1>
<p>{texto}</p>
</body>
</html>

As vezes você irá precisar redirecionar seus leitores para uma nova página, seja permanentemente pois a estrutura do seu site mudou ou em resposta a uma ação como logar em uma rota autenticada.

Você pode definir regras para redirecionar usuários para páginas permanentemente movidas na sua configuração do Astro. Ou, redirecionar usuários dinamicamente enquanto eles utilizam seu site.

Adicionado em: astro@2.9.0

Você pode especificar um mapeamento de redirecionamentos permanentes na sua configuração do Astro com o valor de redirects. Para a maioria dos redirecionamentos, isto é um mapeamento de uma rota antiga para uma nova rota:

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
redirects: {
'/pagina-antiga': '/nova-pagina'
}
});

Estes redirecionamentos seguem as mesmas regras que rotas baseadas em arquivos. Rotas dinâmicas são permitidas contanto que ambas as antigas e novas rotas contenham os mesmos parâmetros, por exemplo:

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

Usando um adaptador de SSR ou estático, você também pode providenciar um objeto como o valor, te permitindo especificar o código de status em adição ao novo destino (destination):

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
redirects: {
'/pagina-antiga': {
status: 302,
destination: '/nova-pagina'
}
}
});

Ao executar astro build, o Astro irá retornar arquivos HTML com a tag meta refresh por padrão. Adaptadores suportados irão ao invés disso, escrever o arquivo de configuração da hospedagem com os redirecionamentos.

O código de estado é 301 por padrão. Se estiver fazendo build de arquivos HTML, o código de estado não é utilizado pelo servidor.

Na global Astro, o método Astro.redirect te permite redirecionar para outra página dinamicamente. Você pode fazer isso após checar se o usuário está logado ao pegar sua sessão de um cookie.

src/pages/conta.astro
---
import { isLoggedIn } from '../utils';
const cookie = Astro.request.headers.get('cookie');
// Se o usuário não estiver logado, o redireciona para a página de login
if (!isLoggedIn(cookie)) {
return Astro.redirect('/login');
}
---
<html>
<!-- Página aqui... -->
</html>

É possível que múltiplas rotas correspondam ao mesmo caminho de URL. Por exemplo, cada uma destas rotas iria corresponder a postagens/criar:

  • Directorysrc/pages/
    • Directorypostagens/
      • criar.astro
      • [pid].astro
      • […slug].astro

Astro precisa saber qual rota deve ser utilizada para construir a página. Para fazer isso, Astro as ordena de acordo com as seguintes regras:

  • Rotas estáticas sem parâmetros de caminho terão precedência sobre todas as outras rotas
  • Rotas dinâmicas utilizando parâmetros nomeados terão precedência sobre parâmetros rest
  • Rotas dinâmicas pré-renderizadas terão precedência sobre rotas dinâmicas do servidor
  • Parâmetros rest terão a menor prioridade
  • Endpoints sempre terão precedência sobre páginas
  • Empates são resolvidos alfabeticamente

Com base no exemplo acima, aqui estão alguns exemplos de como as regras irão corresponder a URL requisitada para a rota utilizada para construir o HTML:

  • pages/postagens/criar.astro - irá construir /postagens/criar
  • pages/postagens/[pid].astro - irá construir /postagens/1, /postagens/abc, etc. Mas não /postagens/criar
  • pages/postagens/[...slug].astro - irã construir /postagens/1/2, /postagens/a/b/c, etc. Mas não /postagens/criar, /postagens/1, /postagens/abc

Redirecionamentos também seguem as mesmas regras, mas são priorizados por último; se existe uma rota baseada em arquivo e um redirecionamento com o mesmo número de prioridade da rota, a rota baseada em arquivo é escolhida.

Astro suporta paginação de forma integrada para grandes coleções de dados que precisam ser divididos em múltiplas páginas. Astro irá gerar propriedades comuns de paginação, como URLs de anterior/próxima página, número total de páginas, e mais.

Nomes de rotas paginadas devem utilizar a mesma sintaxe em [colchetes] de rotas dinâmicas comuns. Por exemplo, o nome de arquivo /astronautas/[pagina].astro irá gerar rotas para /astronautas/1, /astronautas/2, etc, onde [pagina] é o número gerado da página.

Você pode utilizar a função paginate() para gerar estas páginas a partir um array de valores como abaixo:

src/pages/astronautas/[pagina].astro
---
export async function getStaticPaths({ paginate }) {
const paginasAstronautas = [{
astronauta: 'Neil Armstrong',
}, {
astronauta: 'Buzz Aldrin',
}, {
astronauta: 'Sally Ride',
}, {
astronauta: 'John Glenn',
}];
// Gera páginas a partir de nosso array de astronautas, com 2 por página
return paginate(paginasAstronautas, { pageSize: 2 });
}
// Todos os dados paginados são passados para a prop "page".
const { page } = Astro.props;
---
<!--Mostra o número da página atual. Astro.params.page também pode ser utilizado!-->
<h1>Página {page.currentPage}</h1>
<ul>
<!--Lista o array de informações sobre astronautas-->
{page.data.map(({ astronauta }) => <li>{astronauta}</li>)}
</ul>

Isso gera as seguintes páginas, com 2 itens por página:

  • /astronautas/1 - Página 1: Mostra “Neil Armstrong” e “Buzz Aldrin”
  • /astronautas/2 - Página 2: Mostra “Sally Ride” e “John Glenn”

Quando você utiliza a função paginate(), cada página terá seus dados passados através da prop page. A prop page tem diversas propriedades úteis, mas aqui estão as mais importantes:

  • page.data - array contendo um pedaço dos dados da página que você passou para a função paginate()
  • page.url.next - link para a próxima página no conjunto
  • page.url.prev - link para a página anterior no conjunto
src/pages/astronautas/[pagina].astro
---
// Faz a paginação da mesma lista de objetos de { astronauta } do exemplo anterior
export async function getStaticPaths({ paginate }) { /* ... */ }
const { page } = Astro.props;
---
<h1>Página {page.currentPage}</h1>
<ul>
{page.data.map(({ astronauta }) => <li>{astronauta}</li>)}
</ul>
{page.url.prev ? <a href={page.url.prev}>Anterior</a> : null}
{page.url.next ? <a href={page.url.next}>Próximo</a> : null}
interface Page<T = any> {
/** resultado */
data: T[];
/** metadados */
/** A contagem do primeiro item na página, começando por 0 */
start: number;
/** A contagem do último item na página, começando por 0 */
end: number;
/** número total de resultados */
total: number;
/** número da página atual, começando por 1 */
currentPage: number;
/** número de itens por página (padrão: 25) */
size: number;
/** número da última página */
lastPage: number;
url: {
/** url da página atual*/
current: string;
/** url da página anterior (se existir) */
prev: string | undefined;
/** url da próxima página (se existir) */
next: string | undefined;
};
}

Um caso de uso mais avançado para página é a paginação aninhada. Isso é quando a paginação é combinada com outros parâmetros dinâmicos de rota. Você pode usar paginação aninhada para agrupar suas coleções paginadas por alguma propriedade ou etiqueta.

Por exemplo, se você quiser agrupar suas postagens em Markdown por alguma etiqueta, você pode usar a paginação aninhada criando uma página /src/pages/[etiqueta]/[pagina].astro que iria corresponder com as seguintes URLs:

  • /vermelho/1 (etiqueta=vermelho)
  • /vermelho/2 (etiqueta=vermelho)
  • /azul/1 (etiqueta=azul)
  • /verde/1 (etiqueta=verde)

Paginação aninhada funciona retornando um array de resultados do paginate() a partir do getStaticPaths(), sendo uma para cada agrupamento.

No exemplo abaixo, nós iremos implementar a paginação aninhada para construir as URLs listados acima:

src/pages/[etiqueta]/[pagina].astro
---
export async function getStaticPaths({ paginate }) {
const todasEtiquetas = ['vermelho', 'azul', 'verde'];
const todasPostagens = await Astro.glob('../../postagens/*.md');
// Para cada etiqueta, retorna um resultado de paginate().
// Se certifique de que você passou `{params: {etiqueta}}` ao `paginate()`
// para que o Astro saiba qual agrupamento de etiqueta o resultado é para.
return todasEtiquetas.flatMap((etiqueta) => {
const postagensFiltradas = todasPostagens.filter((postagem) => postagem.frontmatter.etiqueta === etiqueta);
return paginate(postagensFiltradas, {
params: { etiqueta },
pageSize: 10
});
});
}
const { page } = Astro.props;
const params = Astro.params;

Você pode excluir páginas ou diretórios inteiros da build ao prefixar seus nomes com um sublinhado (_). Arquivos com o prefixo _ não serão reconhecidas pelo roteador e não serão adicionadas ao diretório dist/.

Você pode utilizar isto para temporariamente desabilitar páginas, e para também adicionar testes, utilitários e componentes na mesma pasta que suas páginas relacionadas.

Neste exemplo, apenas src/pages/index.astro e src/pages/postagens/postagem1.md serão construídas como rotas de página e arquivos HTML.

  • Directorysrc/pages/
    • Directory_diretorio-escondido/
      • pagina1.md
      • pagina2.md
    • _pagina-escondida.astro
    • index.astro
    • Directorypostagens/
      • _AlgumComponente.astro
      • _utils.js
      • postagem1.md