4 puntos por GN⁺ 2024-03-26 | 1 comentarios | Compartir por WhatsApp
  • Jampack es una herramienta de posprocesamiento que toma la salida de un Static Site Generator para optimizar la experiencia de usuario y las puntuaciones de Core Web Vitals; no es un bundler ni un framework
  • Convierte <img> y <picture> de HTML en imágenes responsivas, y agrega automáticamente formatos como WebP y AVIF, además de srcset, sizes, width, height, loading="lazy", decoding="async", etc.
  • Las imágenes en CDN pueden volverse responsivas con srcset basado en parámetros de URL, y las imágenes externas pueden descargarse bajo _jampack para convertirse en imágenes locales optimizadas
  • Los recursos above-the-fold se procesan con alta prioridad y las imágenes pequeñas se insertan inline en el HTML, mientras que las imágenes e iframes below-the-fold se cargan de forma diferida
  • Se aplica ejecutando npx @divriots/jampack ./dist sobre la carpeta de salida del build del sitio estático, y en una segunda pasada también comprime CSS, JS, HTML, SVG e imágenes

Qué hace Jampack

  • Jampack toma como entrada el resultado generado por un Static Site Generator, es decir, un SSG, y optimiza el sitio web estático
  • El objetivo es mejorar la experiencia de usuario y las puntuaciones de Core Web Vitals
  • El README diferencia a Jampack diciendo que “no es un bundler ni un framework”
  • La introducción está disponible en Read the introduction blog post

Optimización de imágenes

  • Un <img> común se transforma en una imagen responsiva
    • Genera un archivo WebP para el src original y agrega srcset
    • Añade atributos como sizes="100vw", loading="lazy", decoding="async", width y height
  • El elemento <picture> se convierte en una estructura responsiva que incluye varios formatos de imagen
    • Se agrega <source type="image/avif"> para AVIF
    • Se agrega <source type="image/webp"> para WebP
    • El <img> original también recibe srcset, sizes, loading, decoding, width y height
  • La función de optimización de imágenes remite a la documentación optimize-images, pero el enlace correspondiente en el README es una ruta relativa

Manejo de imágenes CDN y externas

  • Las imágenes de CDN pueden mantener la URL remota mientras se les agrega un srcset responsivo
    • El ejemplo crea varias opciones de ancho agregando a la URL de una imagen de Unsplash los parámetros w, fit=min y auto=format
    • La imagen original también recibe loading="lazy", decoding="async" y sizes="100vw"
  • Las imágenes externas pueden descargarse y convertirse luego en archivos locales optimizados
    • El ejemplo cambia una imagen externa de Unsplash por una ruta como _jampack/ab99b9d280ce4cf7cfc810b59f3a7739.jpg.webp
    • La imagen convertida incluye width, height, srcset, sizes, loading y decoding

Above-the-fold y optimización de CSS y enlaces

  • Jampack optimiza por separado los recursos above-the-fold
    • Las imágenes se cargan con mayor prioridad
    • Las imágenes pequeñas se incrustan en el HTML
  • Los recursos below-the-fold se cargan de forma diferida
    • Las imágenes y los iframes son objetivos de lazy load
  • El CSS crítico se inserta inline en el HTML
    • El objetivo es evitar el FOUC que puede producirse durante la descarga y el parseo de la hoja de estilos
    • El resto del CSS se carga de forma diferida
  • El prefetch de enlaces sirve para acelerar la navegación a páginas futuras
    • Puede procesarse dinámicamente cuando los enlaces entran en el viewport usando quicklink

Compresión de recursos y forma de ejecución

  • Jampack comprime en una segunda pasada todos los recursos que no tocó antes, manteniendo el mismo nombre y el mismo formato
  • Las herramientas de compresión por extensión son las siguientes
  • Cuando el sitio web estático está en la carpeta dist, se ejecuta con el siguiente comando
npx @divriots/jampack ./dist
  • Las opciones adicionales pueden consultarse en CLI options

Casos de uso y significado del nombre

