O cache de rotas do Astro armazena a resposta renderizada de uma página sob demanda, de modo que um acerto de cache pula a renderização. O EmDash fornece tags de cache para o conteúdo que uma página renderiza e invalida essas tags quando o conteúdo muda. As páginas podem permanecer em cache por dias, enquanto uma publicação normalmente se torna visível em questão de segundos.
O cache de objetos armazena resultados de consultas e continua renderizando cada página. Com um provedor de cache configurado, as renderizações anônimas pulam o cache de objetos e leem do banco de dados, de modo que uma renderização que preenche novamente uma página invalidada não venha de um snapshot mais antigo (veja O que é armazenado em cache). O cache de rotas então atende os visitantes anônimos, e o cache de objetos acelera principalmente as renderizações para editores conectados.
Escolher um provedor de cache
O cache de rotas precisa de um provedor de cache. Use o que corresponde à sua implantação:
| Implantação | Provedor | Importar de |
|---|---|---|
| Node.js | memoryCache() | astro/config |
| Cloudflare | cacheCloudflare() | @astrojs/cloudflare/cache |
memoryCache() mantém as entradas na memória do processo do servidor. cacheCloudflare() é um provedor de CDN: ele armazena as respostas no Cloudflare Workers Cache, e um acerto de cache nunca executa o Worker. Os adaptadores do Astro para Netlify e Vercel também incluem provedores de CDN; veja Provedores de cache dos adaptadores. O EmDash invalida por meio da API cache.invalidate() do Astro, independente do provedor, então suas tags funcionam com qualquer provedor. Diferenças entre provedores descreve o comportamento que depende do provedor. O astro dev nunca usa cache, então teste o cache com um build de produção.
Configurar o cache de rotas
Registre o provedor e declare quais rotas podem ser armazenadas em cache, por quanto tempo e sob quais tags. Este exemplo usa o provedor da Cloudflare; no Node, use cache: { provider: memoryCache() } com memoryCache importado de astro/config:
import { defineConfig } from "astro/config";
import { cacheCloudflare } from "@astrojs/cloudflare/cache";
export default defineConfig({
// ...seu output, adaptador e integrações existentes
cache: {
provider: cacheCloudflare(),
},
routeRules: {
"/": { maxAge: 86_400, swr: 604_800, tags: ["posts", "pages", "all"] },
"/blog": { maxAge: 86_400, swr: 604_800, tags: ["posts", "all"] },
"/blog/[slug]": { maxAge: 86_400, swr: 604_800, tags: ["posts", "all"] },
"/sitemap.xml": { maxAge: 86_400, swr: 604_800, tags: ["posts", "pages", "all"] },
"/sitemap-[collection].xml": { maxAge: 86_400, swr: 604_800, tags: ["posts", "pages", "all"] },
},
});
maxAgeé por quanto tempo o cache serve a entrada antes de a rota ser renderizada novamente. O EmDash invalida entradas obsoletas ao publicar (veja abaixo), mas uma invalidação pode falhar, entãomaxAgetambém limita por quanto tempo uma página pode ficar obsoleta, mais uma resposta obsoleta enquantoswra revalida. Confira Diferenças entre provedores antes de escolher um valor longo.swrpermite que o cache continue servindo uma entrada obsoleta enquanto a revalida em segundo plano, de modo que os visitantes raramente esperam por uma renderização depois que a página está em cache.tagsdão nome à entrada para a invalidação. Marque cada rota com as coleções que ela renderiza, usando os nomes das coleções: a invalidação integrada do EmDash usa nomes de coleções, então as tags correspondentes são invalidadas automaticamente. Uma tag extra abrangente em cada rota em cache (aquiall, que não é um nome de coleção, portanto o EmDash nunca a invalida por conta própria) funciona como chave de emergência: invalidá-la, por exemplo comcontext.cache.invalidate({ tags: ["all"] })em um endpoint que você mesmo proteja, limpa tudo de uma vez.
Os helpers de consulta também retornam um cacheHint que você pode passar para Astro.cache.set() dentro da página. Suas tags nomeiam a entrada exata (getEmDashEntry), a coleção (getEmDashCollection) ou o recurso de chrome (getMenuWithCacheHint, getSiteSettingsWithCacheHint, getTaxonomyTermsWithCacheHint, getWidgetAreaWithCacheHint). Essas são as mesmas tags que o EmDash invalida nas gravações, então uma página que repassa seus hints é invalidada quando uma entrada ou um recurso de chrome que ela renderiza é gravado, inclusive aqueles que sua regra de rota não nomeia:
---
import { getEmDashEntry } from "emdash";
const { slug } = Astro.params;
if (!slug) return Astro.rewrite("/404");
const { entry, cacheHint } = await getEmDashEntry("posts", slug);
if (Astro.cache?.enabled) Astro.cache.set(cacheHint);
---
Astro.cache.set() é mesclado com a regra de rota, e as tags se acumulam entre as chamadas. Os cache hints carregam tags, mas não maxAge, então a regra de rota decide por quanto tempo uma página fica em cache.
Dê a cada rota pública uma regra explícita. As regras correspondem ao caminho da requisição, então liste suas rotas públicas individualmente: um parâmetro rest na raiz do site, como /[...slug], também corresponde às rotas de administração e de API em /_emdash/.
A invalidação na publicação é integrada
As rotas da API de conteúdo do EmDash invalidam o cache de rotas sempre que o conteúdo publicado muda: publicar, cancelar a publicação, excluir ou restaurar uma entrada da lixeira e salvar alterações que chegam à entrada publicada invalidam as tags [collection, id]. Criar ou duplicar uma entrada não invalida nada, porque a nova entrada é um rascunho. Qualquer regra de rota marcada com o nome da coleção (como acima) costuma, portanto, ser atualizada em poucos segundos após uma publicação, mesmo com um maxAge longo.
O chrome do site também está coberto: salvar as configurações do site invalida emdash:settings, edições de menu invalidam emdash:menu:{name}, e gravações de taxonomias e áreas de widgets invalidam suas tags correspondentes emdash:taxonomy:{name} / emdash:widget-area:{name}. As páginas recebem essas tags automaticamente quando usam o cacheHint de getMenuWithCacheHint(), getSiteSettingsWithCacheHint(), getTaxonomyTermsWithCacheHint() ou getWidgetAreaWithCacheHint().
As tags de menu cobrem apenas as edições do menu. Publicar, cancelar a publicação, enviar para a lixeira ou restaurar uma entrada para a qual um menu aponta, ou alterar o slug de uma entrada vinculada ou de um termo de taxonomia, não invalida a tag do menu. Uma página que exibe o menu incorpora essa alteração quando suas tags também nomeiam essa entrada, sua coleção ou a taxonomia desse termo e, caso contrário, quando a página expira.
Criar, editar ou excluir um redirecionamento invalida a página em cache no caminho de origem do redirecionamento, com e sem barra final, para que o redirecionamento seja aplicado na próxima requisição.
Restaurar uma revisão anterior e alterações em assinaturas de autor, na biblioteca de mídia e nos comentários não invalidam nada. As páginas em cache afetadas por elas são atualizadas quando expiram ou quando a entrada que as renderiza é salva novamente. A publicação agendada invalida as tags das entradas publicadas somente na Cloudflare; veja Diferenças entre provedores.
É também por isso que a convenção de tags importa: o EmDash invalida nomes de coleções, ids de entradas e as tags de chrome emdash:*. Se suas regras de rota usarem outros nomes de tag, a invalidação integrada não vai correspondê-los e as entradas obsoletas sobreviverão até que maxAge expire.
Manter respostas fora do cache
As regras de rota correspondem ao caminho da requisição, então também se aplicam a respostas que você não quer armazenar com um TTL longo. O EmDash mantém automaticamente fora do cache de rotas as respostas renderizadas para um usuário conectado, as respostas enviadas com Cache-Control: private ou no-store e também as respostas 404. As demais respostas de erro e seus próprios redirecionamentos de middleware são responsabilidade do template, que os exclui por requisição com Astro.cache.set(false).
Astro.cache.set(false) só vale até a próxima chamada de Astro.cache.set(). Um layout é renderizado depois do frontmatter da página, então um layout que define um cache hint reativa o cache de uma página que o havia desativado. Passe a exclusão para o layout (por exemplo, como prop) e pule suas chamadas a Astro.cache.set() quando ela estiver definida.
Links de pré-visualização e de edição são tratados automaticamente
O middleware do EmDash exclui essas respostas do cache de rotas por conta própria, então nenhum código de template é necessário: requisições com um token ?_preview= (válido ou não, porque essas URLs são por token e, caso contrário, um rascunho em cache continuaria acessível depois que o token expirasse) e respostas com a barra de ferramentas do editor injetada. Com toolbar: "client", o mesmo vale para as URLs ?_edit. As respostas de pré-visualização válidas e as respostas com a barra de ferramentas injetada também são marcadas com Cache-Control: private, no-store para navegadores e CDNs a jusante.
Respostas de erro
O EmDash mantém todo 404 fora do cache de rotas, de modo que publicar mais tarde uma entrada que estava ausente a exibe imediatamente. Outras respostas de erro, como um 500 renderizado em uma rota em cache, herdam o TTL da regra. Exclua-as com Astro.cache.set(false).
Redirecionamentos no middleware
Middleware que interrompe o fluxo com um redirecionamento (por exemplo, a canonicalização do host) deve se excluir com context.cache?.set(false). Caso contrário, o redirecionamento é armazenado em cache com o TTL da regra de rota e, em um provedor de CDN que não separa as entradas de cache por nome de host, pode ser servido também a requisições para o host canônico, causando um loop de redirecionamento instantâneo. Use encadeamento opcional: context.cache é undefined em algumas respostas, como a página 404 de uma URL que não corresponde a nenhuma rota.
Editores e páginas em cache
O cache de rotas armazena uma variante compartilhada por URL, e sua chave de cache ignora cookies, então um acerto de cache nunca reflete a sessão de um editor. Com a barra de ferramentas renderizada no servidor por padrão, um editor que navega pelo site público normalmente recebe a variante anônima em cache, sem a barra de ferramentas, e o cookie emdash-edit-mode não tem efeito em uma URL em cache. Uma página renderizada para um editor conectado nunca é armazenada no cache compartilhado; o próximo visitante anônimo a preenche.
Defina toolbar: "client" em sites que usam cache de rotas. Um pequeno script então mostra o botão de edição para editores conectados nas páginas em cache, e a visualização de edição é carregada de uma URL ?_edit que é sempre renderizada do zero. Os links de pré-visualização ignoram o cache em ambos os modos.
Diferenças entre provedores
Node.js com memoryCache()
- Cada processo do servidor mantém seu próprio cache, e uma invalidação só limpa o processo que tratou a gravação. Se você executa vários processos ou instâncias, os demais continuam servindo suas páginas em cache até que
maxAgeexpire. - Uma reinicialização esvazia o cache.
memoryCache()só armazena uma resposta que tenhamaxAge, então uma rota sem regra nunca é armazenada em cache, mesmo que a página chameAstro.cache.set()com um cache hint.- A publicação agendada não invalida o cache de rotas no Node. Uma página que lista uma entrada agendada só a exibe quando sua cópia em cache expira, então mantenha
maxAgecurto nas rotas que listam conteúdo agendado.
Cloudflare com cacheCloudflare()
- O provedor grava os cabeçalhos de resposta
Cloudflare-CDN-Cache-ControleCache-Tag. O Workers Cache consome ambos; os clientes nunca os veem, e qualquer cabeçalhoCache-Controlque suas páginas definam para os navegadores não é afetado. - Quando um provedor de cache está configurado, o adaptador
@astrojs/cloudflarehabilita o Workers Cache automaticamente: o build grava"cache": { "enabled": true }na configuração do Wrangler gerada, que owrangler deployutiliza. - Uma rota sem regra é marcada como
no-store, mas somente se nada chamarAstro.cache.set()durante a renderização. Um cache hint semmaxAge, como os degetSiteSettingsWithCacheHint()egetMenuWithCacheHint(), produzCloudflare-CDN-Cache-Control: publicsem tempo de vida, então o Workers Cache recorre às suas durações de cache padrão (2 horas para uma resposta200). Se o seu layout define esses hints, toda página que usa o layout passa a poder ser armazenada em cache, com ou sem regra. - Por padrão, a versão do Worker faz parte da chave de cache, então cada implantação começa com um cache vazio e as primeiras requisições depois dela são renderizadas no Worker. Para manter as entradas entre implantações, defina
"cache": { "enabled": true, "cross_version_cache": true }na sua configuração do Wrangler (veja Cache entre versões). As alterações de template então só aparecem quando as entradas afetadas expiram ou são invalidadas. - A publicação agendada invalida as tags das entradas que publica a partir do Cron Trigger.
Limites de taxa de purge
O provedor da Cloudflare invalida fazendo o purge do Workers Cache. Os purges do Workers Cache sempre usam os limites de purge do plano Free da Cloudflare, qualquer que seja o plano da sua conta: 5 requisições por minuto com um burst de 25, por conta (veja Limites de taxa de purge). A maioria das gravações de conteúdo custa uma requisição de purge cada: salvamentos que alteram o conteúdo publicado (incluindo salvamentos automáticos em coleções que salvam diretamente na entrada publicada), publicar, cancelar a publicação, excluir, restaurar, agendar e atribuir termos de taxonomia a uma entrada, além de toda edição de configurações, menus, taxonomias ou widgets. A gravação de um redirecionamento custa uma requisição de purge por variante do caminho de origem, ou seja, até quatro quando a origem de um redirecionamento muda.
Um purge limitado por taxa falha sem erro no administrador, e as páginas afetadas mantêm sua versão em cache até que maxAge expire. Durante edições em massa, ou com vários editores trabalhando ao mesmo tempo, escolha um maxAge que você possa aceitar como pior caso de conteúdo obsoleto.
O cache do navegador é separado
O cache de rotas pode ter TTLs longos porque o EmDash o invalida; os caches dos navegadores não são invalidados. Os hints do EmDash fornecem tags de purge, não validadores Last-Modified automáticos nem o cabeçalho implícito Cache-Control: no-cache do Astro. O horário de modificação de uma única entrada não cobre configurações, listas relacionadas nem entradas excluídas, então usá-lo como validador de página pode manter um corpo desatualizado por meio de respostas 304 condicionais.
Defina o cache do navegador com Astro.response.headers.set("Cache-Control", ...): use no-cache para uma verificação nova a cada visita, ou uma vida útil curta (minutos, não dias). Para habilitar requisições condicionais, forneça seu próprio hint lastModified, cujo carimbo de data/hora avance sempre que qualquer dependência da resposta mudar.
Para a data de modificação exibida de uma entrada, use entry.data.updatedAt em vez de cacheHint.lastModified, que o EmDash não preenche automaticamente.