Um guia completo para regeneração estática incremental (ISR) com Next.js
Publicados: 2022-03-10Há um ano, o Next.js 9.3 lançou suporte para Static Site Generation (SSG), tornando-o a primeira estrutura híbrida. Eu era um usuário feliz do Next.js há cerca de alguns anos, mas esse lançamento fez do Next.js minha nova solução padrão. Depois de trabalhar extensivamente com o Next.js, entrei para a Vercel para ajudar empresas como Tripadvisor e Washington Post a adotar e dimensionar o Next.js.
Neste artigo, gostaria de explorar uma nova evolução do Jamstack: Regeneração Estática Incremental (ISR) . Abaixo, você encontrará um guia para ISR — incluindo casos de uso, demonstrações e compensações.
O problema com a geração de sites estáticos
A ideia por trás do Jamstack é atraente: páginas estáticas pré-renderizadas que podem ser enviadas para um CDN e disponíveis globalmente em segundos. O conteúdo estático é rápido, resiliente ao tempo de inatividade e indexado imediatamente pelos rastreadores. Mas há alguns problemas.
Se você adotou a arquitetura Jamstack ao construir um site estático em grande escala, pode ficar parado esperando horas para construir seu site. Se você dobrar o número de páginas, o tempo de construção também dobrará. Vamos considerar Target.com. É possível gerar estaticamente milhões de produtos a cada implantação?
Mesmo que cada página fosse gerada estaticamente em 1 ms irreal, ainda levaria horas para reconstruir todo o site . Para grandes aplicativos da Web, a escolha da geração completa de sites estáticos não é um bom começo. Equipes de grande escala precisam de uma solução híbrida, personalizada e mais flexível.
Sistemas de gerenciamento de conteúdo (CMS)
Para muitas equipes, o conteúdo do site é desacoplado do código. O uso de um CMS Headless permite que os editores de conteúdo publiquem alterações sem envolver um desenvolvedor. No entanto, com sites estáticos tradicionais, esse processo pode ser lento.
Considere uma loja de comércio eletrônico com 100.000 produtos. Os preços dos produtos mudam com frequência. Quando um editor de conteúdo altera o preço dos fones de ouvido de US$ 100 para US$ 75 como parte de uma promoção, seu CMS usa um webhook para reconstruir todo o site. Não é viável esperar horas para que o novo preço seja refletido.
Compilações longas com computação desnecessária também podem incorrer em despesas adicionais. Idealmente, seu aplicativo é inteligente o suficiente para entender quais produtos foram alterados e atualizar incrementalmente essas páginas sem precisar de uma reconstrução completa .
Regeneração Estática Incremental (ISR)
O Next.js permite que você crie ou atualize páginas estáticas depois de criar seu site. A Regeneração Estática Incremental (ISR) permite que desenvolvedores e editores de conteúdo usem a geração estática por página, sem a necessidade de reconstruir todo o site . Com o ISR, você pode manter os benefícios da estática enquanto escala para milhões de páginas.
Páginas estáticas podem ser geradas em tempo de execução (sob demanda) em vez de em tempo de construção com ISR. Usando análises, testes A/B ou outras métricas, você está equipado com a flexibilidade de fazer sua própria compensação nos tempos de compilação.
Considere a loja de comércio eletrônico de antes com 100.000 produtos. Com 50 ms realistas para gerar estaticamente cada página de produto, isso levaria quase 2 horas sem ISR . Com ISR, podemos escolher entre:
- Construções mais rápidas
Gere os 1.000 produtos mais populares no momento da compilação. As solicitações feitas a outros produtos serão uma perda de cache e gerarão estaticamente sob demanda: compilações de 1 minuto. - Taxa de acertos de cache mais alta
Gere 10.000 produtos em tempo de compilação, garantindo que mais produtos sejam armazenados em cache antes da solicitação de um usuário: compilações de 8 minutos.
Vejamos um exemplo de ISR para uma página de produto de comércio eletrônico.
Começando
Buscando dados
Se você nunca usou o Next.js antes, recomendo a leitura de Introdução ao Next.js para entender o básico. O ISR usa a mesma API Next.js para gerar páginas estáticas: getStaticProps
. Ao especificar revalidate: 60
, informamos Next.js para usar ISR para esta página.
- Next.js pode definir um tempo de revalidação por página. Vamos defini-lo em 60 segundos.
- A solicitação inicial para a página do produto mostrará a página em cache com o preço original.
- Os dados do produto são atualizados no CMS.
- Quaisquer solicitações para a página após a solicitação inicial e antes de 60 segundos são armazenadas em cache e instantâneas.
- Após a janela de 60 segundos, a próxima solicitação ainda mostrará a página em cache (obstante). Next.js aciona uma regeneração da página em segundo plano .
- Depois que a página for gerada com sucesso, o Next.js invalidará o cache e mostrará a página do produto atualizada. Se a regeneração do plano de fundo falhar, a página antiga permanece inalterada.
// pages/products/[id].js export async function getStaticProps({ params }) { return { props: { product: await getProductFromDatabase(params.id) }, revalidate: 60 } }
Gerando Caminhos
Next.js define quais produtos devem ser gerados em tempo de compilação e quais sob demanda. Vamos gerar apenas os 1.000 produtos mais populares no momento da compilação, fornecendo getStaticPaths
uma lista dos 1.000 principais IDs de produtos.
Precisamos configurar como o Next.js fará o “fallback” ao solicitar qualquer um dos outros produtos após a compilação inicial. Existem duas opções para escolher: blocking
e true
.
-
fallback: blocking
(preferencial)
Quando uma solicitação é feita para uma página que não foi gerada, o Next.js renderiza a página pelo servidor na primeira solicitação. Solicitações futuras servirão o arquivo estático do cache. -
fallback: true
Quando uma solicitação é feita para uma página que não foi gerada, o Next.js servirá imediatamente uma página estática com um estado de carregamento na primeira solicitação. Quando os dados terminarem de carregar, a página será renderizada novamente com os novos dados e será armazenada em cache. Solicitações futuras servirão o arquivo estático do cache.
// pages/products/[id].js export async function getStaticPaths() { const products = await getTop1000Products() const paths = products.map((product) => ({ params: { id: product.id } })) return { paths, fallback: 'blocking' } }
Trocas
O Next.js se concentra principalmente no usuário final. A “melhor solução” é relativa e varia de acordo com o setor, o público e a natureza do aplicativo. Ao permitir que os desenvolvedores alternem entre as soluções sem sair dos limites da estrutura, o Next.js permite que você escolha a ferramenta certa para o projeto.
Renderização do lado do servidor
ISR nem sempre é a solução certa. Por exemplo, o feed de notícias do Facebook não pode mostrar conteúdo obsoleto. Nesse caso, você deseja usar SSR e potencialmente seus próprios cabeçalhos cache-control
com chaves substitutas para invalidar o conteúdo. Como o Next.js é uma estrutura híbrida, você mesmo pode fazer essa troca e permanecer dentro da estrutura.
// You can cache SSR pages at the edge using Next.js // inside both getServerSideProps and API Routes res.setHeader('Cache-Control', 's-maxage=60, stale-while-revalidate');
O SSR e o cache de borda são semelhantes ao ISR (especialmente se estiver usando cabeçalhos de cache stale-while-revalidate
), com a principal diferença sendo a primeira solicitação. Com ISR, o primeiro pedido pode ser garantido estático se pré-renderizado. Mesmo que seu banco de dados fique inativo ou haja um problema de comunicação com uma API, seus usuários ainda verão a página estática veiculada corretamente. No entanto, o SSR permitirá que você personalize sua página com base na solicitação recebida.
Nota : O uso de SSR sem armazenamento em cache pode levar a um desempenho ruim. Cada milissegundo é importante ao bloquear o usuário de ver seu site, e isso pode ter um efeito dramático no seu TTFB (Time to First Byte).
Geração de site estático
O ISR nem sempre faz sentido para sites pequenos. Se o período de revalidação for maior do que o tempo necessário para reconstruir todo o site, você também poderá usar a geração tradicional de site estático.
Renderização do lado do cliente
Se você usa React sem Next.js, está usando renderização do lado do cliente. Seu aplicativo atende a um estado de carregamento, seguido pela solicitação de dados dentro do JavaScript no lado do cliente (por exemplo useEffect
). Embora isso aumente suas opções de hospedagem (já que não há necessidade de servidor), há vantagens e desvantagens.
A falta de conteúdo pré-renderizado do HTML inicial leva a uma otimização de mecanismos de pesquisa (SEO) mais lenta e menos dinâmica. Também não é possível usar CSR com JavaScript desabilitado.
Opções de fallback ISR
Se seus dados puderem ser buscados rapidamente, considere usar fallback: blocking
. Então, você não precisa considerar o estado de carregamento e sua página sempre mostrará o mesmo resultado (independentemente de estar em cache ou não). Se a busca de dados for lenta, fallback: true
permite que você mostre imediatamente um estado de carregamento para o usuário.
ISR: Não apenas cache!
Embora eu tenha explicado o ISR por meio do contexto de um cache, ele foi projetado para persistir suas páginas geradas entre implantações. Isso significa que você pode reverter instantaneamente e não perder suas páginas geradas anteriormente.
Cada implantação pode ser codificada por um ID, que o Next.js usa para persistir as páginas geradas estaticamente. Ao reverter, você pode atualizar a chave para apontar para a implantação anterior, permitindo implantações atômicas. Isso significa que você pode visitar suas implantações imutáveis anteriores e elas funcionarão conforme o esperado.
- Aqui está um exemplo de reversão de código com ISR:
- Você envia o código e obtém um ID de implantação 123.
- Sua página contém um erro de digitação “Smshng Magazine”.
- Você atualiza a página no CMS. Não é necessário reimplantar.
- Uma vez que sua página mostra “Smashing Magazine”, ela é mantida no armazenamento.
- Você envia algum código ruim e implanta o ID 345.
- Você reverte para a ID de implantação 123.
- Você ainda vê “Smashing Magazine”.
Reversões e páginas estáticas persistentes estão fora do escopo do Next.js e dependem do seu provedor de hospedagem. Observe que o ISR difere da renderização do servidor com cabeçalhos Cache-Control
porque, por design, os caches expiram. Eles não são compartilhados entre regiões e serão eliminados ao reverter.
Exemplos de Regeneração Estática Incremental
A Regeneração Estática Incremental funciona bem para e-commerce, páginas de marketing, postagens de blog, mídia apoiada por anúncios e muito mais.
- Demonstração de comércio eletrônico
O Next.js Commerce é um kit inicial completo para sites de comércio eletrônico de alto desempenho. - Demonstração de reações do GitHub
Reaja ao problema original do GitHub e veja o ISR atualizar a página de destino gerada estaticamente. - Demonstração de tweets estáticos
Este projeto é implantado em 30 segundos, mas pode gerar estaticamente 500 milhões de tweets sob demanda usando ISR.
Aprenda Next.js hoje
Desenvolvedores e grandes equipes estão escolhendo o Next.js por sua abordagem híbrida e capacidade de gerar páginas de forma incremental sob demanda. Com o ISR, você obtém os benefícios da estática com a flexibilidade da renderização do servidor. O ISR funciona fora da caixa usando o next start
.
Next.js foi projetado para adoção gradual. Com o Next.js, você pode continuar usando seu código existente e adicionar tanto (ou tão pouco) React quanto precisar. Ao começar pequeno e adicionar mais páginas de forma incremental, você pode evitar o descarrilamento do trabalho do recurso, evitando uma reescrita completa. Saiba mais sobre o Next.js — e boa codificação, pessoal!
Leitura adicional
- Introdução ao Next.js
- Comparando métodos de estilo no Next.js
- Como criar um servidor GraphQL usando as rotas da API Next.js