- 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
Casos de uso e significado do nome
1 comentários
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
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...
georges [at] divriots [dot] com
Isso me lembra o módulo PageSpeed para Apache e Nginx: https://developers.google.com/speed/pagespeed/module
O repositório no GitHub também foi arquivado: https://github.com/apache/incubator-pagespeed-ngx
Será que ele foi movido para outro lugar?
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
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-settingsdefinido no CSSFico 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
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
:hoversempre como não críticosMas 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
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?
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
loading="lazy"nativo do navegadorNo 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
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
Você pode desativar esse recurso definindo
browserlistcomo string vazia: https://jampack.divriots.com/features/browser-compatibility/