1 comentarios

 
GN⁺ 2024-03-26
Opiniones en Hacker News
  • Era justo la herramienta que estaba buscando. Para hacer este tipo de optimización de imágenes, venía escribiendo mis propios scripts basados en Sharp, pero Jampack los reemplaza por completo y funciona mucho mejor.
    Después de compilar un sitio estático con Quarto y ejecutar Jampack, el tamaño de la carpeta se redujo 32%, y todavía no veo desventajas evidentes.
    Según PageSpeed Insights, antes de Jampack en móvil tenía rendimiento 52, accesibilidad 73, prácticas recomendadas 100 y SEO 85; en escritorio, rendimiento 90, accesibilidad 75, prácticas recomendadas 100 y SEO 82.
    Después de aplicarlo, dio rendimiento móvil 49, accesibilidad 80, prácticas recomendadas 100, SEO 92, y en escritorio rendimiento 85, accesibilidad 82, prácticas recomendadas 100, SEO 91.

    • Las puntuaciones de Lighthouse y PageSpeed Insights pueden fluctuar. Para este tipo de comparaciones de rendimiento, conviene ejecutarlas varias veces y mirar la mediana.
      También hay material que dice que “la mediana de 5 ejecuciones de Lighthouse es dos veces más estable que una sola ejecución”: https://developers.google.com/web/tools/lighthouse/variabili...
    • Me alegra que te haya gustado. Aun así, esperaba que las métricas de rendimiento mejoraran más. Si no te molesta, me gustaría revisar el resultado del sitio estático antes de aplicar Jampack.
      georges [at] divriots [dot] com
  • Me recuerda al módulo PageSpeed para Apache y Nginx: https://developers.google.com/speed/pagespeed/module

  • Vaya, esto me gusta bastante. Pienso probarlo.
    Si a alguien le parece malo, me gustaría que señalara las fallas. A mis ojos se parece a compilar C a ensamblador ultraoptimizado, y parece una herramienta que se encarga bien de algo que no quiero hacer yo mismo.

    • Si tenemos que distribuir algo como ensamblador ultraoptimizado para HTML y CSS, no sé si estamos yendo en la dirección correcta.
      Creo que, si escribimos el HTML y CSS más simple e intuitivo posible, el navegador de cualquier dispositivo simplemente debería renderizarlo bien.
      Si de verdad hay que distribuir artefactos optimizados a ese nivel, sería mejor saltarse HTML y CSS por completo, distribuir WebAssembly altamente optimizado y dejar que los desarrolladores usen el lenguaje que quieran.
  • Estaría bueno que hubiera una forma de crear subconjuntos de fuentes según el rango Unicode de la salida del SSG, y de fijar ejes OpenType a partir de los font-feature-settings definidos en el CSS.

    • Sí, hay muchas cosas interesantes que se pueden hacer con fuentes. En el TODO está agregar automáticamente sustitutos de fuentes del sistema con las métricas correctas para mejorar automáticamente el CLS.
      Me pregunto si eso es lo que querías decir con “fijar ejes OpenType basado en font-feature-settings”, o si te referías a otra cosa.
      También me gustaría optimizar subconjuntos de fuentes, pero todavía no sé bien cuánto se podría mejorar. Me da curiosidad si lo has hecho manualmente.
    • Si usas fuentes del navegador/sistema, puedes optimizar el tamaño de fuente a 0, así que no sé si realmente hace falta.
  • Me parece interesante la idea de identificar el CSS crítico que debería ir inline en vez de en una hoja de estilos separada.
    Esperaba que existiera una forma de distinguir por principio entre CSS crítico y no crítico. Por ejemplo, considerar siempre como no críticos los efectos de interacción del usuario como :hover.
    Pero la biblioteca que usan renderiza la página y hace su mejor estimación de qué reglas pueden considerarse críticas, lo cual me deja un poco insatisfecho: https://github.com/GoogleChromeLabs/critters

    • Si el CSS pesa menos de 50 KB, simplemente ponlo inline. Si tienes más de 50 KB de CSS, probablemente algo estás haciendo mal.
      Claro, si estás incluyendo fuentes inline, lo entiendo; pero si solo los estilos superan los 50 KB, en general vas por mal camino.
      Hablando en serio, el inline es tremendamente bueno para el rendimiento incluso comparado con una caché caliente, y el umbral a partir del cual una hoja de estilos o script externo empieza a ser mejor es más alto de lo que uno cree; bajo criterios de mercado comunes, puede llegar a cientos de KB.
      El concepto de CSS crítico me parece un enfoque derrotista para recuperar un poco del rendimiento desperdiciado en vez de arreglar el problema de fondo.
      Dicho eso, no es una técnica sistemática, sino un juicio basado en experiencia y observaciones ligeras. Ojalá alguien mida mejor este concepto, aunque no creo que vaya a ser yo.
  • Esto parece cubrir varios de los usos por los que la gente elige SSG y plugins desde el principio. Especialmente si eliges Astro o Eleventy.
    ¿Hay alguna razón para preferir dejarlo como un paso separado después del build? Hace que los rebuilds durante el desarrollo sean más rápidos, pero parece un compromiso frente a la posibilidad de pasar por alto bugs sutiles al agregar cosas como declaraciones de width en imágenes.

  • Como alguien que odia trabajar en layouts de páginas web y se niega a aprenderlo, pero a veces tiene que hacerlo, esta herramienta se ve muy bien.

  • Se ve bien. Pero personalmente odio tener que esperar imágenes cuando hago scroll debajo del primer pantallazo de una página.
    ¿El comportamiento por defecto carga en segundo plano el resto del contenido inferior después de que termina el contenido del primer pantallazo?

    • No. Aprovecha la carga diferida nativa del navegador. Los navegadores principales interpretan el atributo loading="lazy" como “no cargues esta imagen/iframe hasta que esté casi visible”: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/im...
      Eso sí, como la relación de aspecto se inserta inline, el layout no cambia después de que termina de cargar. Es decir, evita el mayor pecado de la carga diferida.
    • Como señaló @lelandfe, Jampack usa el loading="lazy" nativo del navegador.
      Actualmente no hay forma de cambiar este comportamiento, pero se podría agregar una opción para precargar en segundo plano las imágenes debajo del primer pantallazo una vez cargada toda la página. Es una idea bastante buena.
      Aunque me preocupa que termine cargando también imágenes innecesarias al final de la página. Si es una opción, cada quien podría activarla o desactivarla, así que estaría bien.
  • ¿Qué generadores de sitios estáticos usan en producción? Parece que esta herramienta podría optimizar aún más el resultado.
    Por ejemplo, ayer pasé todo el día siguiendo ejemplos para convertir un sitio web en React de Divjoy a HTML simple y servirlo desde un bucket de S3. No pensé que fuera a ser tan difícil y todavía sigo perdido.
    Idealmente, me gustaría algo que despliegue automáticamente a un bucket de S3 y hasta conecte el dominio. Me duele haber pagado y que el desarrollador haya desaparecido y el Discord esté abandonado. Por eso siempre prefiero FOSS.

    • Hugo, Zola y Jekyll, por ejemplo.
      En cierta medida, ya tienen algunas de estas funciones.
  • En uno de mis proyectos no hubo grandes cambios. Por ejemplo, el tamaño total del bundle bajó, pero el tamaño gzip subió, así que en la práctica para mí fue una pérdida neta.
    Aun así, las mejoras de CSS sí parecen haber ayudado.
    La idea se ve excelente, y si el proyecto hubiera tenido imágenes probablemente habría ayudado.

    • Si no hay imágenes, es cierto que los beneficios son limitados. Además, como mejora automáticamente la compatibilidad con navegadores, el tamaño final del CSS también puede aumentar.
      Puedes desactivar esa función configurando browserlist como una cadena vacía: https://jampack.divriots.com/features/browser-compatibility/