Transcript

00:00:00(música animada) - Olá a todos.
00:00:06Meu nome é Aurora.
00:00:07Sou desenvolvedora web da Noruega.
00:00:09Trabalho como consultora na Crane Consulting e estou ativamente desenvolvendo com o Next.js app router no meu projeto de consultoria atual.
00:00:16Hoje,
00:00:17vou ensinar padrões de composição,
00:00:19cache e arquitetura no Next.js moderno que ajudarão a garantir escalabilidade e desempenho.
00:00:24Primeiro,
00:00:24vamos relembrar o conceito mais fundamental para esta palestra: renderização estática e dinâmica.
00:00:30Encontramos ambos no Next.js app router.
00:00:33A renderização estática nos permite criar sites mais rápidos porque o conteúdo pré-renderizado pode ser armazenado em cache e distribuído globalmente,
00:00:39garantindo que os usuários o acessem mais rapidamente.
00:00:42Por exemplo, o site da Next.js Conf.
00:00:46A renderização estática reduz a carga do servidor porque o conteúdo não precisa ser gerado para cada solicitação do usuário.
00:00:51O conteúdo pré-renderizado também é mais fácil para os rastreadores de mecanismos de busca indexarem,
00:00:56pois já está disponível no carregamento da página.
00:00:58A renderização dinâmica,
00:00:59por outro lado,
00:01:00permite que nossa aplicação exiba dados em tempo real ou frequentemente atualizados.
00:01:05Também nos permite servir conteúdo personalizado,
00:01:07como painéis e perfis de usuário.
00:01:09Por exemplo, o painel da Vercel.
00:01:12Com a renderização dinâmica,
00:01:13podemos acessar informações que só podem ser conhecidas no momento da solicitação.
00:01:16Neste caso,
00:01:17qual usuário está acessando seu painel,
00:01:19que sou eu.
00:01:20Existem certas APIs que podem fazer com que uma página seja renderizada dinamicamente.
00:01:25O uso das props params e search params passadas para as páginas ou seus hooks equivalentes causará a renderização dinâmica.
00:01:32No entanto,
00:01:32com params,
00:01:33podemos predefinir um conjunto de páginas pré-renderizadas usando static params genéricos,
00:01:36e também podemos armazenar em cache as páginas à medida que são geradas pelos usuários.
00:01:40Além disso,
00:01:41a leitura de cookies e cabeçalhos de requisição de entrada fará com que a página opte pela renderização dinâmica.
00:01:46Ao contrário de params,
00:01:47tentar armazenar em cache ou pré-renderizar algo usando cabeçalhos ou cookies causará erros durante a compilação,
00:01:52porque essa informação não pode ser conhecida antecipadamente.
00:01:56Por fim,
00:01:56usar fetch com uma configuração de cache de dados no store também forçará a renderização dinâmica.
00:02:00Então,
00:02:01estas são algumas,
00:02:02há mais algumas APIs que podem causar renderização dinâmica,
00:02:04mas estas são as que mais comumente encontramos.
00:02:06Em versões anteriores do Next,
00:02:08uma página seria renderizada como totalmente estática ou totalmente dinâmica.
00:02:13Uma única API dinâmica em uma página fará com que a página inteira opte pela renderização dinâmica.
00:02:17Por exemplo,
00:02:18fazer uma simples verificação de autenticação para o valor de um cookie.
00:02:20Ao utilizar componentes de servidor React com Suspense,
00:02:23podemos transmitir conteúdo dinâmico,
00:02:24como um banner de boas-vindas personalizado ou recomendações,
00:02:27à medida que ficam prontos,
00:02:28e fornecer apenas fallbacks com Suspense enquanto exibimos conteúdo estático,
00:02:32como um boletim informativo.
00:02:34No entanto,
00:02:34ao adicionar vários componentes assíncronos em uma página dinâmica,
00:02:38como um produto em destaque,
00:02:39eles também seriam executados no momento da solicitação,
00:02:42mesmo que não dependessem de APIs dinâmicas.
00:02:45Então,
00:02:45para evitar o bloqueio do carregamento inicial da página,
00:02:48suspenderíamos e transmitiríamos esses componentes também,
00:02:51fazendo trabalho extra,
00:02:52criando esqueletos e nos preocupando com coisas como o deslocamento cumulativo de layout.
00:02:56No entanto,
00:02:57as páginas são frequentemente uma mistura de conteúdo estático e dinâmico.
00:03:01Por exemplo,
00:03:02um aplicativo de e-commerce que depende de informações do usuário,
00:03:05mas ainda contém principalmente dados estáticos.
00:03:07Ser forçado a escolher entre eles,
00:03:09entre estático ou dinâmico,
00:03:11causa muito processamento redundante no servidor para conteúdo que nunca ou muito raramente muda e não é ideal para o desempenho.
00:03:19Então,
00:03:20para resolver este problema,
00:03:21na Next.js Conf do ano passado,
00:03:23a diretiva use cache foi anunciada.
00:03:26E este ano,
00:03:26como vimos na keynote,
00:03:28está disponível no Next.js 16.
00:03:30Então,
00:03:31com use cache,
00:03:31as páginas não serão mais forçadas à renderização estática ou dinâmica.
00:03:36Elas podem ser ambas.
00:03:37E o Next.js não precisa mais adivinhar o que é uma página com base em se ela acessa coisas como params.
00:03:43Tudo é dinâmico por padrão e use cache nos permite optar explicitamente pelo cache.
00:03:47Use cache permite o cache composable.
00:03:51Podemos marcar uma página,
00:03:52um componente React ou uma função como armazenável em cache.
00:03:55Aqui,
00:03:56podemos realmente armazenar em cache o componente de produtos em destaque porque ele não precisa da requisição e processamento e não usa APIs dinâmicas.
00:04:03E esses segmentos em cache podem ser pré-renderizados e incluídos como parte do shell estático com pré-renderização parcial,
00:04:09o que significa que os produtos em destaque agora estão disponíveis no carregamento da página e não precisam ser transmitidos.
00:04:14Então,
00:04:15agora que temos esse conhecimento de base importante,
00:04:18vamos fazer uma demonstração.
00:04:19Uma melhoria de uma base de código com problemas comuns frequentemente encontrados em aplicativos Next.js.
00:04:24Isso inclui prop drilling profundo,
00:04:25dificultando a manutenção e refatoração de recursos,
00:04:28JavaScript redundante no lado do cliente e componentes grandes com múltiplas responsabilidades,
00:04:32e falta de renderização estática,
00:04:33levando a custos adicionais de servidor e desempenho degradado.
00:04:36Então, sim, vamos começar.
00:04:37E me dê um segundo aqui.
00:04:50Certo, ótimo.
00:04:54Então, este é um aplicativo muito simples.
00:04:56É inspirado em uma plataforma de e-commerce.
00:04:59E deixe-me fazer uma demonstração inicial aqui.
00:05:01Então, posso carregar esta página.
00:05:03Tenho algum conteúdo como este produto em destaque.
00:05:06Tenho categorias em destaque, diferentes dados de produtos.
00:05:09Há também esta página "Navegar em Tudo" aqui,
00:05:13onde posso ver todos os produtos da plataforma e navegar entre eles.
00:05:20Depois,
00:05:20temos esta página "Sobre" aqui,
00:05:22que é apenas estática.
00:05:24Também posso fazer login como usuário.
00:05:27E isso me conectará ao meu usuário.
00:05:30E também obter conteúdo personalizado no meu painel aqui.
00:05:33Como,
00:05:34por exemplo,
00:05:34produtos recomendados ou estes descontos personalizados aqui.
00:05:38Então, percebam que há uma boa mistura.
00:05:42Ah, também mais uma página que esqueci de mostrar.
00:05:45A página do produto, a mais importante.
00:05:47Também aqui,
00:05:48podemos ver informações do produto e depois salvá-lo se quisermos para o nosso usuário.
00:05:52Então,
00:05:52percebam que há uma boa mistura de conteúdo estático e dinâmico neste aplicativo por causa de todos os nossos recursos dependentes do usuário.
00:05:59Vamos também dar uma olhada no código, que estaria aqui.
00:06:05Então, estou usando o app router aqui, claro, no Next.js 16.
00:06:08Tenho todas as minhas diferentes páginas,
00:06:10como a página "Sobre",
00:06:11a página "Tudo",
00:06:12nossa página de produto.
00:06:13Também tenho...
00:06:14estou usando feature slicing aqui para manter minha pasta app limpa..
00:06:17Tenho diferentes componentes e consultas conversando com meu banco de dados com Prisma.
00:06:23Então, sim, e eu propositalmente desacelerei tudo isso.
00:06:25É por isso que temos esta etapa de carregamento realmente longa,
00:06:28apenas para que possamos ver mais facilmente o que está acontecendo.
00:06:31Então,
00:06:31os problemas comuns que queríamos resolver aqui e que realmente temos nesta aplicação eram o prop drilling,
00:06:37dificultando a manutenção e refatoração de recursos,
00:06:39excesso de JavaScript no lado do cliente e falta de renderização estática,
00:06:43levando a custos adicionais de servidor e desempenho integrado.
00:06:47Então,
00:06:47o objetivo desta demonstração é basicamente apenas melhorar este aplicativo com alguns padrões inteligentes de composição,
00:06:54cache e arquitetura para corrigir esses recursos comuns e torná-lo mais rápido,
00:06:58mais escalável e mais fácil de manter.
00:07:01Então, vamos começar com isso.
00:07:02O primeiro problema que queremos corrigir está realmente relacionado ao prop drilling.
00:07:05E isso seria aqui na página.
00:07:10Percebam que aqui, tenho esta variável loggedIn no topo.
00:07:15E vocês podem ver que estou passando-a para alguns componentes.
00:07:17Na verdade,
00:07:17ela foi passada por vários níveis até este banner pessoal.
00:07:20Então,
00:07:20isso vai dificultar a reutilização de coisas aqui porque sempre temos essa dependência de loggedIn para o nosso banner de boas-vindas.
00:07:28Então,
00:07:28com os componentes de servidor,
00:07:30a melhor prática seria realmente empurrar a busca de dados para os componentes que estão usando isso e resolver as promessas mais profundamente na árvore.
00:07:37E para que isso seja autenticado,
00:07:39desde que esteja usando fetch ou algo como React cache,
00:07:42podemos duplicar várias chamadas disso e podemos simplesmente reutilizá-lo onde quisermos dentro de nossos componentes.
00:07:48Então, seria totalmente bom reutilizar.
00:07:51Então,
00:07:51agora podemos realmente mover isso para a seção personalizada aqui.
00:07:54E não vamos mais precisar desta prop.
00:07:57E apenas colocá-lo diretamente — opa — aqui.
00:08:01E não vamos mais precisar passar isso.
00:08:04E como estamos agora movendo esta chamada assíncrona para a seção personalizada,
00:08:07não estamos mais bloqueando a página.
00:08:09Podemos ir em frente e suspender isso com um simples Suspense aqui.
00:08:13E não vamos precisar deste fallback.
00:08:16Quanto ao banner de boas-vindas,
00:08:19suponho que faremos o mesmo.
00:08:22Mas tentar usar — obter a variável ou valor loggedIn aqui,
00:08:26não funciona,
00:08:27certo?
00:08:27Porque este é um componente cliente.
00:08:29Então, precisamos resolver isso de uma maneira diferente.
00:08:30E vamos usar um padrão bem inteligente aqui para resolver isso.
00:08:33Na verdade,
00:08:34vamos para o layout e envolver tudo aqui com um Auth Provider.
00:08:39Então,
00:08:39vou apenas colocar isso em torno de todo o meu aplicativo aqui e obter esta variável loggedIn aqui.
00:08:45E eu definitivamente não quero bloquear todo o meu root layout.
00:08:48Vamos em frente e remover o await aqui.
00:08:50E apenas passar isso como uma promessa para este Auth Provider.
00:08:55E isso pode apenas conter essa promessa.
00:08:57Pode ficar lá, esperando, até estarmos prontos para lê-lo.
00:09:01Então, agora temos isso configurado.
00:09:03Isso significa que podemos realmente ir em frente e nos livrar desta prop,
00:09:08em primeiro lugar.
00:09:09E vamos nos livrar desta que está sendo passada para o banner pessoal.
00:09:12E vamos nos livrar do prop drilling também aqui ou da assinatura.
00:09:16E agora podemos usar este Auth Provider para buscar este valor loggedIn localmente dentro do banner pessoal com useAuth com o provedor que acabamos de criar.
00:09:26E lê-lo com use.
00:09:28Então,
00:09:28isso realmente funcionará de uma forma que precisamos suspender isso enquanto está sendo resolvido.
00:09:33Então,
00:09:33agora eu apenas co-localizei aquela pequena busca de dados dentro do banner pessoal.
00:09:37E não preciso passar essas props por aí.
00:09:40E enquanto isso está sendo resolvido,
00:09:42vamos em frente e suspender este também com um fallback.
00:09:44E vamos apenas fazer um banner geral aqui para evitar qualquer deslocamento cumulativo estranho.
00:09:51E finalmente, também nos livramos deste.
00:09:53Então, agora este banner de boas-vindas é composable.
00:09:58É reutilizável.
00:09:59Não temos props ou dependências estranhas na página inicial.
00:10:02E como podemos reutilizar isso tão facilmente,
00:10:05vamos em frente e adicioná-lo também a esta página de navegação aqui,
00:10:10que estará aqui.
00:10:11E posso simplesmente usá-lo aqui sem quaisquer dependências.
00:10:15Então,
00:10:16através desses padrões,
00:10:17somos capazes de manter uma boa arquitetura de componentes utilizando React cache,
00:10:24React use,
00:10:25e tornar nossos componentes mais utilizáveis e composable.
00:10:30Certo.
00:10:31Vamos abordar o próximo desafio comum,
00:10:33que seria o JavaScript excessivo no lado do cliente e componentes grandes com múltiplas responsabilidades.
00:10:40Na verdade, isso também está na página "Tudo" aqui.
00:10:43E novamente,
00:10:43teremos que trabalhar neste banner de boas-vindas.
00:10:46Atualmente, é um componente cliente.
00:10:48E a razão pela qual é um componente cliente é porque tenho este estado de
00:10:51"dispensado"
00:10:52muito simples aqui.
00:10:53Posso simplesmente clicar nisso.
00:10:54É uma boa interação de UI.
00:10:56Tudo bem.
00:10:57O que não é tão bom,
00:10:58porém,
00:10:58é que por causa disso,
00:10:59eu converto todo este componente em um componente do lado do cliente ou um componente cliente.
00:11:04E eu até uso swr para buscar dados no lado do cliente.
00:11:07Agora tenho esta camada de API aqui.
00:11:08Não tenho mais segurança de tipo nos meus dados.
00:11:11Sim, isso não é necessário.
00:11:12E também estamos quebrando a separação de preocupações aqui porque estamos envolvendo lógica de UI com dados.
00:11:18Então,
00:11:18vamos em frente e usar outro padrão inteligente para corrigir isso.
00:11:21É chamado de padrão donut.
00:11:23Basicamente,
00:11:23o que vou fazer é extrair isso para um wrapper do lado do cliente.
00:11:27Então, vamos criar um novo componente aqui.
00:11:29E vamos chamá-lo de BannerContainer.
00:11:32E este vai conter nossa lógica interativa com a diretiva use client.
00:11:37Podemos criar a assinatura.
00:11:38Podemos colar tudo o que tínhamos antes.
00:11:42E em vez de usar esses banners,
00:11:44vou apenas encaixar uma prop aqui,
00:11:47que será children.
00:11:48É por isso que é chamado de padrão donut.
00:11:50Estamos apenas criando esta lógica de UI de wrapper em torno de conteúdo renderizado no servidor,
00:11:54ou poderia ser conteúdo renderizado no servidor.
00:11:56E então,
00:11:57como não temos mais esta dependência do lado do cliente,
00:11:59podemos ir em frente e remover o use client.
00:12:01Podemos usar nossa função assíncrona isAuth aqui em vez disso.
00:12:06Podemos transformar isso em um componente de servidor assíncrono.
00:12:09Podemos até substituir a busca de dados do lado do cliente pela busca de dados do lado do servidor.
00:12:11Então,
00:12:12deixe-me ir em frente e apenas obter os dados de desconto diretamente aqui.
00:12:16Dados de desconto.
00:12:18E apenas utilizar nosso modelo mental regular como antes com segurança de tipo.
00:12:24E isso significa que também posso excluir esta camada de API com a qual não quero trabalhar de qualquer forma.
00:12:29Finalmente,
00:12:29para o isLoading,
00:12:30podemos apenas exportar um novo banner de boas-vindas aqui com nosso BannerContainer do padrão donut contendo conteúdo renderizado no servidor.
00:12:38E isso significa que não precisamos mais deste isLoading.
00:12:40Então,
00:12:41basicamente,
00:12:41refatoramos tudo isso em um componente de servidor e extraímos um ponto de lógica de UI.
00:12:46Mas o que é isso?
00:12:48Parece que tenho outro erro.
00:12:51Então, isso é na verdade por causa do Motion.
00:12:53Usem o Motion.
00:12:54É uma biblioteca de animação realmente ótima,
00:12:57mas requer a diretiva useClient.
00:12:59E novamente,
00:13:00não precisamos usar useClient apenas para animação.
00:13:03Podemos criar,
00:13:04novamente,
00:13:05um wrapper de padrão donut e apenas extrair wrappers para essas animações.
00:13:10E isso significa que não precisamos converter nada aqui para o lado do cliente.
00:13:14E provavelmente estou perdendo algo aqui embaixo.
00:13:17Sim.
00:13:18Aí está.
00:13:21Então, agora tudo aqui foi convertido para o servidor.
00:13:23Temos a mesma interação.
00:13:24Ainda temos nossa lógica interativa aqui,
00:13:27mas agora temos esta única maneira de buscar dados.
00:13:29E temos muito menos JS do lado do cliente.
00:13:31Na verdade,
00:13:32estou usando este padrão donut para este UI boundary helper,
00:13:39que se parece com isso.
00:13:42Estão vendo?
00:13:43Então,
00:13:44isso meio que mostra,
00:13:44novamente,
00:13:45o que quero dizer,
00:13:45certo?
00:13:45Com o padrão donut,
00:13:46temos este componente cliente em torno de um componente servidor.
00:13:49Também marquei muitos dos meus outros componentes com este UI helper aqui.
00:13:53Também aqui, tenho mais componentes de servidor.
00:13:56Vamos em frente e melhorar esses também,
00:13:59já que estamos ficando muito bons nisso.
00:14:01Eles estão no rodapé.
00:14:04Essas categorias...
00:14:05quero dizer,
00:14:05tenho este bom componente buscando seus próprios dados..
00:14:08E eu só queria adicionar este showMore,
00:14:11caso fique muito longo.
00:14:14E com o padrão donut,
00:14:15posso apenas envolver um componente showMore aqui.
00:14:20E isso conterá minha lógica de UI.
00:14:23E parece com isso, certo?
00:14:27Bem legal.
00:14:28E isso agora contém a lógica do cliente,
00:14:31permitindo-nos usar o estado.
00:14:33Estamos usando a contagem de children e para array para fatiar isso.
00:14:36E o que é tão legal aqui é que esses dois são agora componentes totalmente composable e reutilizáveis que funcionam juntos assim.
00:14:42Então,
00:14:42esta é realmente a beleza desses padrões que estamos aprendendo aqui.
00:14:45Você pode usar isso para qualquer coisa.
00:14:50Eu também uso para este modal aqui.
00:14:52Sim,
00:14:52apenas lembrem-se disso da próxima vez que estiverem considerando adicionar qualquer tipo de lógica de cliente aos seus componentes de servidor.
00:14:59OK, conhecemos o padrão donut.
00:15:01Sabemos como utilizá-lo para criar esses componentes composable e evitar client-side JS,
00:15:07então podemos passar para o problema final.
00:15:10Deixe-me fechar isso novamente.
00:15:13Então,
00:15:14isso seria com a falta de estratégias de renderização estática,
00:15:18certo?
00:15:18Olhando para a saída da minha compilação,
00:15:20na verdade,
00:15:21tenho cada página como uma página dinâmica aqui.
00:15:24Então,
00:15:24isso significa que sempre que eu carregar algo aqui,
00:15:27isso será executado para cada usuário.
00:15:29Desculpe.
00:15:30Cada usuário que abrir isso vai ter este estado de carregamento.
00:15:33Isso vai desperdiçar custos de servidor,
00:15:35piorando o desempenho.
00:15:37E isso significa também que algo dentro das minhas páginas está causando renderização dinâmica ou forçando a renderização dinâmica para todas as minhas páginas.
00:15:45Na verdade, está dentro do meu root layout.
00:15:49Não sei se vocês já experimentaram isso.
00:15:51Está aqui.
00:15:53No meu cabeçalho, tenho este perfil de usuário.
00:15:57E isso,
00:15:57claro,
00:15:58está usando cookies para obter o usuário atual,
00:16:00e isso significa que todo o resto também é renderizado dinamicamente.
00:16:02Porque,
00:16:03novamente,
00:16:03as páginas podem ser dinâmicas ou estáticas,
00:16:06certo?
00:16:06Este é um problema bastante comum e algo que já foi resolvido em versões anteriores do Next,
00:16:11então vamos ver o que podemos fazer.
00:16:13Uma coisa que poderíamos fazer é criar um grupo de rotas e dividir nosso aplicativo em seções estáticas e dinâmicas,
00:16:20o que me permitiria extrair minha página "Sobre".
00:16:23Eu poderia renderizar isso estaticamente.
00:16:25Tudo bem para alguns aplicativos,
00:16:27mas no meu caso,
00:16:28a página importante é a página do produto,
00:16:30e esta ainda é dinâmica,
00:16:31então não é muito útil.
00:16:33Que tal esta estratégia?
00:16:35Então,
00:16:35aqui estou criando este request context param codificando um certo estado na minha URL,
00:16:40e então posso usar generate static params para gerar todas as diferentes variantes das minhas páginas.
00:16:46Isso,
00:16:47na verdade,
00:16:47combinado com a busca de dados do usuário no lado do cliente,
00:16:51me permitiria ter isso em cache na minha página de produto.
00:16:54Definitivamente um padrão viável.
00:16:55É recomendado pelo SDK Vercel Flags,
00:16:58chamado de padrão precompute,
00:17:00eu acho.
00:17:00Mas isso é realmente complexo,
00:17:02e tenho várias maneiras de buscar dados.
00:17:04E,
00:17:04na verdade,
00:17:05não quero reescrever todo o meu aplicativo para isso.
00:17:07E se não tivéssemos que fazer nenhuma dessas soluções alternativas?
00:17:10E se houvesse uma maneira mais simples?
00:17:12Bem, existe.
00:17:14Vamos voltar ao nosso aplicativo novamente.
00:17:17Então,
00:17:17podemos realmente ir para o next config e apenas habilitar cache components.
00:17:23Ah, legal.
00:17:25OK,
00:17:25e o que isso faz,
00:17:26como vocês sabem da keynote,
00:17:28é que ele realmente fará com que todas as nossas chamadas assíncronas optem pelo tempo de requisição ou dinâmico.
00:17:34E também nos dará erros sempre que tivermos alguma chamada assíncrona não suspensa,
00:17:39e nos dará esta diretiva use cache que podemos usar para armazenar em cache granularmente uma página,
00:17:46uma função ou um componente.
00:17:48Então, sim, vamos em frente e utilizar isso.
00:17:51Podemos começar com a página inicial aqui.
00:17:55Vamos dar uma olhada.
00:17:56Então,
00:17:56novamente,
00:17:57tenho esta mistura de conteúdo estático e dinâmico.
00:17:59Tenho meu banner de boas-vindas para mim,
00:18:01algo para você também para mim.
00:18:03Vamos dar uma olhada nisso com este UI helper novamente.
00:18:06Então,
00:18:06por exemplo,
00:18:07o banner é renderizado dinamicamente com isso aqui.
00:18:10Enquanto eu marquei isso como renderização híbrida porque o herói está buscando essa coisa assíncrona e está indo bem devagar.
00:18:18Mas não depende de nenhum tipo de dado do usuário ou APIs dinâmicas.
00:18:21Então,
00:18:22isso significa que tudo o que é renderizado de forma híbrida aqui pode ser reutilizado em todas as requisições e em todos os usuários.
00:18:27E podemos usar a diretiva use cache nisso.
00:18:30Então,
00:18:30vamos adicionar a diretiva use cache aqui e marcar isso como armazenado em cache.
00:18:35E isso me permitirá — sempre que eu recarregar esta página — eu não salvei isso.
00:18:43Aí está.
00:18:44Não recarregará esta parte porque está em cache.
00:18:47Agora é estático, certo?
00:18:49E também existem outras APIs relacionadas,
00:18:52como a cache tag para me permitir tipar isso ou validar a entrada de cache específica granularmente ou definir meu período de revalidação.
00:19:01Mas para esta demonstração,
00:19:03vamos focar apenas na diretiva simples.
00:19:05Agora que tenho esta diretiva use cache,
00:19:07posso realmente remover meu limite de Suspense em torno deste herói.
00:19:10E isso significa — bem,
00:19:12o que isso fará é que a pré-renderização parcial pode realmente ir em frente e incluir isso no shell pré-renderizado estaticamente para que este herói,
00:19:20neste caso,
00:19:21faça parte da minha saída de compilação.
00:19:23Vamos fazer a mesma coisa para todo o resto nesta página que pode ser compartilhado.
00:19:28Por exemplo, tenho estas categorias em destaque aqui.
00:19:31Vamos em frente e fazer o mesmo lá.
00:19:33E adicionar a diretiva use cache e marcar isso como armazenado em cache.
00:19:37Assim.
00:19:39E podemos remover o limite de Suspense.
00:19:40Não vamos mais precisar disso.
00:19:43O mesmo para os produtos em destaque.
00:19:44Vamos adicionar use cache e marcar isso como armazenado em cache.
00:19:48Opa.
00:19:50E então remover o limite de Suspense.
00:19:52Então, percebam quanta complexidade eu consigo remover aqui.
00:19:55Não preciso me preocupar com meus esqueletos,
00:19:57meu deslocamento cumulativo de layout que eu estava fazendo antes.
00:20:00E a página não é mais — ou não temos mais esta limitação de nível de página estático versus dinâmico.
00:20:07Então,
00:20:08agora,
00:20:08quando eu carregar esta página,
00:20:10vocês verão que tudo aqui está em cache,
00:20:12exceto por este conteúdo verdadeiramente específico do usuário.
00:20:16Certo.
00:20:18Então, isso é bem legal.
00:20:19Vamos para a página "Navegar" e fazer a mesma coisa lá.
00:20:24Sim.
00:20:25Já marquei todos os meus limites aqui para que vocês possam entender facilmente o que está acontecendo.
00:20:29E quero pelo menos armazenar em cache estas categorias.
00:20:33Parece que estou recebendo um erro, porém.
00:20:37Talvez vocês reconheçam isso.
00:20:38Então, significa que tenho uma rota de bloqueio.
00:20:40E não estou usando um limite de Suspense quando deveria.
00:20:43Atualizando isso, é verdade, hein?
00:20:46Isso é realmente lento.
00:20:47E está causando problemas de desempenho e má UX.
00:20:50Então, isso é ótimo.
00:20:51Use cache ou cache components está me ajudando a identificar minhas rotas de bloqueio.
00:20:55Vamos realmente ver o que está acontecendo lá dentro.
00:20:57Então, este é o problema, certo?
00:20:59Estou buscando essas categorias no nível superior e não tenho nenhum limite de Suspense acima delas.
00:21:03Basicamente, precisamos fazer uma escolha.
00:21:05Ou adicionamos um limite de Suspense acima ou optamos pelo cache.
00:21:09Vamos fazer a coisa simples primeiro e apenas adicionar um loading.tsx aqui.
00:21:12E vamos adicionar uma página de carregamento aqui,
00:21:18uma bela UI de esqueleto.
00:21:21Isso é muito bom.
00:21:21Resolveu o erro,
00:21:22mas não tenho nada útil acontecendo nesta página enquanto espero.
00:21:25Não consigo nem pesquisar.
00:21:27Então,
00:21:28com cache components,
00:21:29dinâmico é como — ou estático versus dinâmico é como uma escala.
00:21:33E cabe a nós decidir o quanto de estático queremos em nossas páginas.
00:21:37Então,
00:21:37vamos mover esta página mais para o estático e apenas deletar este loading.tsx novamente.
00:21:43E então utilizar os padrões que estávamos aprendendo anteriormente para empurrar esta busca de dados para o componente e co-localizá-la com a UI.
00:21:50Então,
00:21:51mova isso para meus filtros de categoria responsivos aqui.
00:21:54Tenho dois por causa do design responsivo.
00:21:57Posso realmente ir em frente e apenas adicioná-lo aqui.
00:22:01Opa.
00:22:03E importar isso.
00:22:05Não preciso mais deste prompt.
00:22:06Na verdade, meu componente está se tornando mais composable.
00:22:09E em vez de suspendê-lo,
00:22:11vamos apenas adicionar a diretiva use cache.
00:22:14E isso deve ser suficiente.
00:22:16Então,
00:22:17percebam como estou sendo forçado a pensar mais sobre onde estou resolvendo minhas promessas e realmente melhorando minha arquitetura de componentes através disso.
00:22:24Não preciso suspender isso.
00:22:25Isso será apenas incluído no shell estático aqui.
00:22:28A lista de produtos, deixe-me apenas mantê-la atualizada.
00:22:35Assim, posso recarregar isso toda vez.
00:22:37Enquanto as categorias na parte inferior,
00:22:39também quero armazenar em cache.
00:22:41Então, vamos em frente e ir para o rodapé.
00:22:44E como estou usando o padrão donut aqui,
00:22:47isso pode realmente ser armazenado em cache,
00:22:50mesmo que esteja dentro desta parte da UI que é interativa.
00:22:54Então, isso está totalmente bem.
00:22:55Então,
00:22:56esse padrão não foi bom apenas para composição,
00:22:58mas também para cache.
00:22:58Acho que tenho mais um erro lá.
00:23:03Vamos ver o que é.
00:23:04Ainda tenho este erro.
00:23:08Isso é na verdade por causa desses search frames.
00:23:10Search frames, como sabemos, é uma API dinâmica.
00:23:12Não consigo armazenar isso em cache.
00:23:13Mas posso resolvê-lo mais profundamente para revelar mais da minha UI e torná-la estática.
00:23:18Então,
00:23:18vamos em frente e mover isso para baixo,
00:23:21passá-lo como uma promessa para a lista de produtos.
00:23:24Vamos tipar isso como uma promessa aqui, assim.
00:23:30Vamos resolvê-lo dentro da lista de produtos,
00:23:33usar os parâmetros de busca resolvidos aqui e aqui.
00:23:36E como isso está suspenso aqui, o erro desaparecerá.
00:23:40Então,
00:23:41recarregando isso,
00:23:42a única coisa que está recarregando aqui é apenas a parte que escolhi especificamente para ser dinâmica.
00:23:48Todo o resto pode ser armazenado em cache.
00:23:49E isso significa que posso interagir com meu banner ou até mesmo pesquisar porque essa parte já foi pré-renderizada.
00:23:57Certo,
00:23:57vamos fazer a página final aqui,
00:24:00que é a página do produto,
00:24:02que é a mais difícil e a mais importante.
00:24:05Está muito ruim agora.
00:24:08Isso é super importante para uma plataforma de e-commerce,
00:24:10aparentemente.
00:24:11Certo, vamos em frente e consertar esse também.
00:24:15Então, aqui tenho esta página de produto.
00:24:18Vamos começar a armazenar em cache apenas o conteúdo reutilizável aqui,
00:24:22por exemplo,
00:24:22o próprio produto.
00:24:23E apenas adicionar use cache aqui e marcar isso como armazenado em cache.
00:24:27Isso deve estar bem.
00:24:28Isso significa que podemos remover o limite de Suspense aqui.
00:24:33Certo,
00:24:33e isso não está mais recarregando a cada requisição aqui,
00:24:37certo?
00:24:38Para os detalhes do produto, vamos fazer a mesma coisa.
00:24:40Vamos adicionar use cache.
00:24:41Vamos marcá-lo como armazenado em cache e ver se isso também funcionará.
00:24:47Não funcionou.
00:24:48Na verdade, este é um erro diferente.
00:24:50Está me dizendo que estou tentando usar APIs dinâmicas dentro deste segmento em cache.
00:24:54E isso é verdade.
00:24:54Estou usando o botão "Salvar Produto", certo?
00:24:56Isso me permitiu clicar e alternar o estado salvo.
00:25:00Então, o que vocês acham que podemos fazer com isso?
00:25:03Podemos usar o padrão donut novamente.
00:25:06Na verdade,
00:25:06também podemos encaixar segmentos dinâmicos em segmentos de cache.
00:25:10Então, estamos intercalando-os como antes, mas com cache.
00:25:12Então, isso é bem legal.
00:25:14Vamos em frente e adicionar os children aqui assim.
00:25:19E isso removerá o erro.
00:25:21E posso apenas envolver isso em torno deste único segmento dinâmico da minha página aqui,
00:25:27remover o limite de Suspense e adicionar apenas uma pequena UI de marcador para aquela parte dinâmica da página.
00:25:34E vamos ver como isso fica agora.
00:25:40Então,
00:25:40percebam como quase toda a UI está disponível,
00:25:43mas tenho este pequeno pedaço que é dinâmico,
00:25:46e tudo bem.
00:25:47Todo o resto ainda está lá.
00:25:48E vamos deixar as avaliações dinâmicas porque poderíamos mantê-las atualizadas.
00:25:53Ainda há mais um erro.
00:25:54Vamos apenas resolver isso rapidamente.
00:25:56Novamente, este é o params.
00:25:58Estou recebendo ajuda de que preciso fazer uma escolha: ou adicionar um loading fallback ou armazenar isso em cache.
00:26:04Vamos apenas usar generate static params neste caso.
00:26:07Depende do seu caso de uso e do seu conjunto de dados.
00:26:10Mas,
00:26:10para este caso,
00:26:11vou apenas adicionar algumas páginas pré-renderizadas e predefinidas e depois apenas armazenar em cache o resto à medida que são geradas pelos usuários.
00:26:17E isso removerá meu erro aqui.
00:26:20Então, acho que terminei minha refatoração.
00:26:22Vamos em frente e dar uma olhada na versão implantada e ver como ela se parece.
00:26:26Então, acabei de implantar isso no Vercel.
00:26:27E lembrem-se,
00:26:29eu propositalmente desacelerei muitas buscas de dados aqui.
00:26:35E ainda assim,
00:26:36quando eu carrego esta página inicialmente,
00:26:39tudo já está disponível.
00:26:40A única coisa aqui são apenas aqueles poucos segmentos dinâmicos,
00:26:44como os descontos e o "para você".
00:26:46O mesmo com o "Navegar em Tudo".
00:26:47Toda a UI já está disponível.
00:26:50E para o produto em si, parece instantâneo.
00:26:54E lembrem-se,
00:26:55novamente,
00:26:55que todos esses segmentos em cache serão incluídos com o shell estático com pré-renderização parcial.
00:27:00E pode ser pré-buscado usando o prefetching aprimorado no novo roteador cliente do Next 16.
00:27:05Então, isso significa que cada navegação apenas...
00:27:08parece tão rápido, certo?.
00:27:09Certo,
00:27:10para resumir,
00:27:11com cache components,
00:27:13não há mais estático versus dinâmico.
00:27:17E não precisamos evitar APIs dinâmicas ou comprometer o conteúdo dinâmico.
00:27:28E podemos pular esses hacks e soluções alternativas complexas usando múltiplas estratégias de busca de dados apenas para aquele...
00:27:35este acerto de cache, como eu mostrei a vocês..
00:27:37Então,
00:27:38no Next.js moderno,
00:27:39dinâmico versus estático é uma escala.
00:27:40E nós decidimos o quanto de estático queremos em nossos aplicativos.
00:27:43E desde que sigamos certos padrões,
00:27:45podemos ter um modelo mental que é performático,
00:27:48composable e escalável por padrão.
00:27:50Então, vamos voltar aos slides.
00:27:53Então,
00:27:53se vocês não estão — não estavam já impressionados com a velocidade disso,
00:27:56esta é a pontuação do Lighthouse.
00:27:56Então,
00:27:57coletei alguns dados de campo com o Vercel Speed Insights.
00:28:00Então,
00:28:00temos uma pontuação de 100 em todas as páginas mais importantes,
00:28:03a página inicial,
00:28:04a página do produto e a lista de produtos,
00:28:06mesmo que sejam altamente dinâmicas.
00:28:08Então,
00:28:08vamos finalmente resumir os padrões que garantirão escalabilidade e desempenho em aplicativos Next.js e nos permitirão aproveitar as últimas inovações e obter pontuações como esta.
00:28:18Primeiramente,
00:28:19podemos refinar nossa arquitetura resolvendo promessas profundamente na árvore de componentes e buscando dados localmente dentro dos componentes usando React Cache para evitar trabalho duplicado.
00:28:28Podemos evitar a passagem excessiva de props para componentes cliente usando provedores de contexto combinados com React Use.
00:28:35Em segundo lugar,
00:28:35podemos compor componentes de servidor e cliente usando o padrão donut para reduzir o JavaScript do lado do cliente,
00:28:40manter uma clara separação de preocupações e permitir a reutilização de componentes.
00:28:43E este padrão nos permitirá ainda mais armazenar em cache nossos componentes de servidor compostos posteriormente.
00:28:50E,
00:28:50finalmente,
00:28:51podemos armazenar em cache e pré-renderizar com use cache,
00:28:53seja por página,
00:28:54componente ou função,
00:28:55para eliminar processamento redundante,
00:28:56impulsionar o desempenho e o SEO,
00:28:58e permitir que a pré-renderização parcial renderize estaticamente esses segmentos do aplicativo.
00:29:01E se nosso conteúdo for verdadeiramente dinâmico,
00:29:04podemos suspendê-lo com fallbacks de carregamento apropriados.
00:29:07E lembrem-se que tudo isso está conectado.
00:29:09Então,
00:29:09quanto melhor sua arquitetura,
00:29:10mais fácil será compor,
00:29:11e mais fácil será armazenar em cache e pré-renderizar com os melhores resultados.
00:29:15Por exemplo,
00:29:15resolver APIs dinâmicas profundamente na árvore permitirá que você crie um shell estático parcialmente renderizado maior.
00:29:22E com isso,
00:29:22este é o repositório da versão completa do aplicativo.
00:29:25Há tantas coisas que nem mostrei lá que vocês podem conferir.
00:29:29E vocês podem escanear o código QR para encontrar minhas redes sociais lá,
00:29:32junto com o repositório,
00:29:34se não quiserem tirar uma foto e digitar vocês mesmos.
00:29:36Então, sim, é isso para mim.
00:29:37Obrigado, Next.js Conf, por me receberem aqui.
00:29:39[MÚSICA TOCANDO]

