<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ary Ribeiro</title>
    <description>The latest articles on DEV Community by Ary Ribeiro (@aryribeiro).</description>
    <link>https://dev.to/aryribeiro</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4122599%2F68480ab2-554e-41af-971d-73ddbfff1c4e.png</url>
      <title>DEV Community: Ary Ribeiro</title>
      <link>https://dev.to/aryribeiro</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aryribeiro"/>
    <language>en</language>
    <item>
      <title>O que descobri medindo o Core Web Vitals de um portal de notícias em hospedagem compartilhada</title>
      <dc:creator>Ary Ribeiro</dc:creator>
      <pubDate>Tue, 15 Sep 2026 01:11:51 +0000</pubDate>
      <link>https://dev.to/aryribeiro/o-que-descobri-medindo-o-core-web-vitals-de-um-portal-de-noticias-em-hospedagem-compartilhada-ce5</link>
      <guid>https://dev.to/aryribeiro/o-que-descobri-medindo-o-core-web-vitals-de-um-portal-de-noticias-em-hospedagem-compartilhada-ce5</guid>
      <description>&lt;p&gt;Sete dias medindo um portal de notícias em WordPress numa hospedagem compartilhada. As três causas reais estavam fora da lista de suspeitos do Google, e o painel de diagnóstico apontou a imagem errada duas vezes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A apuração é do &lt;a href="https://diretonoticias.com.br" rel="noopener noreferrer"&gt;Direto Notícias&lt;/a&gt;, portal de Guarapari, no Espírito Santo. Os números foram medidos entre 6 e 14 de setembro de 2026 e estão datados por isso.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;O portal estava reprovado no Core Web Vitals do Google no celular. O maior elemento da tela levava 2,8 segundos para aparecer, contra o limite de 2,5. Isso barra a entrada no Discover, que é de onde vem tráfego de descoberta para veículo pequeno.&lt;/p&gt;

&lt;p&gt;A parte fácil do diagnóstico o próprio Google entrega: o relatório aponta JavaScript bloqueando a renderização, imagens pesadas e refluxo forçado. A parte difícil é descobrir qual desses itens é a causa e qual é sintoma. Passei sete dias medindo, e as três causas reais não estavam na lista de suspeitos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Primeira: o site gastava o servidor gerando páginas para ninguém
&lt;/h2&gt;

&lt;p&gt;O plugin de cache tinha uma fila de pré-carregamento ligada. Ela completava entre 130 e 180 páginas a cada quinze minutos, o dia inteiro, com quase sete mil pendentes e mais de dois mil erros acumulados.&lt;/p&gt;

&lt;p&gt;Numa hospedagem compartilhada, isso não é otimização, é concorrência. Medi a home já em cache respondendo em 1,2 segundo enquanto a fila trabalhava. A mesma home, com a fila parada, responde em 0,22.&lt;/p&gt;

&lt;p&gt;O detalhe que quase me enganou: eu achava que a página estava fria. Não estava. O arquivo de cache tinha sido gravado horas antes. O servidor é que estava ocupado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Segunda: 100% dos cliques de celular caíam em matérias, e nenhum na home
&lt;/h2&gt;

&lt;p&gt;Puxei o Search Console por página e por dispositivo. Em 28 dias, todos os cliques de celular vindos da busca caíram em matérias espalhadas pelo acervo. A home recebeu zero.&lt;/p&gt;

&lt;p&gt;Isso inverte a estratégia inteira. Eu vinha otimizando a home, que é o que todo mundo mede. Quem decide a nota de campo é o acervo, e o acervo estava sempre frio: cada publicação limpava o cache do site todo, o portal publica dezenas de textos por dia, e o cache vive sete dias.&lt;/p&gt;

&lt;p&gt;A correção foi cirúrgica, por filtro: publicação nova limpa home e categoria; atualização de texto limpa apenas aquela matéria. Mais um aquecedor que mantém quentes as matérias que o Google efetivamente manda gente, com a lista vinda do próprio Search Console.&lt;/p&gt;

&lt;p&gt;E uma regra que ficou: disparar uma requisição não é aquecer. Requisição não bloqueante com tempo limite curto é descartada pela hospedagem antes de o cache gravar. Só o arquivo em disco prova. O aquecedor confere a data do arquivo e registra se gravou ou não.&lt;/p&gt;

