4 pontos por GN⁺ 2024-03-26 | 1 comentários | Compartilhar no WhatsApp
  • Jampack é uma ferramenta de pós-processamento que recebe a saída de Static Site Generators e otimiza a experiência do usuário e as pontuações de Core Web Vitals; não é um bundler nem um framework
  • Ele transforma <img> e <picture> em HTML em imagens responsivas e adiciona automaticamente formatos como WebP e AVIF, srcset, sizes, width, height, loading="lazy", decoding="async" etc.
  • Imagens de CDN podem ser tratadas de forma responsiva com srcset baseado em parâmetros de URL, e imagens externas podem ser baixadas para _jampack e substituídas por imagens locais otimizadas
  • Assets above-the-fold são tratados com alta prioridade, imagens pequenas são embutidas no HTML, e imagens e iframes below-the-fold recebem carregamento preguiçoso
  • A aplicação é feita executando npx @divriots/jampack./dist na pasta de saída do build do site estático; em uma segunda passada, ele também compacta CSS, JS, HTML, SVG e imagens

O papel do Jampack

  • Jampack recebe como entrada a saída criada por um Static Site Generator, ou SSG, e otimiza sites estáticos
  • O objetivo é melhorar a experiência do usuário e as pontuações de Core Web Vitals
  • O README diferencia o Jampack dizendo que ele “não é um bundler nem um framework”
  • O texto de introdução está disponível em Read the introduction blog post

Otimização de imagens

  • Um <img> comum é convertido em uma imagem responsiva
    • Para o src original, ele cria um arquivo WebP e adiciona srcset
    • São adicionados atributos como sizes="100vw", loading="lazy", decoding="async", width e height
  • Elementos <picture> são transformados em uma estrutura responsiva que inclui vários formatos de imagem
    • É adicionado um <source type="image/avif"> para AVIF
    • É adicionado um <source type="image/webp"> para WebP
    • O <img> original também recebe srcset, sizes, loading, decoding, width e height
  • A funcionalidade de otimização de imagens aponta para a documentação optimize-images, mas esse link no README é um caminho relativo

Tratamento de imagens de CDN e externas

  • Imagens de CDN podem receber um srcset responsivo mantendo a URL remota
    • O exemplo cria candidatos em várias larguras adicionando parâmetros w, fit=min e auto=format a uma URL de imagem do Unsplash
    • A imagem original também recebe loading="lazy", decoding="async" e sizes="100vw"
  • Imagens externas podem ser baixadas e depois substituídas por arquivos locais otimizados
    • O exemplo troca uma imagem externa do Unsplash por um caminho como _jampack/ab99b9d280ce4cf7cfc810b59f3a7739.jpg.webp
    • A imagem convertida inclui width, height, srcset, sizes, loading e decoding

Otimização de above-the-fold, CSS e links

  • O Jampack otimiza separadamente assets above-the-fold
    • Imagens são carregadas com prioridade mais alta
    • Imagens pequenas são embutidas no HTML
  • Assets below-the-fold recebem carregamento preguiçoso
    • Imagens e iframes são alvos de lazy load
  • O Critical CSS é embutido no HTML
    • O objetivo é evitar FOUC, que pode ocorrer durante o download e o parsing da folha de estilos
    • O restante do CSS é carregado de forma preguiçosa
  • O prefetch de links é um recurso para acelerar futuras navegações entre páginas
    • Ele pode ser tratado dinamicamente quando links entram no viewport usando quicklink

Compactação de assets e modo de execução

  • Em uma segunda passada, o Jampack compacta todos os assets que não foram alterados, mantendo o mesmo nome e o mesmo formato
  • As ferramentas de compactação por extensão são as seguintes
  • Quando o site estático está na pasta dist, execute com o seguinte comando
npx @divriots/jampack ./dist
  • Opções adicionais podem ser conferidas em CLI options

Casos de uso e significado do nome