Key Takeaway

O Next.js 16, com a diretiva `use cache` e a funcionalidade `cache components`, transforma a renderização de páginas de uma escolha binária (estática ou dinâmica) para uma escala flexível, permitindo otimizar o desempenho e a escalabilidade através de padrões de composição e cache granular.

Highlights

Apresenta os conceitos de renderização estática e dinâmica no Next.js App Router e as APIs que forçam a renderização dinâmica.

Introduz a diretiva `use cache` no Next.js 16, que permite o cache composable e a pré-renderização parcial de segmentos estáticos dentro de páginas dinâmicas.

Demonstra padrões de arquitetura como resolver promessas profundamente na árvore de componentes e usar o padrão donut para compor componentes de servidor e cliente, reduzindo o JavaScript do lado do cliente.

Mostra como a diretiva `use cache` e a funcionalidade `cache components` ajudam a identificar e otimizar rotas de bloqueio e conteúdo que pode ser estático.

Explica como aplicar `use cache` em diferentes cenários (página inicial, navegação, página de produto) para melhorar o desempenho e a experiência do usuário, mesmo em aplicações altamente dinâmicas.

Enfatiza que no Next.js moderno, a escolha entre estático e dinâmico é uma escala, permitindo aos desenvolvedores decidir o nível de estaticidade em suas aplicações.

