Usando Ganchos de Reação SWR com a Regeneração Estática Incremental (ISR) do Next.js

Publicados: 2022-03-10
Resumo rápido ↬ Quando combinado com as rotas de API ISR e Next.js, o SWR pode ser usado para criar uma experiência de usuário responsiva. Neste artigo, Sam Poder explica o que é SWR, onde usá-lo (e onde não) e como construir um site usando a Regeneração Estática Incremental.

Se você já usou a Regeneração Estática Incremental (ISR) com Next.js, pode ter enviado dados obsoletos para o cliente. Isso ocorre quando você está revalidando a página no servidor. Para alguns sites isso funciona, mas para outros (como o Scrapbook do Hack Club, um site criado por @lachlanjc que ajudo a manter), o usuário espera que os dados sejam mantidos atualizados.

A primeira solução que vem à mente pode ser simplesmente renderizar as páginas do lado do servidor, garantindo que o cliente sempre receba os dados mais atualizados. No entanto, buscar grandes blocos de dados antes da renderização pode retardar o carregamento inicial da página. A solução usada no Scrapbook foi usar a biblioteca SWR de ganchos do React para atualizar a página em cache do servidor com a busca de dados do lado do cliente . Essa abordagem garante que os usuários ainda tenham uma boa experiência, que o site seja rápido e que os dados sejam mantidos atualizados.

Conheça a SWR

SWR é uma biblioteca React Hooks construída pela Vercel, o nome vem do termo stale-while-revalidate. Como o nome sugere, seu cliente receberá dados obsoletos/antigos enquanto os dados mais atualizados estão sendo buscados (revalidando) por meio de SWR no lado do cliente. O SWR não revalida os dados apenas uma vez, no entanto, você pode configurar o SWR para revalidar os dados em um intervalo, quando a guia recupera o foco, quando um cliente se reconecta à Internet ou programaticamente.

Quando emparelhado com as rotas de API do ISR e Next.js, o SWR pode ser usado para criar uma experiência de usuário responsiva . O cliente recebe primeiro a página gerada estaticamente em cache (gerada com getStaticProps() ), em segundo plano o servidor também inicia o processo de revalidação dessa página (leia mais aqui). Esse processo parece rápido para o cliente e agora ele pode ver o conjunto de dados, mas pode estar um pouco desatualizado. Depois que a página é carregada, uma solicitação de busca é feita para uma rota da API Next.js que retorna os mesmos dados que foram gerados com getStaticProps() . Quando essa solicitação for concluída (supondo que tenha sido bem-sucedida), o SWR atualizará a página com esses novos dados.

Vamos agora olhar para o Scrapbook e como isso ajudou a resolver o problema de ter dados obsoletos na página . O óbvio é que agora, o cliente recebe uma versão atualizada. O mais interessante, porém, é o impacto na velocidade do nosso lado. Quando medimos a velocidade através do Lighthouse, obtemos um índice de velocidade de 1,5 segundos para a variante ISR + SWR do site e 5,8 segundos para a variante Server Side Rendering (mais um aviso sobre o tempo de resposta inicial do servidor). Esse é um contraste bastante forte entre os dois (e foi perceptível ao carregar as páginas também). Mas há também uma compensação, na página Server Side Rendered o usuário não teve o layout do site alterado após alguns segundos com novos dados chegando. Embora eu acredite que o Scrapbook lide bem com essa atualização, é uma consideração importante quando projetar a experiência do usuário.

Mais depois do salto! Continue lendo abaixo ↓

Onde usar SWR (e onde não usar)

O SWR pode ser implementado em vários lugares, aqui estão algumas categorias de sites onde o SWR se encaixaria perfeitamente:

  • Sites com dados ao vivo que exigem atualização rápida.
    Exemplos de tais sites seriam sites de resultados esportivos e rastreamento de voos. Ao construir esses sites, você deve usar a opção revalidar no intervalo com uma configuração de intervalo baixo (um a cinco segundos).
  • Sites com estilo de feed de atualizações ou posts que atualizam em tempo real.
    O exemplo clássico disso seriam os sites de notícias que possuem blogs ao vivo de eventos como eleições. Outro exemplo seria o Scrapbook acima mencionado também. Nesse caso, você provavelmente também desejaria usar a opção revalidar no intervalo, mas com uma configuração de intervalo mais alta (trinta a sessenta segundos) para economizar no uso de dados e evitar chamadas de API desnecessárias.
  • Sites com atualizações de dados mais passivas, que as pessoas mantêm muito abertas em segundo plano.
    Exemplos desses sites seriam páginas meteorológicas ou nas páginas de números de casos COVID-19 de 2020. Essas páginas não são atualizadas com tanta frequência e, portanto, não precisam da revalidação constante dos dois exemplos anteriores. No entanto, ainda melhoraria a experiência do usuário para que os dados fossem atualizados. Nesses casos, eu recomendaria revalidar a data em que a guia recupera o foco e quando um cliente se reconecta à internet, isso significa que se uma pessoa retornar ansiosamente à torneira esperando que tenha havido apenas um pequeno aumento nos casos de COVID, obter esses dados rapidamente.
  • Sites com pequenos dados com os quais os usuários podem interagir.
    Pense no botão de inscrição do Youtube, quando você clica em inscrever-se, você quer ver essa contagem mudar e sentir que fez a diferença. Nesses casos, você pode revalidar os dados programaticamente usando SWR para buscar a nova contagem e atualizar o valor exibido.

