perf-optimizer: corrige duas instruções e cobre o <head>/lote eager - #342
Open
viniciusventura29 wants to merge 1 commit into
Open
perf-optimizer: corrige duas instruções e cobre o <head>/lote eager#342viniciusventura29 wants to merge 1 commit into
<head>/lote eager#342viniciusventura29 wants to merge 1 commit into
Conversation
O catálogo cobre bem opportunity de terceiros (embed, fonte, cache header), mas não tinha nada para o caso em que o LCP é ruim com todo o resto verde — e duas das instruções existentes estão medidas como armadilha. CORREÇÕES em linhas que já existiam: - `uses-responsive-images` mandava "Add explicit width/height". Em componente dirigido por CMS o `width` costuma ser TAMBÉM o alvo de resize passado para o CDN de imagem, então escrever a largura intrínseca faz cada imagem baixar em resolução cheia. A reserva de caixa correta é `aspectRatio`. - `prioritize-lcp-image` parava em eager + fetchpriority. É necessário e não suficiente: se o Load Delay continuar alto, a imagem está perdendo disputa de banda para `modulepreload` (prioridade High) e nenhuma prioridade declarada no markup resolve — o browser agenda por prioridade, não por ordem de documento. - a regra de terceiros mandava deferir para `load` incondicionalmente. Falta o sequenciamento: com LCP > 4 s o TBT é medido FCP->TTI, então o trabalho deferido continua dentro da janela. Medido: score 44 -> 30. LCP/CLS primeiro. LINHAS NOVAS: - `unused-javascript` do NOSSO lote eager: atribuir antes de refatorar, decodificando as `mappings` do `.js.map` e nunca `sourcesContent` (mede o arquivo original e superestimou um pacote em 5x: 499 966 B contra 101 631 B). Procurar módulo dev/admin alcançável por import estático — um comentário dizendo "só carrega quando…" não é gate, só `import()` é — e código de primeira parte que a lista de exclusão do glob "exclui" mas um import nomeado traz de volta. Não splitar por módulo: medido, o JS total quase não mudou (1,727 -> 1,737 MB) e virou 27 requests a mais sem compressão de stream, score local 42 -> 20. - `unsized-images` / CLS de banner de CMS: checar o componente primeiro; se ele já aceita dimensão, o que falta é conteúdo (1192 de 1198 banners sem valor). Ler a dimensão real do header do arquivo com `Range: bytes=0-65535`. Se o conteúdo é regerado por bot, o fix tem de ser script de post-generate — um refresh de conteúdo desfez em silêncio um fix de CLS já mergeado (0,00 -> 0,95, reproduzido duas vezes). - `dom-size`: ranquear por bytes TRANSFERIDOS e contagem de nós, nunca por share de bytes crus. Markup SSR repetitivo é o caso ótimo do Brotli — um bloco de navegação que era 64% dos bytes crus do documento valia ~25% do documento comprimido (~16 KB), enquanto um chunk de JS na mesma página era 254 KB na rede. E quando vale cortar, paga em parse/DOM/hidratação: verificar em TBT/INP. REGRA NOVA, e é a mais importante porque este agente edita `<head>` e `__root`: **não se muta o que o framework renderizou — muda-se a FONTE do render, em todos os environments que renderizam.** Apagar tag do HTML servido é mismatch: 13 de 4300 nós sobreviveram. Client-only quando o SSR tem de ficar byte-idêntico; client E ssr quando os dois renderizam a tag, porque aí mexer em um só É o mismatch. VERIFY ganhou duas checagens: - afirmar o que deve SOBREVIVER, não só o que saiu: depois de qualquer transform no `<head>` ou no manifest, procurar o script de entrada do cliente no HTML servido. Uma mudança dessa classe produziu documento de 572 KB perfeito, `<head>` limpo, zero erro de console, zero aviso de build — e página que nunca hidratava. Contar a tag removida teria passado. - um run de Lighthouse não é resultado: TBT variou 0,53 s -> 5,91 s em 5 runs do mesmo build. Mediana de 5, run de controle no base antes de chamar de regressão, e evidência estrutural acima de score. A mecânica profunda vai para `skills/knowledge/perf/head-priority-and-hydration.md` (padrão que o próprio agente já usa com `render-location.md` e `edge-caching.md`), com linha no `skills/knowledge/INDEX.md`. Fica lá o que não cabe numa linha de tabela: por que prioridade vence ordem, como os dois environments se decidem, a quebra silenciosa do manifest passo a passo, e as armadilhas de medição (preview local sem compressão, build local de main != build deployed de main, cache persistido do worker, warmup de cache segmentado). Números de before/after medidos numa migração real. Sem identificar o site. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
JonasJesus42
approved these changes
Sep 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
O catálogo do
perf-optimizercobre bem opportunity de terceiros (embed, fonte, cache header), mas não tinha nada para o caso em que o LCP é ruim com todo o resto verde — e duas das instruções que já estão lá estão medidas como armadilha.Tudo abaixo é before/after medido numa migração real. Sem identificar o site.
Correções em linhas que já existiam
uses-responsive-imageswidth/height"widthcostuma ser também o alvo de resize passado ao CDN de imagem — escrever a largura intrínseca faz cada imagem baixar em resolução cheia. A reserva de caixa correta éaspectRatioprioritize-lcp-imagefetchpriority="high"modulepreload(High) — o browser agenda por prioridade, não por ordem de documento. Medido: hoist do preload não moveu nada, Load Delay ficou em 5239 msloadif it isn't already"E na mesma linha de imagem, para quando for preciso cortar bytes: menos resolução a qualidade alta domina mesma resolução a qualidade baixa — por SSIM, 620w@high foi menor (57 219 B contra 60 708 B) e mais fiel (0,9412 contra 0,9340) que 824w@low.
Linhas novas no catálogo
unused-javascriptdo NOSSO lote eager. Atribuir antes de refatorar: decodificar asmappingsdo.js.map, nuncasourcesContent— este mede o arquivo original e superestimou um pacote em 5x (499 966 B contra 101 631 B), mandando você atrás de bytes que o bundler já removeu. Depois procurar duas coisas: módulo dev/admin alcançável por import estático (um comentário dizendo "só carrega quando…" não é gate; sóimport()é) e código de primeira parte que a lista de exclusão do glob "exclui" mas um import nomeado traz de volta. Não splitar por módulo: medido, o JS total quase não mudou (1,727 → 1,737 MB) e virou 27 requests a mais sem compressão de stream — score local 42 → 20.unsized-images/ CLS de banner de CMS. Checar o componente primeiro: se ele já aceita dimensão, o que falta é conteúdo (1192 de 1198 banners sem valor). Não chutar razão — ler a dimensão real do header do arquivo comRange: bytes=0-65535. E se o conteúdo é regerado por bot, o fix tem de ser script de post-generate: um refresh de conteúdo desfez em silêncio um fix de CLS já mergeado (0,00 → 0,95, reproduzido duas vezes).dom-size. Ranquear por bytes transferidos e contagem de nós, nunca por share de bytes crus. Markup SSR repetitivo é o caso ótimo do Brotli: um bloco de navegação que era 64% dos bytes crus do documento valia ~25% do documento comprimido (~16 KB), enquanto um chunk de JS na mesma página era 254 KB na rede. Quando vale cortar, paga em parse/DOM/hidratação — verificar em TBT/INP, e o que um crawler precisa ler continua server-rendered.Regra nova — a mais importante, porque este agente edita
<head>e__rootApagar tag do HTML servido é mismatch: medido, 13 de 4300 nós sobreviveram. Client-only quando o SSR tem de ficar byte-idêntico; client e ssr quando os dois renderizam a tag, porque aí mexer em um só é o mismatch. E o build tem de falhar se o transform não casou onde deveria.
Verify ganhou duas checagens
<head>ou no manifest, procurar o script de entrada do cliente (import("/assets/main-*.js")) no HTML servido. Uma mudança dessa classe produziu documento de 572 KB perfeito,<head>limpo, zero erro de console, zero aviso de build — e página que nunca hidratava. Contar a tag removida teria passado no check.Onde a profundidade foi parar
skills/knowledge/perf/head-priority-and-hydration.md(novo) — mesmo padrão que o agente já usa comrender-location.mdeedge-caching.md, com linha noskills/knowledge/INDEX.md. Lá está o que não cabe numa célula de tabela: por que prioridade vence ordem, como se decide entre os dois environments, a quebra silenciosa do manifest passo a passo (getStartManifestpoda a rota sempreloads/assets→__root__some → oif (rootRoute)deixa de emitir o script de entrada), e as armadilhas de medição — preview local sem compressão, build local demain≠ build deployed demain(307 kB de diferença que não existe), cache persistido do worker, warmup de cache segmentado por device.skills/knowledge/perf/não está na lista de vendorização doscripts/sync-skills.ts(sótanstack/*evtex/*), então o arquivo novo não gera drift.Diff
agents/perf-optimizer.mdskills/knowledge/perf/head-priority-and-hydration.mdskills/knowledge/INDEX.mdRepo público: passei um scan por identificador de cliente, URL interna e path de repo privado antes de subir — nada vazou. Se preferirem atribuição explícita à migração de origem, é só pedir que eu adiciono.
🤖 Generated with Claude Code
Summary by cubic
Updates the
perf-optimizeragent catalog with measured corrections to two existing instructions and new coverage for the case where LCP is bad while everything else is green.uses-responsive-imagesnow recommendsaspectRatioinstead of explicitwidth/height, since in CMS-driven componentswidthis often the CDN resize target and writing the intrinsic width forces full-resolution downloads.unused-javascriptin the own eager bundle (attribute via.js.mapmappings, neversourcesContent; don't split per module),unsized-images/CLS on CMS banners (content is usually the gap, not the component), anddom-size(rank by transfer bytes and node count, not raw byte share).skills/knowledge/perf/head-priority-and-hydration.mddocuments why priority beats document order, how to patch client vs. ssr environments safely, the silent hydration-break failure mode, and measurement traps.Migration
<head>transforms or the eager bundle; it replaces the need to restate the mechanics in commit messages.Written for commit 2b4f8d2. Summary will update on new commits.