Timeline

Introdução e Tópico da Palestra

A oradora, Aurora, desenvolvedora web da Noruega e consultora na Crane Consulting, apresenta-se e o tema da palestra. Ela abordará padrões de composição, cache e arquitetura no Next.js moderno. O objetivo é garantir escalabilidade e desempenho em aplicações. Este segmento estabelece o contexto e a importância dos tópicos a serem discutidos. A palestra foca em como o Next.js App Router pode ser utilizado para construir aplicações robustas e eficientes.

Renderização Estática vs. Dinâmica

Aurora revisita os conceitos fundamentais de renderização estática e dinâmica, ambos presentes no Next.js App Router. A renderização estática cria sites mais rápidos, pois o conteúdo pré-renderizado pode ser armazenado em cache e distribuído globalmente, reduzindo a carga do servidor e melhorando o SEO (ex: site Next.js Conf). A renderização dinâmica, por outro lado, permite exibir dados em tempo real, conteúdo frequentemente atualizado ou personalizado (ex: painel Vercel). Ela acessa informações conhecidas apenas no momento da solicitação, sendo crucial para entender como o Next.js processa e entrega conteúdo.

APIs que Causam Renderização Dinâmica

Este segmento detalha as APIs que podem forçar uma página a ser renderizada dinamicamente. O uso de `params` e `search params` (passados para páginas ou hooks equivalentes) causa renderização dinâmica, embora `static params` possa predefinir páginas pré-renderizadas. A leitura de cookies e cabeçalhos de requisição de entrada também força a renderização dinâmica e pode causar erros de compilação se houver tentativa de cache. Finalmente, `fetch` com uma configuração de cache `no-store` também resulta em renderização dinâmica, sendo essencial compreender essas APIs para controlar o comportamento de renderização.

