Como usar um agente de IA para pensar em performance no frontend
Veja como orientar um agente de IA a medir e melhorar a performance de frontends React ou Vue com SSR, cache, lazy loading e validação antes e depois.
Um agente de IA ajuda mais na performance quando mede antes de alterar. SSR, cache e lazy loading são hipóteses: o ganho só existe quando uma comparação reproduzível confirma o resultado.
Performance não começa na técnica
Quando uma aplicação começa a receber mais acessos, é comum a conversa virar uma lista conhecida: usar SSR, adicionar lazy loading, configurar cache, reduzir o bundle, otimizar imagens ou colocar uma CDN na frente. Todos esses pontos podem ajudar, mas eles não resolvem o mesmo problema.
SSR pode melhorar a entrega do conteúdo inicial e, ao mesmo tempo, aumentar o trabalho do servidor se cada acesso exigir uma nova renderização. Lazy loading pode reduzir o JavaScript inicial e piorar o carregamento se esconder justamente o conteúdo principal. Cache pode reduzir latência e carga no origin, mas também pode entregar informação antiga ou compartilhar uma resposta personalizada no lugar errado.
Por isso, a pergunta útil não é “qual otimização está faltando?”. É “qual comportamento está lento, qual evidência mostra isso e qual é o menor experimento capaz de melhorar esse sinal?”. É nessa investigação que um agente de IA pode ser realmente útil.
“Muitos acessos” esconde dois problemas diferentes
1. A experiência de cada usuário
A primeira pergunta é: a página aparece, estabiliza e responde rapidamente para quem está usando? Aqui entram LCP, INP e CLS — o conjunto atual de Core Web Vitals —, além da quantidade de JavaScript enviado e executado, tarefas longas no main thread e tamanho e prioridade de imagens, fontes e outros recursos.
Ferramentas de laboratório são úteis durante o desenvolvimento, mas não substituem dados de campo. O Lighthouse, por exemplo, não mede o INP real porque não existe uma sequência representativa de interações de usuários naquele teste. O TBT pode sinalizar bloqueio da thread principal, mas não deve ser apresentado como se fosse a mesma métrica.
2. O trabalho repetido a cada acesso
A segunda pergunta é: quanto trabalho a aplicação, o servidor e as APIs repetem para atender cada visita? Aqui entram TTFB, taxa de cache hit, requisições que chegam ao origin, renderizações por acesso, chamadas duplicadas, volume transferido, saturação, fila, timeout e taxa de erro sob carga.
Uma página pode ter bom score de laboratório e ainda pressionar o servidor porque consulta e renderiza os mesmos dados em toda requisição. O contrário também acontece: uma página estática pode absorver muito tráfego na CDN e continuar enviando JavaScript demais para um celular de entrada. Lighthouse não é teste de carga, e teste de carga não substitui Core Web Vitals.
O prompt “deixe meu site mais rápido” é pequeno demais
Um agente de código pode ler componentes, configurações, dependências e resultados do build, além de controlar um navegador. Mesmo assim, um pedido genérico pode levá-lo a refatorar uma área irrelevante, espalhar memoização sem profiling, dividir componentes pequenos demais, atrasar a imagem de LCP ou transformar uma rota em SSR sem considerar cache e custo do origin.
1medir2 -> localizar o gargalo3 -> formular uma hipótese4 -> mudar uma coisa5 -> medir novamente6 -> decidirO agente não deveria começar escrevendo código. Ele deveria começar construindo uma linha de base e deixando claro o que foi medido, o que foi inferido e o que ainda não pôde ser verificado.
O contexto mínimo para uma boa auditoria
- Framework, versão e comando de build de produção.
- Forma de deploy, CDN, origin e rotas mais importantes.
- Quais páginas são públicas, personalizadas ou autenticadas.
- Frequência de atualização dos dados e regras de validade.
- Dispositivos e redes predominantes, quando esse dado existir.
- Comportamentos, SEO e acessibilidade que não podem mudar.
- Métricas de campo e orçamento de performance já disponíveis.
1Para cada conclusão, marque:2- medido3- inferido4- não verificadoSete pontos simples que o agente pode investigar
O objetivo não é aplicar os sete. É descobrir quais atacam o gargalo medido com o menor risco.
1. Escolher a renderização por rota
SSR, SSG e CSR não deveriam ser decisões globais tomadas apenas pelo nome da arquitetura. Um artigo ou uma landing page pouco volátil pode ser estático. Uma página pública atualizada a cada poucos minutos pode aceitar revalidação. Uma área autenticada talvez precise de renderização dinâmica. Uma tela muito interativa pode manter partes no cliente sem obrigar toda a rota a começar como uma SPA vazia.
Pergunta para o agente: quais partes desta rota realmente dependem da requisição atual e quais poderiam ser estáticas, cacheadas ou revalidadas?
2. Configurar cache de acordo com a validade
Cache pode existir no navegador, na CDN, no HTML renderizado, nas chamadas de dados e nos assets versionados. Arquivos com hash normalmente aceitam cache longo e immutable; HTML costuma exigir outra política. Respostas autenticadas ou personalizadas precisam de cuidado extra para nunca se tornarem públicas em um cache compartilhado.
- O que será armazenado e por quanto tempo continua válido?
- A resposta é pública ou privada?
- Qual evento exige invalidação?
- O que acontece quando o cache expira?
- Como serão medidos cache hit e tráfego poupado no origin?
3. Aplicar lazy loading somente ao que não é crítico
Modal, editor, mapa, gráfico pesado, player abaixo da dobra e uma rota que talvez nem seja visitada são bons candidatos. A imagem ou o conteúdo que forma o LCP não são: o recurso principal precisa ser descoberto cedo e receber prioridade adequada. Adie o que não participa da primeira experiência, mas preserve o caminho do conteúdo principal.
4. Enviar e executar menos JavaScript
O agente pode procurar dependências pesadas para tarefas pequenas, imports que prejudicam tree-shaking, bibliotecas carregadas em todas as rotas, fronteiras client-side amplas, componentes estáticos hidratados sem necessidade, scripts de terceiros no caminho crítico e código não utilizado no bundle inicial. Em React e Next.js, vale revisar o alcance de use client. Em Vue e Nuxt, vale observar o custo da hidratação e de plugins executados no início.
5. Revisar imagens, fontes e estabilidade visual
Dimensões ausentes, arquivos maiores do que o tamanho exibido, falta de variações responsivas, compressão insuficiente, imagem de LCP sem prioridade e mídia fora da tela carregada cedo são oportunidades frequentes. Largura, altura ou proporção reservada ajudam a reduzir CLS. Muitas famílias, pesos e estilos de fonte também aumentam transferência e podem atrasar texto.
6. Eliminar waterfalls e requisições duplicadas
1buscar usuário2 -> buscar permissões3 -> buscar catálogo4 -> buscar recomendaçõesSe catálogo e recomendações não dependem de permissões, parte dessas chamadas pode acontecer em paralelo. O agente também pode encontrar uma busca feita no servidor e repetida durante a hidratação, componentes irmãos consultando o mesmo recurso, payloads maiores do que a tela usa e prefetch agressivo que gera tráfego sem retorno.
7. Reduzir renderizações e listas caras depois de medir
Nem todo gargalo aparece no carregamento. Uma busca pode travar ao digitar, um filtro pode atualizar centenas de componentes e uma tabela pode criar milhares de nós no DOM. Profiler e painel de performance ajudam a encontrar props instáveis, cálculos repetidos, listas sem paginação ou virtualização e tarefas longas. Memoização entra depois da evidência, não antes dela.
Um exemplo prático em React e Vue
Imagine um catálogo público com título, imagem principal, produtos atualizados a cada poucos minutos, filtros interativos, um gráfico comparativo aberto sob demanda e avaliações abaixo da primeira tela. Uma hipótese inicial pode manter a estrutura estática, revalidar a lista dentro da janela aceita, deixar filtros no cliente e carregar gráfico e avaliações somente quando necessários.
1'use client';23import dynamic from 'next/dynamic';4import { useState } from 'react';56const ProductChart = dynamic(() => import('./ProductChart'), {7 loading: () => <p>Carregando comparação...</p>,8});910export function CompareButton() {11 const [showChart, setShowChart] = useState(false);1213 return (14 <section>15 <button onClick={() => setShowChart(true)}>Comparar produtos</button>16 {showChart ? <ProductChart /> : null}17 </section>18 );19}No exemplo com Next.js, o ganho não vem apenas de usar dynamic. Ele vem de o gráfico pesado não participar do carregamento inicial e talvez nunca ser baixado por quem não abre a comparação. O agente ainda deve confirmar a separação do chunk no build, revisar o alcance de use client e preservar a prioridade da imagem principal.
1<script setup lang="ts">2import { defineAsyncComponent, ref } from 'vue';34const showChart = ref(false);5const ProductChart = defineAsyncComponent(() => import('./ProductChart.vue'));6</script>78<template>9 <section>10 <button @click="showChart = true">Comparar produtos</button>11 <ProductChart v-if="showChart" />12 </section>13</template>No Vue, defineAsyncComponent expressa a mesma intenção. Em Nuxt, um componente autoimportado pode usar o prefixo Lazy e versões atuais também oferecem hidratação adiada. O detalhe da API muda; a intenção continua sendo preservar conteúdo crítico, dividir código opcional, evitar hidratação desnecessária e confirmar o resultado no build e no navegador.
Um prompt melhor para a auditoria
1Atue como um agente de diagnóstico de performance frontend.23Objetivo:4Identificar as três oportunidades de maior impacto para a rota [ROTA],5considerando a experiência por visita e o trabalho repetido por acesso.67Contexto:8- stack e versões: [REACT/NEXT OU VUE/NUXT]9- deploy: [PLATAFORMA, CDN E ORIGIN]10- tipo de rota: [PÚBLICA, PERSONALIZADA OU AUTENTICADA]11- atualização dos dados: [FREQUÊNCIA]12- comando de build: [COMANDO]13- comportamento que não pode mudar: [RESTRIÇÕES]1415Sucesso significa:16- executar o build de produção e registrar uma linha de base;17- inspecionar bundle, waterfall, HTML inicial, hidratação, imagens,18 fontes, scripts de terceiros e headers de cache;19- separar fatos medidos, inferências e dados ausentes;20- avaliar SSR/SSG/CSR, lazy loading, cache e redução de JavaScript21 somente quando atacarem o gargalo observado;22- priorizar no máximo três hipóteses por impacto, confiança, esforço e risco;23- indicar para cada hipótese a métrica afetada e como validar;24- não alterar código nesta etapa.2526Restrições:27- não tratar uma nota única do Lighthouse como prova suficiente;28- não usar TBT como se fosse INP de campo;29- não inventar ganhos percentuais;30- não aplicar lazy loading ao elemento de LCP sem justificativa;31- não cachear respostas personalizadas em cache compartilhado;32- não recomendar SSR como solução universal.3334Saída:351. resumo da linha de base;362. gargalos com evidência;373. tabela de hipóteses priorizadas;384. plano do menor experimento útil;395. lacunas que exigem dados de produção.Implemente uma hipótese por vez
1Implemente somente a hipótese aprovada: [HIPÓTESE].23Preserve comportamento, acessibilidade, SEO e atualização correta dos dados.4Execute o mesmo build e repita a mesma medição nas condições da linha de base.56Ao finalizar, informe:7- arquivos alterados;8- baseline e resultado de cada métrica relevante;9- variação entre execuções;10- efeitos colaterais ou riscos;11- decisão recomendada: manter, revisar ou descartar.1213Se a evidência não mostrar melhora consistente, não apresente a mudança como ganho.Separar diagnóstico e implementação evita misturar várias mudanças e depois não saber qual delas alterou o resultado. Também permite rejeitar uma solução tecnicamente interessante quando ela não produz ganho suficiente naquele contexto.
Plugin ou skill: o que realmente ajuda?
Para esse trabalho, eu não começaria por um plugin genérico. O agente precisa principalmente de acesso ao repositório, ao terminal, ao build e a um navegador. Um plugin do provedor de infraestrutura pode complementar a análise quando expõe métricas reais de CDN, cache ou edge, mas não substitui profiling, dados de campo nem teste controlado.
Uma skill local chamada frontend-performance-audit pode ser mais útil porque preserva o método: detectar a stack, gerar o build, medir a rota, inspecionar HTML, waterfall, hidratação e cache, separar fatos de hipóteses, implementar uma mudança aprovada e produzir o relatório antes/depois. Referências específicas para React/Next, Vue/Nuxt e SPA com Vite podem ficar dentro da mesma skill.
O ganho da skill não é adicionar uma capacidade secreta ao modelo. É tornar a auditoria repetível para que a próxima revisão não dependa de lembrar o prompt inteiro.
Como saber se a mudança realmente ajudou
Rede, temperatura do dispositivo, processos em segundo plano, cache aquecido, localização e carga do servidor criam variação. Uma comparação confiável registra build, rota, cenário, dispositivo, rede, estado do cache, quantidade de execuções, mediana, dispersão e a diferença entre laboratório e campo.
O resultado não deveria ser apenas uma nota geral. Uma mudança pode melhorar LCP e aumentar JavaScript; reduzir o bundle inicial e criar atraso quando uma função importante é aberta; diminuir TTFB com cache e manter conteúdo antigo por tempo demais. O trade-off precisa aparecer no relatório.
Performance budget como proteção contra regressão
- Tamanho máximo para o chunk inicial de uma rota.
- Limite para a imagem principal e JavaScript de terceiros.
- Alerta quando o bundle cresce além da tolerância definida.
- Revisão obrigatória para novas fronteiras client-side.
- Verificação dos headers de cache em assets públicos.
Os números não devem ser inventados pelo agente. Eles precisam nascer da aplicação, do público e da linha de base. Depois disso, o agente pode revisar diffs e apontar regressões antes que elas se acumulem.
Checklist prático
- Qual rota é mais importante e o build analisado é de produção?
- O problema é carregamento, interação ou capacidade sob tráfego?
- Existe dado de campo ou apenas laboratório?
- Qual elemento forma o LCP e quanto JavaScript chega primeiro?
- Existe código opcional carregado cedo demais?
- SSR está fazendo trabalho novo em toda visita?
- Quais rotas poderiam ser estáticas ou revalidadas?
- HTML, APIs e assets possuem políticas de cache coerentes?
- Alguma resposta personalizada pode cair em cache compartilhado?
- Existem requisições duplicadas, waterfalls ou listas grandes?
- Qual métrica deve melhorar e como o mesmo teste será repetido?
- Qual resultado faria a hipótese ser descartada?
Limites e ressalvas
Este artigo não substitui profiling, teste de carga, RUM, documentação do framework nem conhecimento sobre o deploy real. Os snippets mostram intenção arquitetural; APIs de renderização, cache, revalidação e hidratação mudam entre versões de Next.js e Nuxt e precisam ser conferidas antes da implementação.
Não existe orçamento universal. Uma página editorial, um dashboard interno e um editor gráfico possuem públicos e prioridades diferentes. Nem toda recomendação do Lighthouse precisa virar tarefa, nem toda rota dinâmica deveria ser estática e nem todo cache é seguro. Nenhum agente conhece o comportamento real dos usuários quando esse dado não está disponível.
Conclusão
Um agente de IA consegue navegar pelo projeto, identificar rotas, analisar dependências, executar o build, inspecionar a página e relacionar código com métricas. O ganho não vem de pedir “deixe tudo mais rápido”. Vem de oferecer contexto e exigir evidência.
Quando o prompt pergunta qual rota é crítica, se o problema está no navegador ou no trabalho repetido pelo servidor, qual métrica precisa mudar e como o teste será repetido, o agente deixa de ser um gerador de sugestões e passa a participar de um experimento técnico. Esse é um uso criterioso da IA: ajudar a medir, comparar e decidir.