&lt;h2&gt;
  
  
  Terceira: a capa invisível que era baixada com prioridade máxima
&lt;/h2&gt;

&lt;p&gt;O tema imprimia a imagem de destaque num bloco próprio, acima do texto. Meses antes, uma regra de CSS tinha escondido esse bloco em todos os aparelhos, porque a mesma foto já aparecia no corpo da matéria.&lt;/p&gt;

&lt;p&gt;Esconder por CSS não impede o download. O navegador baixava 24 KB com prioridade alta para uma imagem que ninguém via, disputando banda com a foto que o leitor realmente enxerga.&lt;/p&gt;

&lt;p&gt;Fica a lição: compare sempre o que está &lt;strong&gt;visível&lt;/strong&gt; com o que está sendo &lt;strong&gt;baixado&lt;/strong&gt;. São listas diferentes, e a segunda é a que custa.&lt;/p&gt;

&lt;h2&gt;
  
  
  O painel de causas do Google apontou a imagem errada. Duas vezes
&lt;/h2&gt;

&lt;p&gt;O relatório do PageSpeed acusava a capa da matéria de "elemento de imagem sem tamanho definido", e depois o logotipo do cabeçalho.&lt;/p&gt;

&lt;p&gt;Testei segurando cada imagem por seis segundos com o navegador controlado e medindo a caixa antes e depois de carregar. Nos dois casos a caixa já estava reservada, porque os atributos de largura e altura geram proporção. Falso positivo nos dois.&lt;/p&gt;

&lt;p&gt;A causa real só apareceu ao instrumentar o próprio navegador com observador de deslocamento de layout, processador estrangulado e rede lenta, olhando quais nós se moviam. Eram dois:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A fonte dos títulos. Em Arial o título ocupava três linhas; quando a fonte condensada chegava, virava duas, e tudo abaixo subia trinta pixels. Resolvido com pré-carregamento da fonte e uma fonte reserva com métrica ajustada, para as duas ocuparem a mesma altura.&lt;/li&gt;
&lt;li&gt;O anúncio automático, que insere um bloco entre a foto e o primeiro parágrafo depois de a página já estar montada. Esse eu não toquei: é a receita do veículo.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  O que eu mediria diferente da próxima vez
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nota de laboratório é ruído quando há anúncio.&lt;/strong&gt; A mesma matéria, sem nenhuma mudança no código, deu 89 e depois 66 em rodadas seguidas, só porque o anúncio sorteado travou a thread por mais tempo. Compare tempo de carregamento e deslocamento de layout, nunca a nota.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Medir logo após limpar o cache mede página fria.&lt;/strong&gt; Duas medições minhas foram para o lixo por isso.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amostra de um não mede nada.&lt;/strong&gt; Registrei como lição que o compressor de imagens não gerava formato moderno para miniaturas. Uma semana depois conferi mês a mês e estava errado: ele gera. Minha conclusão tinha saído de um único arquivo, e esse arquivo era de um lote que nunca chegou a ser processado. Voltei e corrigi o registro.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Campo é janela de 28 dias.&lt;/strong&gt; Nada do que se faz hoje aparece antes de semanas. No dia das mudanças o número de campo até piorou, porque a janela ainda carregava os dias ruins.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Onde chegou
&lt;/h2&gt;

&lt;p&gt;No laboratório, em celular: a home saiu de 93 para 97 e a matéria passou a carregar o maior elemento em 2,2 segundos, contra 2,4 a 2,6 antes. O bloqueio de renderização caiu de cerca de dois segundos para pouco mais de um. As imagens do acervo recente passaram a ser servidas em formato moderno, com 29% menos peso.&lt;/p&gt;

&lt;p&gt;O número que decide, o de campo, só será lido no começo de outubro. Até lá, não se mexe em mais nada, porque cada mudança nova suja a leitura.&lt;/p&gt;




&lt;p&gt;Se o assunto for útil, o portal fica em &lt;a href="https://diretonoticias.com.br" rel="noopener noreferrer"&gt;diretonoticias.com.br&lt;/a&gt; e a página de transparência explica quem o mantém e como ele se financia.&lt;/p&gt;