Limitações de Versões Anteriores do Next.js

Em versões anteriores do Next.js, uma página era renderizada como totalmente estática ou totalmente dinâmica, o que significava que uma única API dinâmica em uma página forçava a página inteira a ser dinâmica. Isso levava a um processamento redundante no servidor para conteúdo que raramente mudava. Mesmo com React Server Components e Suspense, adicionar múltiplos componentes assíncronos em uma página dinâmica que não dependiam de APIs dinâmicas ainda exigia trabalho extra (esqueletos, preocupação com CLS). A necessidade de escolher entre estático e dinâmico para páginas mistas resultava em desempenho subótimo e custos de servidor desnecessários, problema que a nova diretiva `use cache` visa resolver.

A Solução: Diretiva `use cache` no Next.js 16

A diretiva `use cache`, anunciada na Next.js Conf e disponível no Next.js 16, resolve o problema da renderização binária. Agora, as páginas podem ser estáticas e dinâmicas simultaneamente. Por padrão, tudo é dinâmico, e `use cache` permite optar explicitamente pelo cache em nível granular (página, componente, função). Isso permite que segmentos em cache (como produtos em destaque) sejam pré-renderizados e incluídos no shell estático com pré-renderização parcial. Isso significa que o conteúdo estático está disponível no carregamento da página, eliminando a necessidade de streaming e esqueletos, e oferecendo uma abordagem mais flexível e eficiente para o gerenciamento de renderização.

