Frontends com Vibecoding · Capítulo 21 de 30 · 17 min
Validar desempenho, autenticação e segurança
Você sai com uma entrega que integra carga, estado de erro, permissão e recuperação.
Este capítulo faz parte do curso gratuito Frontends com Vibecoding. Para marcar como concluído e salvar o progresso, abra este capítulo na página do curso.
Uma imagem grande no topo da página costuma ser o vilão do LCP. Esse sinal mede quando o maior bloco da tela aparece, e o alvo é 2,5 segundos ou menos, com o limiar incluído.
Desempenho tem três sinais públicos que dizem se a página parece rápida de verdade, e cada um tem um vilão típico. Você mede os três com um número e cobra o pedido certo do agente. O orçamento de desempenho entra desde o primeiro sprint, o ciclo de uma ou duas semanas.
CLS mede o quanto a página pula sozinha enquanto carrega, com alvo de 0,1 ou menos. O vilão é imagem ou anúncio sem altura reservada, que empurra o botão no instante do clique.
INP mede o tempo entre o toque e a resposta da tela, com alvo de 200 milissegundos ou menos. O vilão é uma rotina longa em JavaScript segurando o navegador. Nos três, a página que fica exatamente no número entra na faixa boa.
Os três números de campo valem pelo percentil 75 das visitas, separados entre celular e computador, porque a média pode esconder a experiência mais lenta. O Lighthouse, o auditor embutido no navegador, simula uma carga e ajuda a diagnosticar LCP, CLS e bloqueio da thread principal. Essa execução não mede o INP das visitas reais.
O relatório do Search Console lê esses dados de campo do CrUX numa janela móvel de 28 dias. Ele só aprova a URL quando LCP, INP e CLS ficam na faixa boa. A janela pertence ao conjunto de dados, e não à definição do limiar.
O Lighthouse CI roda essa mesma auditoria a cada publicação, dentro da esteira, e reprova o envio que estoura o alvo. A biblioteca web-vitals (o pacote que mede os três sinais no aparelho do visitante) envia os resultados ao painel. Reproduza interações no DevTools para investigar INP e confirme o percentil 75 com os dados de campo.
Um orçamento de desempenho (o teto de peso e tempo que a página não pode passar, como o limite do cartão) entra no primeiro sprint. Produto visual sem esse controle degrada em silêncio: cada componente novo soma alguns quilobytes, ninguém mede, e meses depois o site está lento sem um culpado.
Dois instrumentos acompanham o orçamento. O profiling (a gravação de onde o navegador gasta cada milissegundo) aponta a rotina longa por trás do INP. O OpenTelemetry (o padrão aberto para coletar métricas, traces e logs) mostra a mesma lentidão do lado do servidor. Sem os dois, o Lighthouse diz que está lento e ninguém sabe onde.
Imagem tem teto de 150 KB no tamanho em que aparece na tela, em AVIF antes de WebP antes de formato legado. A conversão sai no build, via Sharp ou Squoosh. Uma foto de câmera com vários megabytes no topo da página estoura o orçamento sozinha, o vilão do LCP em quase todo site pequeno.
Fonte variável é o piso: um arquivo substitui de seis a 12 estáticos, com suporte universal, em famílias como Inter, Geist, Roboto Flex, Source Serif e Fraunces. Ela fica hospedada no seu próprio site, com Fontsource e subsetting (o recorte que deixa só os caracteres usados), nunca por chamada remota ao Google Fonts.
A razão vem de um tribunal: a sentença de Munique tratou o envio do IP do visitante ao Google Fonts como vazamento de dado pessoal. Em documento confidencial, como um relatório para o conselho, fonte remota é anti-padrão, porque cada abertura avisa a um terceiro que aquele arquivo foi lido.
O orçamento de desempenho do primeiro sprint
| Item | Teto | Quem mede | Vilão típico |
|---|---|---|---|
| LCP | 2,5 s ou menos no percentil 75 | Lighthouse CI e web-vitals | Imagem grande no topo |
| CLS | 0,1 ou menos no percentil 75 | Lighthouse CI e web-vitals | Imagem sem altura reservada |
| INP | 200 ms ou menos no percentil 75 | web-vitals no aparelho real e profiling | Rotina longa em JavaScript |
| Imagem | 150 KB no tamanho exibido, AVIF antes de WebP | Sharp ou Squoosh no build | Foto de câmera sem conversão |
| Fonte | Um arquivo variável, hospedado no site | Fontsource com subsetting | Chamada remota ao Google Fonts |
| Servidor | Tempo de resposta acompanhado por rota | OpenTelemetry | Consulta lenta que ninguém vê |
Cada linha vira uma reprovação automática na esteira quando o número estoura; sem a linha escrita, o teto é opinião.
Um cardápio publicado direto da câmera do celular, em oito megapixels, vira sozinho o maior contribuinte do LCP. O cliente com internet de rua desiste antes de ver o prato. Corrigir é converter para AVIF e redimensionar, sem trocar de fornecedor, e com o teto de 150 KB escrito a foto seguinte já nasce no tamanho certo.
Rode o Lighthouse no modo celular com rede simulada e anote os itens na ordem de impacto. Peça ao agente a correção na raiz de cada um: imagem em AVIF abaixo de 150 KB, altura reservada, script pesado adiado e fonte variável hospedada com Fontsource.
Escreva os seis tetos como regra de reprovação automática no Lighthouse CI. Só aprove a publicação quando LCP, CLS e INP ficarem dentro do alvo no percentil 75.
A injeção, a chave e a permissão que só valem no servidor
A GitGuardian contou 28,65 milhões de novos segredos escritos direto no código de repositórios públicos em 2025, 34% acima do ano anterior. Boa parte nasce de um pedido simples ao agente: conectar direto numa API externa, o caminho mais curto para o pedido funcionar.
Três defesas de segurança só valem no servidor: limpar o texto que um estranho digita, guardar a chave dos serviços externos e conferir quem pode ver o quê. Cada uma se testa em minutos, e a dependência desatualizada anula as três quando carrega uma falha já pública.
Um levantamento da Veracode, com mais de 150 modelos testados em 80 tarefas e quatro linguagens, mediu duas coisas ao mesmo tempo.
O código gerado por IA compila e roda em mais de 95% dos casos, mas a aprovação em segurança fica em 55%. Ela cai para 15% na injeção de conteúdo malicioso, a falha que nasce no formulário de comentário.
A comparação de dois anos do mesmo levantamento fecha a porta ao atalho: modelos mais novos e maiores melhoraram sintaxe e taxa de compilação sem melhorar a segurança. Trocar de modelo não conserta essa classe de falha, e a revisão continua sendo sua.
O React (a biblioteca que monta a tela a partir do seu código) escapa texto por padrão: uma tag script digitada no comentário aparece inerte, como texto puro. A brecha abre quando o código usa dangerouslySetInnerHTML, que injeta HTML cru, ou funções como eval e document.write.
A correção é limpar esse texto com uma biblioteca madura, como o DOMPurify no navegador ou o sanitize-html no servidor, na hora de gravar. Limpar na gravação passa por um ponto único, e toda tela que mostrar aquele conteúdo, mesmo a que ainda não foi escrita, já recebe o texto limpo.
A sessão fica num cookie httpOnly, fora do localStorage, o armazenamento que qualquer script da página consegue ler. Essa escolha decide o tamanho do estrago quando a limpeza falha.
Se a figura ultrapassar a área visível, deslize para os lados. Pelo teclado, foque a figura e use as setas.
No Next.js (a estrutura que organiza o site em React, com páginas e rotas de servidor), a variável com prefixo NEXT_PUBLIC_ vai dentro do pacote enviado ao navegador. É assim que a chave escapa. Pedir ao agente para conectar direto numa API externa produz esse vazamento, porque é o caminho mais curto.
O conserto é uma rota do próprio servidor, como /api/clima: o componente chama a rota, e o servidor usa a chave para falar com o serviço externo. Chave exposta uma vez só se conserta gerando outra no provedor.
Se a figura ultrapassar a área visível, deslize para os lados. Pelo teclado, foque a figura e use as setas.
Esconder um botão no menu é experiência de uso, e a barreira fica em outro lugar: qualquer pessoa chama a mesma rota pelo terminal, sem passar pela tela. A permissão precisa ser conferida de novo dentro da função que lê ou grava no banco.
O teste mais simples prova isso: troque o identificador na URL da página e veja se aparece o dado de outra pessoa. Se aparecer, a checagem só existe na tela, e a função que toca o dado passa reto.
Dependência tem patch de segurança (a correção que o autor da biblioteca publica) com data, e a lista do seu projeto envelhece sozinha. Uma CVE é o registro público de uma falha de segurança, com número e data, como um recall de carro.
O React corrigiu a CVE-2025-55182, que afeta as versões 19.0.0 a 19.2.2, e quem ficou nelas carrega uma falha que qualquer atacante conhece.
O mesmo vale para quem gera PDF de HTML: o WeasyPrint 69 é obrigatório para quem renderiza HTML não confiável, por causa da CVE-2026-49452. O jsPDF 4.2.1 corrigiu um path traversal (a leitura de arquivo fora da pasta permitida) no build Node. O pdfMake 0.3.11 ganhou setUrlAccessPolicy() contra download de recurso controlado por atacante.
Antes de renderizar HTML de terceiro, o conteúdo passa por sanitize-html. O renderizador roda num sandbox (uma caixa isolada da rede interna) que barra o SSRF, o pedido forjado que usa o seu servidor para alcançar um endereço interno.
No Astro 6, o gerador de sites estáticos, a CSP (a política que lista de onde o site aceita script) vem embutida na configuração. Antes disso, era plugin escrito à mão.
Num escritório de contabilidade que gera o balanço em PDF, o HTML enviado pelo cliente passa por sanitize-html. Só depois ele vai para o renderizador atualizado. Trocar o id do cliente na URL do portal abre o balanço de outra empresa quando a checagem mora só no menu.
Procure dangerouslySetInnerHTML e toda variável com o prefixo NEXT_PUBLIC_ antes de aprovar a próxima entrega. Mova a chamada para uma rota do servidor e confira se a sessão está em cookie httpOnly.
Rode npm audit. Suba o React para fora da faixa 19.0.0 a 19.2.2, o WeasyPrint para a 69, o jsPDF para a 4.2.1 e o pdfMake para a 0.3.11. Só publique quando a auditoria terminar sem vulnerabilidade alta ou crítica conhecida.
Todos os capítulos de Frontends com Vibecoding
- 01Projetar o briefing, o repertório da marca e o custo de manter
- 02Dirigir o prompt e avaliar a entrega do agente
- 03Escolher a stack e projetar suas dependências
- 04Investigar uma stack e priorizar atualizações
- 05Construir a identidade com tokens, CSS moderno e DESIGN.md
- 06Construir componentes, usar o registro e publicar o catálogo
- 07Projetar uma linguagem de ícones e ilustração
- 08Projetar menus, popovers e modais acessíveis
- 09Adaptar o layout ao celular e ao contêiner
- 10Projetar movimento, assinatura e narrativas por rolagem
- 11Preparar imagens, ícones e vídeo para a web
- 12Construir profundidade e dirigir a montagem de vídeo
- 13Construir formulários e estados de interação
- 14Publicar conteúdo encontrável em vários idiomas
- 15Projetar gráficos e painéis pela decisão
- 16Dimensionar tabelas e organizar o cálculo das métricas
- 17Escolher mapas, diagramas e cenas espaciais
- 18Comparar direção visual em Stripe e Apple
- 19Avaliar busca, conversão e padrões de comércio
- 20Auditar acessibilidade e contraste nos dois temas
- 21Validar desempenho, autenticação e segurança
- 22Planejar a modernização e publicar com reversão
- 23Construir o projeto final, medir a cara de IA e revisar
- 24Comparar modelos e interpretar benchmarks
- 25Calcular custo por tarefa e definir governança
- 26Supervisionar o modelo que opera o computador
- 27Configurar ambiente, skills e o contêiner de contexto
- 28Aplicar direção de arte, UX writing e padrões de código
- 29Construir um aplicativo instalável e resiliente
- 30Produzir apresentações e PDF com critérios de entrega