Uma coisa a notar é que tudo isso pode ser aplicado com ou sem ISR.

Claro que existem alguns lugares onde você não vai querer usar SWR ou usar SWR sem ISR. SWR não é muito útil se seus dados não estão mudando ou mudam muito raramente e, em vez disso, podem obstruir suas solicitações de rede e usar os dados do usuário móvel. O SWR pode trabalhar com páginas que requerem autenticação, no entanto, você desejará usar a renderização do lado do servidor nesses casos e não a regeneração estática incremental.

Usando SWR com Next.js e regeneração estática incremental

Agora que exploramos a teoria dessa estratégia, vamos explorar como a colocamos em prática. Para isso vamos construir um site que mostra quantos táxis estão disponíveis em Cingapura (onde moro!) usando essa API fornecida pelo governo.

Estrutura do projeto

Nosso projeto funcionará tendo três arquivos:

  • lib/helpers.js
  • pages/index.js (nosso arquivo frontend)
  • pages/api/index.js (nosso arquivo de API)

Nosso arquivo helpers exportará uma função ( getTaxiData ) que buscará os dados da API externa e os retornará em um formato apropriado para nosso uso. Nosso arquivo API importará essa função e definirá sua exportação padrão para uma função de manipulador que chamará a função getTaxiData e a retornará, isso significa que enviar uma solicitação GET para /api retornará nossos dados.

Precisaremos dessa capacidade para que o SWR faça a busca de dados do lado do cliente. Por fim, em nosso arquivo frontend importaremos getTaxiData e o usaremos em getStaticProps , seus dados serão passados ​​para a função de exportação padrão do nosso arquivo frontend que renderizará nossa página React. Fazemos tudo isso para evitar a duplicação de código e garantir a consistência em nossos dados. Que bocado, vamos começar a programação agora.

O arquivo de ajudantes

Começaremos criando a função getTaxiData em lib/helpers.js :

 export async function getTaxiData(){ let data = await fetch("https://api.data.gov.sg/v1/transport/taxi-availability").then(r => r.json()) return {taxis: data.features.properties[0].taxi_count, updatedAt: data.features.properties[0].timestamp} }

O arquivo de API

Em seguida, criaremos a função do manipulador em api/index.js , além de importar a função getTaxiData :

 import { getTaxiData } from '../../lib/helpers' export default async function handler(req, res){ res.status(200).json(await getTaxiData()) }

Não há nada aqui exclusivo para SWR ou ISR, além da estrutura do projeto acima mencionada. Esse material começa agora em index.js !

O arquivo de front-end

A primeira coisa que queremos fazer é criar nossa função getStaticProps ! Esta função irá importar nossa função getTaxiData , usá-la e então retornar os dados com alguma configuração adicional.

 export async function getStaticProps(){ const { getTaxiData } = require("../lib/helpers") return { props: (await getTaxiData()), revalidate: 1 } }

Eu gostaria de focar na chave de revalidação em nosso objeto retornado. Esta chave praticamente permite a Regeneração Estática Incremental. Ele informa ao seu host que a cada segundo que gera novamente a página estática é uma opção disponível, essa opção é acionada em segundo plano quando um cliente visita sua página. Você pode ler mais sobre Regeneração Estática Incremental (ISR) aqui.

Agora é hora de usar SWR! Vamos importá-lo primeiro:

 import useSWR from 'swr'

Vamos usar SWR em nossa função de renderização React, então vamos criar essa função:

 export default function App(props){ }

Estamos recebendo os adereços de getStaticProps . Agora estamos prontos para configurar o SWR:

 const fetcher = (...args) => fetch(...args).then(res => res.json()) const { data } = useSWR("/api", fetcher, {fallbackData: props, refreshInterval: 30000})

Vamos quebrar isso. Em primeiro lugar, definimos o fetcher. Isso é exigido pelo SWR como um argumento para que ele saiba como buscar seus dados, pois diferentes estruturas etc. podem ter configurações diferentes. Nesse caso, estou usando a função fornecida na página de documentos do SWR. Em seguida, chamamos o gancho useSWR , com três argumentos: o caminho para buscar os dados, a função fetcher e, em seguida, um objeto de opções.

Nesse objeto de options , especificamos duas coisas:

  1. Os dados de fallback;
  2. O intervalo no qual o SWR deve revalidar os dados.

A opção de dados de fallback é onde fornecemos os dados obtidos de getStaticProps , o que garante que os dados sejam visíveis desde o início. Por fim, usamos a desestruturação de objetos para extrair os dados do gancho.

Para finalizar, renderizaremos esses dados com um JSX bem básico:

 return <div>As of {data.updatedAt}, there are {data.taxis} taxis available in Singapore!</div>

E, nós fizemos isso! Lá temos um exemplo muito básico de usar SWR com Regeneração Estática Incremental. (A fonte do nosso exemplo está disponível aqui.)

Se você se deparar com dados obsoletos com ISR, você sabe para quem ligar: SWR.

Leitura adicional no SmashingMag

  • Biblioteca SWR React Hooks
  • Uma introdução ao SWR: React Hooks for Remote Data Fetching, Ibrahima Ndaw
  • ISR vs DPR: Grandes Palavras, Explicação Rápida, Cassidy Williams
  • Estilo global versus local em Next.js, Alexander Dubovoj
  • Roteamento do lado do cliente em Next.js, Adebiyi Adedotun Lukman