Demonstração Inicial e Problemas Comuns

Aurora inicia uma demonstração prática de um aplicativo de e-commerce simples, mostrando suas funcionalidades (página inicial, 'Navegar em Tudo', 'Sobre', painel de usuário com conteúdo personalizado, página de produto). O aplicativo possui uma mistura de conteúdo estático e dinâmico. Ela destaca os problemas comuns presentes na base de código inicial: prop drilling profundo, excesso de JavaScript no lado do cliente, componentes grandes com múltiplas responsabilidades e falta de renderização estática. O objetivo da demonstração é melhorar o aplicativo usando padrões inteligentes de composição, cache e arquitetura, com operações intencionalmente desaceleradas para facilitar a visualização dos problemas e das melhorias.

Resolvendo Prop Drilling com Componentes de Servidor e Contexto

O primeiro problema abordado é o prop drilling. Aurora demonstra como mover a busca de dados para componentes que realmente os utilizam, resolvendo promessas mais profundamente na árvore de componentes. Ela utiliza `React cache` e `React use` para reutilizar chamadas de autenticação e introduz um `Auth Provider` no layout raiz para passar o estado `loggedIn` como uma promessa. Isso permite que componentes cliente busquem o valor localmente, eliminando a necessidade de passar props por múltiplos níveis. Essa abordagem torna os componentes mais composable e reutilizáveis, como o banner de boas-vindas, que pode ser adicionado facilmente a outras páginas sem dependências, resultando em uma arquitetura de componentes mais limpa e eficiente.