1 comentários

 
GN⁺ 2024-03-26
Comentários no Hacker News
  • Era exatamente a ferramenta que eu estava procurando. Eu vinha escrevendo scripts baseados em Sharp para fazer esse tipo de otimização de imagens, mas o Jampack substitui isso completamente e funciona muito melhor
    Depois de gerar um site estático com Quarto e rodar o Jampack, o tamanho da pasta caiu 32%, e ainda não notei nenhuma desvantagem evidente
    Segundo o PageSpeed Insights, antes do Jampack o mobile tinha desempenho 52, acessibilidade 73, práticas recomendadas 100 e SEO 85, e no desktop era desempenho 90, acessibilidade 75, práticas recomendadas 100 e SEO 82
    Depois da aplicação, apareceu mobile com desempenho 49, acessibilidade 80, práticas recomendadas 100, SEO 92, e desktop com desempenho 85, acessibilidade 82, práticas recomendadas 100 e SEO 91

    • As pontuações do Lighthouse e do PageSpeed Insights podem oscilar. Ao fazer esse tipo de comparação de desempenho, é melhor executar várias vezes e olhar a mediana
      Existe até material dizendo que “a mediana de 5 execuções do Lighthouse é duas vezes mais estável do que 1 execução”: https://developers.google.com/web/tools/lighthouse/variabili...
    • Fico feliz que tenha gostado. Ainda assim, eu esperava que as métricas de desempenho melhorassem mais. Se puder, gostaria de dar uma olhada no resultado do site estático antes de aplicar o Jampack
      georges [at] divriots [dot] com
  • Isso me lembra o módulo PageSpeed para Apache e Nginx: https://developers.google.com/speed/pagespeed/module

  • Uau, gostei bastante disso. Pretendo testar
    Se alguém achou ruim, queria que apontasse os defeitos. Para mim, parece algo parecido com compilar C para assembly altamente otimizado, e claramente parece uma ferramenta que assume um trabalho que eu não gostaria de fazer manualmente

    • Se precisamos entregar algo como assembly altamente otimizado em HTML e CSS, não sei se estamos indo na direção certa
      Acho que deveríamos poder escrever o HTML e o CSS mais simples e intuitivos possível, e os navegadores de todos os dispositivos simplesmente renderizarem bem
      Se realmente precisamos entregar artefatos otimizados nesse nível, então seria melhor pular HTML e CSS de vez, distribuir WebAssembly altamente otimizado e deixar o desenvolvedor usar a linguagem que quiser
  • Seria bom ter uma forma de fazer subset de fontes com base no intervalo Unicode da saída do SSG, e fixar eixos OpenType com base no font-feature-settings definido no CSS

    • Sim, há muita coisa interessante para fazer com fontes. No TODO existe a tarefa de adicionar automaticamente substituições por fontes do sistema com métricas corretas para melhorar o CLS automaticamente
      Fico na dúvida se isso é o que você quis dizer com “fixar eixos OpenType com base em font-feature-settings”, ou se você estava falando de outra coisa
      Também quero fazer otimização de subset de fontes, mas ainda não sei bem o quanto isso melhoraria. Fico curioso para saber se você já fez isso manualmente
    • Se você usar fontes do navegador/sistema, pode otimizar para tamanho de fonte zero, então nem sei se vale a pena
  • Acho interessante a ideia de identificar o CSS crítico que deve ser embutido inline em vez de ficar numa folha de estilo separada
    Eu esperava que houvesse alguma forma baseada em princípios para distinguir CSS crítico de não crítico. Por exemplo, tratar efeitos de interação do usuário como :hover sempre como não críticos
    Mas a biblioteca usada renderiza a página e faz a melhor estimativa possível sobre quais regras são críticas, então isso me decepciona um pouco: https://github.com/GoogleChromeLabs/critters

    • Se o CSS tiver menos de 50KB, é só embutir inline. Se você tem mais de 50KB de CSS, provavelmente está fazendo algo errado
      Claro, se você estiver embutindo fontes também, dá para entender, mas se só os estilos passam de 50KB, na maioria dos casos o caminho está errado
      Falando sério, inline é incrivelmente bom para desempenho mesmo comparado a cache aquecido, e o ponto em que folhas de estilo ou scripts externos passam a ser melhores é bem mais alto do que se imagina, chegando a centenas de KB segundo padrões comuns do mercado
      O conceito de CSS crítico parece uma abordagem derrotista para recuperar um pouco do desempenho desperdiçado, em vez de corrigir o problema na raiz
      Dito isso, isso não é uma técnica sistemática, mas um julgamento baseado em experiência leve e observações. Seria bom se alguém medisse esse conceito de forma mais adequada, mas não acho que vou ser eu
  • Isso parece cobrir vários dos casos de uso pelos quais as pessoas escolhem SSG e plugins em primeiro lugar. Ainda mais se estiverem escolhendo Astro ou Eleventy
    Existe algum motivo para preferir isso como uma etapa separada de pós-build? Parece um trade-off: o rebuild durante o desenvolvimento fica mais rápido, mas você talvez deixe passar bugs sutis que surgem ao adicionar coisas como declaração de width em imagens

  • Como alguém que odeia trabalhar com layout de páginas web e se recusa a aprender, mas às vezes precisa fazer isso mesmo assim, essa ferramenta parece ótima

  • Parece bom. Mas, pessoalmente, eu não gosto de ter que esperar imagens quando faço scroll da página para abaixo da primeira dobra
    O comportamento padrão carrega em segundo plano o restante do conteúdo abaixo da primeira dobra depois que o conteúdo visível inicialmente termina?

    • Não. Ele aproveita o lazy loading nativo do navegador. Os principais navegadores tratam o atributo loading="lazy" como “não carregue esta imagem/iframe até ela estar quase visível”: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/im...
      Porém, como a proporção é inserida inline, o layout não muda depois que o carregamento termina. Ou seja, evita o maior pecado do lazy loading
    • Como o @lelandfe apontou, o Jampack usa o loading="lazy" nativo do navegador
      No momento não há como mudar esse comportamento, mas poderíamos adicionar uma opção para pré-carregar em segundo plano as imagens abaixo da primeira dobra depois que a página inteira terminar de carregar. É uma ideia muito boa
      Só me preocupa acabar carregando imagens desnecessárias no fim da página. Como opção, cada um poderia ativar ou desativar, então parece razoável
  • Quais são alguns geradores de sites estáticos usados em produção? Acho que eu conseguiria otimizar ainda mais a saída com essa ferramenta
    Por exemplo, ontem passei o dia inteiro seguindo exemplos para transformar um site React do Divjoy em HTML simples e servir isso de um bucket S3. Não imaginava que seria tão difícil e ainda estou apanhando
    No ideal, queria algo que fizesse deploy automático para um bucket S3 e até conectasse o domínio. Dói ter pago por algo, o desenvolvedor sumiu e o Discord ficou abandonado. Por isso sempre tendo a preferir FOSS

    • Tem Hugo, Zola e Jekyll
      Até certo ponto, eles já têm parte desse tipo de funcionalidade
  • Em um dos meus projetos, não houve grande mudança. Por exemplo, o tamanho total do bundle diminuiu, mas o tamanho gzip aumentou, então na prática foi perda líquida para mim
    Ainda assim, a melhoria de CSS parece realmente ter ajudado
    A ideia parece excelente, e se o projeto tivesse imagens, provavelmente teria ajudado

    • Se não houver imagens, realmente os ganhos são limitados. Além disso, ele melhora automaticamente a compatibilidade entre navegadores, então o tamanho final do CSS também pode aumentar
      Você pode desativar esse recurso definindo browserlist como string vazia: https://jampack.divriots.com/features/browser-compatibility/