</description>
      <category>webperf</category>
      <category>wordpress</category>
      <category>php</category>
      <category>performance</category>
    </item>
    <item>
      <title>Como a AtlasDocs roda mais de 130 ferramentas sem enviar nada ao servidor</title>
      <dc:creator>Ary Ribeiro</dc:creator>
      <pubDate>Sat, 12 Sep 2026 21:09:28 +0000</pubDate>
      <link>https://dev.to/aryribeiro/como-o-atlasdocs-roda-138-ferramentas-de-arquivo-sem-enviar-nada-ao-servidor-419f</link>
      <guid>https://dev.to/aryribeiro/como-o-atlasdocs-roda-138-ferramentas-de-arquivo-sem-enviar-nada-ao-servidor-419f</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Este artigo foi publicado primeiro no blog da AtlasDocs: &lt;a href="https://atlasdocs.io/blog/como-o-atlasdocs-processa-arquivos-no-navegador" rel="noopener noreferrer"&gt;https://atlasdocs.io/blog/como-o-atlasdocs-processa-arquivos-no-navegador&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Quando alguém junta dois PDFs, extrai o áudio de um vídeo ou lê o texto de uma foto no &lt;a href="https://atlasdocs.io" rel="noopener noreferrer"&gt;AtlasDocs&lt;/a&gt;, o arquivo não viaja para lugar nenhum. O navegador baixa o programa que faz o trabalho, e o trabalho acontece na memória da máquina de quem usa. O resultado nasce ali e é salvo direto no dispositivo. Não existe upload, não existe fila em servidor, e não existe uma cópia do documento guardada em algum lugar esperando ser apagada.&lt;/p&gt;

&lt;p&gt;A página de privacidade diz isso em uma frase. Este texto explica como é possível, e onde estão os limites.&lt;/p&gt;

&lt;h2&gt;
  
  
  WebAssembly é o que torna isso viável
&lt;/h2&gt;

&lt;p&gt;A base é o WebAssembly, que permite rodar dentro do navegador programas escritos originalmente para computador. É assim que motores conhecidos passaram a funcionar numa aba:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;7-Zip&lt;/strong&gt; para arquivos compactados (via 7z-wasm)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FFmpeg&lt;/strong&gt; para vídeo e áudio (via ffmpeg.wasm)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tesseract&lt;/strong&gt; para reconhecer texto em imagens (via tesseract.js)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQLite&lt;/strong&gt; para bancos de dados (via sql.js)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leitura de RAR&lt;/strong&gt; (via node-unrar-js)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MediaInfo&lt;/strong&gt; para inspecionar mídia (via mediainfo.js)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para PDF, duas bibliotecas de código aberto escritas para o navegador: &lt;strong&gt;pdf-lib&lt;/strong&gt;, que edita o documento, e &lt;strong&gt;pdf.js&lt;/strong&gt;, mantida pela Mozilla, que desenha as páginas na tela.&lt;/p&gt;

&lt;h2&gt;
  
  
  O motor pesado só carrega quando alguém pede
&lt;/h2&gt;

&lt;p&gt;Reconhecer texto numa foto exige um motor grande, mais o modelo de idioma. Se ele viesse junto com a página, o site ficaria lento para todo mundo, inclusive para quem só quer girar um PDF.&lt;/p&gt;

&lt;p&gt;Por isso cada ferramenta carrega o próprio motor sob demanda, no primeiro uso. No código isso é um &lt;code&gt;import()&lt;/code&gt; dinâmico na camada de infraestrutura, do tipo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;optimizeForSocial&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/infrastructure/image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A página inicial pesa o mesmo com ou sem as ferramentas pesadas, e um gate de peso no pipeline de testes impede que uma versão suba se a home ou uma ferramenta ficar mais pesada que o limite. É também por isso que o primeiro uso de uma ferramenta de vídeo demora alguns segundos a mais: é o download do motor, uma única vez, que o navegador guarda em cache.&lt;/p&gt;

&lt;p&gt;Os motores ficam hospedados no próprio site, com cópias de reserva em CDNs públicas caso a primeira falhe. Se você abriu um RAR lá, o motor veio do servidor; o seu arquivo, não.&lt;/p&gt;