Reduzindo JavaScript do Lado do Cliente com o Padrão Donut

Para combater o JavaScript excessivo no lado do cliente e componentes com múltiplas responsabilidades, Aurora introduz o 'padrão donut'. Ela refatora um `WelcomeBanner` que era um componente cliente devido a uma lógica de UI simples. A lógica interativa é extraída para um wrapper do lado do cliente (`BannerContainer`) que aceita `children`, enquanto o conteúdo principal (renderizado no servidor) permanece server-side. Isso permite misturar interatividade do cliente com conteúdo do servidor, reduzindo o bundle de JS do cliente. O padrão é aplicado também para integrar bibliotecas como Framer Motion e para um componente 'show more' no rodapé, demonstrando sua versatilidade para criar componentes composable e reutilizáveis, melhorando a separação de preocupações e otimizando o carregamento de scripts.

O Problema da Falta de Renderização Estática e Soluções Antigas

Aurora revisita o problema da falta de renderização estática, onde todas as páginas eram dinâmicas na saída da compilação, resultando em custos de servidor e desempenho degradado. A causa é identificada no `UserProfile` do cabeçalho, que usa cookies, forçando todo o layout raiz a ser dinâmico. Ela discute soluções alternativas anteriores, como a criação de grupos de rotas (limitado) ou o uso de `request context param` com `generate static params` e busca de dados no lado do cliente (complexo e exigiria reescrever o aplicativo). A complexidade dessas soluções ressalta a necessidade de uma abordagem mais simples e integrada, preparando o terreno para a introdução da solução moderna no Next.js 16.

Habilitando `cache components` e Aplicando `use cache` na Página Inicial

A solução moderna é habilitar `cache components` no `next.config.js`, o que faz com que todas as chamadas assíncronas optem pelo tempo de requisição e impõe limites de Suspense. Em seguida, a diretiva `use cache` é aplicada a componentes na página inicial que não dependem de APIs dinâmicas (ex: `Hero`, `FeaturedCategories`, `FeaturedProducts`). Isso permite que esses segmentos sejam pré-renderizados e incluídos no shell estático com pré-renderização parcial, eliminando a necessidade de limites de Suspense e melhorando o tempo de carregamento inicial. A oradora demonstra como a página recarrega mais rapidamente, com apenas o conteúdo verdadeiramente específico do usuário sendo dinâmico, e `use cache` oferece controle granular sobre o cache, permitindo otimizar o desempenho sem comprometer a dinâmica.

Otimizando a Página 'Navegar em Tudo' com `use cache`

Na página 'Navegar em Tudo', Aurora tenta aplicar `use cache` às categorias, mas encontra um erro de 'rota de bloqueio' devido à busca de dados no nível superior sem Suspense. Isso demonstra como `cache components` ajuda a identificar gargalos de desempenho. A solução envolve mover a busca de dados das categorias para dentro dos componentes de filtro de categoria responsivos e aplicar `use cache` a eles. Ela também aborda os `search params` (uma API dinâmica) passando-os como uma promessa para a lista de produtos, resolvendo-os mais profundamente na árvore. Isso garante que a maior parte da UI seja pré-renderizada e estática, enquanto apenas a parte dinâmica (a lista de produtos filtrada) recarrega, melhorando a arquitetura e a experiência do usuário.