&lt;h2&gt;
  
  
  FFmpeg inteiro dentro da aba
&lt;/h2&gt;

&lt;p&gt;Extrair áudio, juntar vídeos, trocar formato, colocar marca d'água: tudo usa o FFmpeg, o mesmo programa de estúdios e serviços de streaming. A versão para navegador roda num Web Worker, então a interface continua respondendo enquanto o vídeo é processado.&lt;/p&gt;

&lt;p&gt;O limite é a memória do dispositivo. Um vídeo de várias centenas de megabytes pode não caber num celular simples. Quando não cabe, a conversão falha e a ferramenta mostra uma mensagem de erro. Nada é enviado para fora para tentar de novo.&lt;/p&gt;

&lt;h2&gt;
  
  
  RAR: ler sim, criar não
&lt;/h2&gt;

&lt;p&gt;RAR é formato fechado. A licença permite ler e extrair, mas não criar arquivos RAR fora do programa oficial. Por isso a plataforma AtlasDocs abre, extrai e converte RAR para ZIP ou 7z, mas não gera RAR. Foi uma decisão de respeitar a licença, não uma limitação técnica.&lt;/p&gt;

&lt;h2&gt;
  
  
  As duas exceções, ditas na própria ferramenta
&lt;/h2&gt;

&lt;p&gt;Duas ferramentas enviam o arquivo ao servidor: converter documentos do Word, Excel e PowerPoint para PDF, e visualizar esses mesmos documentos. O motivo é técnico. Não existe hoje um programa para navegador que abra arquivos do Office com fidelidade; o que faz isso bem é o LibreOffice, que precisa de um servidor. Nesses dois casos o arquivo é convertido e descartado em seguida, e a ferramenta mostra um aviso na tela antes do envio. As outras mais de 130, continuam no dispositivo.&lt;/p&gt;

&lt;p&gt;Há mais dois pontos de contato com o servidor, e nenhum vê arquivos. O assistente de ajuda envia a pergunta digitada para um modelo de linguagem, e só ela. E o contador de visitas registra apenas o caminho da página: sem cookie, sem IP guardado, sem identificação de pessoa.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como conferir por conta própria
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Abra qualquer ferramenta da AtlasDocs no computador e pressione F12.&lt;/li&gt;
&lt;li&gt;Vá na aba &lt;strong&gt;Network&lt;/strong&gt; e deixe a lista de requisições aberta.&lt;/li&gt;
&lt;li&gt;Envie um arquivo e execute a operação até baixar o resultado.&lt;/li&gt;
&lt;li&gt;Olhe a lista: você verá o download do motor e das páginas do site, e nenhum POST com o conteúdo do seu arquivo. As duas exceções mostram o envio, como o aviso na tela diz.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Como o código é mantido
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;TypeScript no modo estrito, cerca de 76 mil linhas, Next.js 16 e React 19.&lt;/li&gt;
&lt;li&gt;Cada regra de negócio vive em um módulo separado da interface (capabilities e pipelines), o que permite reaproveitar a mesma conversão em ferramentas diferentes.&lt;/li&gt;
&lt;li&gt;A cada versão rodam 737 testes unitários e 176 testes em navegador real, que abrem as páginas, enviam arquivos de verdade e conferem o resultado.&lt;/li&gt;
&lt;li&gt;Lighthouse no celular entre 94 e 97, medido em produção a cada release.&lt;/li&gt;
&lt;li&gt;Interface em português, inglês e espanhol.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  O que eu faria diferente hoje
&lt;/h2&gt;

&lt;p&gt;O gate de peso e a medição de Lighthouse por release entraram tarde, depois que a página inicial já tinha chegado a 68 pontos no celular. Ter isso desde o primeiro commit teria evitado um dia inteiro de otimização. Se você está começando algo parecido, coloque o orçamento de peso antes da segunda ferramenta.&lt;/p&gt;

&lt;p&gt;Se tiver alguma dúvida sobre como uma conversão específica funciona, pergunte nos comentários. A plataforma AtlasDocs está em &lt;a href="https://atlasdocs.io" rel="noopener noreferrer"&gt;https://atlasdocs.io&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>braziliandevs</category>
      <category>privacy</category>
      <category>webassembly</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