Otimizando a Página de Produto com `use cache` e Padrão Donut

A página de produto, considerada a mais crítica, é otimizada. Aurora aplica `use cache` ao produto e aos detalhes do produto. No entanto, o botão 'Salvar Produto' dentro dos detalhes do produto usa APIs dinâmicas (estado do usuário), causando um erro. A solução é usar o padrão donut novamente: o botão 'Salvar Produto' (dinâmico) é envolvido por um componente pai (estático) que utiliza `use cache`. Isso permite intercalar segmentos dinâmicos dentro de segmentos em cache. Para os `params` da página de produto, `generate static params` é usado para pré-renderizar um conjunto de páginas e armazenar em cache o restante à medida que são geradas, resultando em uma página de produto quase instantânea.

Resultados da Demonstração e Filosofia do Next.js Moderno

Aurora apresenta a versão implantada do aplicativo no Vercel, demonstrando a velocidade e o desempenho aprimorados. Apesar das buscas de dados intencionalmente lentas, as páginas carregam instantaneamente, com apenas os segmentos dinâmicos (como descontos personalizados) sendo carregados separadamente. Ela explica que os segmentos em cache são incluídos no shell estático via pré-renderização parcial e podem ser pré-buscados pelo novo roteador cliente do Next 16. A conclusão é que `cache components` elimina a dicotomia estático vs. dinâmico, transformando-a em uma escala onde os desenvolvedores decidem o nível de estaticidade, permitindo um modelo mental performático, composable e escalável por padrão.

Resumo dos Padrões e Conclusão Final

Aurora resume os três padrões principais para escalabilidade e desempenho no Next.js: refinar a arquitetura (resolvendo promessas profundamente e buscando dados localmente com `React Cache` e `React Use`), compor componentes (usando o padrão donut para misturar componentes de servidor e cliente), e cache e pré-renderização (utilizando `use cache` para eliminar processamento redundante e permitir pré-renderização parcial). Ela enfatiza a interconexão desses padrões e mostra pontuações de Lighthouse de 100 em páginas importantes. A palestra conclui com a importância de uma boa arquitetura para facilitar a composição e o cache, levando a melhores resultados, e fornece links para o repositório e redes sociais.

Community Posts

View all posts