El diseño web adaptativo se ha convertido en la norma para los sitios web y aplicações web modernos, brindando una experiencia consistente en una amplia variedad de dispositivos y al mismo tiempo optimizando la visualización para cada dispositivo. Sin embargo, los dispositivos modernos varían no sólo en términos de tamaño de pantalla sino también en la densidad de píxeles. La etiqueta img
de HTML5 proporciona una serie de características que permiten al navegador seleccionar el activo más apropiado si el servidor ofrece múltiples variantes. Si el sitio web implementa varios tamaños diferentes de la misma imagen, el navegador web puede elegir el tamaño que mejor se adapte a su entorno actual.
Por lo tanto, las imágenes adaptables pueden permitir que el navegador web produzca una representación que coincida estrechamente con la intención del diseñador. Esto mejora la experiencia del usuario, pero también supone una carga adicional para los equipos de desarrollo y operaciones, que ahora tienen que crear e implementar numerosas variantes de activos de imagen, además de la imagen predeterminada.
En esta publicación del blog, mostramos cómo usar el módulo Image‑Filter para NGINX y NGINX Plus para ofrecer imágenes responsivas sin el dolor de cabeza de crear y administrar una gran cantidad de variantes de activos de imagen; en su lugar, podemos implementar una única versión "fuente" de cada imagen que NGINX o NGINX Plus redimensiona sobre la marcha. La información de la publicación se aplica tanto a NGINX Open Source como a NGINX Plus (a excepción de las instrucciones separadas en Instalación del módulo de filtro de imagen ); para abreviar, nos referimos a NGINX Plus en todo momento.
srcset
La herramienta principal para entregar imágenes responsivas es el atributo srcset
de la etiqueta img de
HTML5. Podemos usarlo para especificar una cantidad de variantes de recursos de imagen para diferentes densidades de píxeles y tamaños de ventanas gráficas. Viewport es un término genérico para el espacio de visualización disponible para el navegador web, ya sea en una ventana en un escritorio o en una aplicación de pantalla completa en un dispositivo móvil.
En el siguiente ejemplo, el atributo src
define una imagen predeterminada para los navegadores que no admiten el atributo srcset
y el atributo srcset
nombra dos variantes: una para pantallas con densidad de píxeles estándar ( 1x
) y una segunda para pantallas con doble densidad de píxeles, como las pantallas Apple Retina™ y algunos monitores 4K ( 2x
).
< img src= "/images/mylogo-default.png" srcset= "/images/mylogo-density1.png 1x, /images/mylogo-density2.png 2x" >
El siguiente ejemplo, más sofisticado, define una serie de variantes de activos de imagen para mostrar, según el ancho de la ventana gráfica. El atributo de tamaños
especifica que el navegador representa una imagen en la mitad de la ventana gráfica si esta es más ancha que 10 em
y utiliza toda la ventana gráfica en caso contrario. El navegador determina cuánto espacio está disponible para la imagen y selecciona la variante del recurso de imagen que mejor se adapta al espacio disponible, generalmente "redondeando hacia arriba" al siguiente ancho (sufijo w
) y redimensionando internamente la imagen para llenar el espacio con exactitud.
< img src= "/images/racecar-default.jpg" sizes= "(ancho mínimo: 10em) 50vw, 100vw" srcset= "/images/racecar-100px.jpg 100w, /images/racecar-225px.jpg 225w, /images/racecar-450px.jpg 450w, /images/racecar-675px.jpg 675w" >
Este enfoque para ofrecer imágenes adaptables mediante la especificación de una variedad de variantes de activos de imagen es fácil de codificar y altamente efectivo. Sin embargo, presenta desafíos en términos de creación y gestión de las propias variantes de imagen. Es necesario realizar un gran trabajo de redimensionamiento de imágenes de preproducción e implementar una cantidad mucho mayor de archivos en el servidor. Ajustar la cantidad y el tamaño óptimos de cada variante puede llevar mucho tiempo, lo que luego genera dificultades a la hora de probar que cada variante de recurso de imagen sea accesible.
Para obtener más información sobre el atributo srcset
y otras técnicas para imágenes responsivas, consulte esta excelente publicación de blog .
El procedimiento para obtener ese módulo de filtro de imagen difiere para NGINX Plus y NGINX.
El módulo Filtro de imagen está disponible como un módulo dinámico gratuito para los suscriptores de NGINX Plus.
Obtenga el módulo instalándolo desde el repositorio NGINX Plus.
Para sistemas Ubuntu y Debian:
$ sudo apt-get install nginx-plus-module-image-filter
Para sistemas RedHat, CentOS y Oracle Linux:
$ sudo yum install nginx-plus-module-image-filter
Habilite el módulo incluyendo una directiva load_module
para él en el contexto de nivel superior (“principal”) del archivo de configuración nginx.conf (es decir, no en los contextos http
o stream
).
módulo_de_carga módulos/ngx_http_image_filter_module.so;
Vuelva a cargar NGINX Plus para cargar el módulo Image‑Filter en la instancia en ejecución.
$ sudo nginx -s reload >
La forma más sencilla de instalar el módulo Image‑Filter es obtenerlo del repositorio oficial de NGINX. Siga estas instrucciones para configurar su sistema para acceder al repositorio oficial NGINX y luego instálelo con el administrador de paquetes de su sistema operativo.
Para sistemas Ubuntu y Debian:
$ sudo apt-get install nginx-module-image-filter
Para sistemas Red Hat, CentOS y Oracle Linux:
$ sudo yum install nginx-module-image-filter
Una vez instalado, siga los pasos 2 y 3 de Instalación del módulo de filtro de imágenes para NGINX Plus para configurar NGINX y volver a cargarlo.
También es posible compilar el módulo Image‑Filter desde la fuente y cargarlo como un módulo compilado estáticamente o dinámico. Para obtener más detalles, consulte la Guía de administración de NGINX Plus .
Con el módulo Image‑Filter, podemos crear e implementar una única versión “fuente” de cada imagen y hacer que NGINX Plus la redimensione sobre la marcha para ofrecer cualquier variante de tamaño solicitada por el navegador. Podemos ajustar páginas web e imágenes responsivas completamente dentro del código fuente HTML, sin tener que redimensionar ni implementar manualmente las imágenes en nuestro servidor web.
En este archivo HTML de muestra, definimos cuatro variantes de imagen para dispositivos con diferentes densidades de píxeles.
< html > < head > < title > Logotipo adaptable title > head > < body > < h2 > Selección del logotipo según la densidad de píxeles h2 > < img src= "/img400/mylogo.png" srcset= "/img400/mylogo.png 1x, /img800/mylogo.png 2x, /img1200/mylogo.png 3x, /img1600/mylogo.png 4x" > body > html >
Los directorios /img400 , /img800 , /img1200 y /img1600 en realidad no existen. En cambio, la siguiente configuración de NGINX Plus coincide con las solicitudes de activos con el prefijo /img y las transforma en solicitudes para cambiar el tamaño de la imagen en el nombre de archivo original (por ejemplo, mylogo.png en el HTML anterior).
servidor { escucha 80;
raíz /var/www/public_html;
ubicación ~ ^/img([0-9]+)(?:/(.*))?$ {
alias /var/www/source_images/$2;
búfer de filtro de imagen 10M;
cambio de tamaño del filtro de imagen $1 -;
}
}
El bloque de servidor
define cómo NGINX Plus maneja las solicitudes HTTP entrantes. La directiva listen
le dice a NGINX Plus que escuche en el puerto 80, el predeterminado para el tráfico HTTP. La directiva raíz
especifica la ubicación en el disco de este sitio web. En este sencillo ejemplo, utilizamos un sitio web estático alojado en NGINX Plus, pero también es habitual que NGINX Plus actúe como proxy inverso para contenido dinámico o como conector de aplicação , como FastCGI. Todos estos casos de uso pueden aprovechar el módulo Filtro de Imágenes, como se describe aquí, implementando las imágenes de origen en el servidor NGINX Plus.
El bloque de ubicación
utiliza una expresión regular para hacer coincidir las solicitudes de activos almacenados en cualquier directorio que comience con /img seguido de uno o más dígitos. Los dígitos se capturan como variable $1
y el nombre de archivo que sigue se captura como variable $2
. Luego usamos la directiva alias
para atender esta solicitud desde el directorio en el disco que contiene nuestras imágenes de origen. Tenga en cuenta que este directorio no está bajo la ruta raíz
, por lo que los clientes no pueden solicitar las imágenes de origen directamente.
Como es probable que nuestras imágenes de origen sean muy grandes, quizás de miles de píxeles de ancho, debemos asegurarnos de que el módulo Filtro de imagen asigne suficiente memoria para cargarlas y redimensionarlas. En este ejemplo utilizamos la directiva image_filter_buffer
para admitir archivos de imagen de hasta 10 MB de tamaño.
Finalmente, la directiva image_filter
le dice al módulo Image‑Filter que cambie el tamaño de la imagen de origen al ancho capturado del sufijo del nombre del directorio /img . El guion (-) le indica a NGINX Plus que mantenga la relación de aspecto de la imagen de origen.
La configuración descrita en Coincidencia de tamaño de imagen con densidad de píxeles puede proporcionar cualquier variante de tamaño de una imagen dependiendo del nombre del directorio utilizado para solicitar la imagen. Sin embargo, para un entorno de producción no queremos esperar a que el servidor web cambie el tamaño de las imágenes para cada solicitud. Esto no es bueno para la latencia general y también puede agregar una sobrecarga significativa de la CPU.
La solución más efectiva es almacenar en caché nuestras variantes de imágenes redimensionadas para que las solicitudes posteriores para cada variante se atiendan desde el caché, sin pasar por el módulo Image‑Filter. Podemos lograr esto con la configuración de NGINX Plus definiendo un servidor virtual separado que realiza el cambio de tamaño de la imagen y envía solicitudes de proxy solo si el tamaño de imagen solicitado ya no está en el caché. A esto lo llamamos el servidor de imágenes responsivo .
También debemos considerar las implicaciones de seguridad de permitir solicitudes arbitrarias para realizar operaciones de cambio de tamaño de imágenes. Tener el almacenamiento en caché configurado no ayuda si un atacante realiza solicitudes rápidas a variantes de activos de imágenes únicas, como /img1001/mylogo.png , /img1002/mylogo.png , /img1003/mylogo.png , etc. Incluso con un volumen de solicitudes relativamente bajo, estos ataques pueden causar denegación de servicio (DoS) debido al uso excesivo de la CPU. Para solucionar esto, aplicamos un límite de velocidad al servidor de imágenes responsivas, pero no al servidor frontend que contiene las variantes almacenadas en caché. La siguiente configuración extiende la configuración de Coincidencia de tamaño de imagen con densidad de píxeles aplicando almacenamiento en caché y limitación de velocidad al módulo Filtro de imagen.
ruta_caché_proxy /var/www/imgcache niveles=1 zona_claves=redimensionado:1m tamaño_máximo=256m;
servidor {
escuchar 80;
raíz /var/www/public_html;
ubicación ~ ^/img([0-9]+)(?:/(.*))?$ {
contraseña_proxy http://127.0.0.1:9001;
caché_proxy redimensionado;
caché_proxy_válido 180m;
}
}
zona_límite_solicitud "1" zona=2persec:32k tasa=2r/s;
servidor {
escuchar 9001;
permitir 127.0.0.1;
denegar todo;
zona_límite_solicitud=2persec ráfaga=10;
ubicación ~ ^/img([0-9]+)(?:/(.*))?$ {
alias /var/www/source_images/$2;
búfer de filtro de imagen 10M;
cambio de tamaño del filtro de imagen $1 -;
}
}
Comenzamos definiendo la ubicación de nuestras imágenes almacenadas en caché con la directiva proxy_cache_path
. El parámetro keys_zone
define una zona de memoria compartida para el índice de caché (llamado resized
) y asigna 1 MB, que es suficiente para aproximadamente 8000 imágenes redimensionadas. El parámetro max_size
define el punto en el que NGINX Plus comienza a eliminar del caché las imágenes solicitadas menos recientemente para dejar lugar para nuevos elementos almacenados en caché.
La directiva de ubicación
para el servidor web frontend (el que escucha en el puerto 80) usa la directiva proxy_pass
para enviar solicitudes con el prefijo /img al servidor de imágenes responsivo alojado internamente (127.0.0.1:9001). La directiva proxy_cache
habilita el almacenamiento en caché para esta ubicación al especificar el nombre del caché ( redimensionado
) que se utilizará para almacenar las respuestas del servidor de imágenes responsivo. La directiva proxy_cache_valid
garantiza que las imágenes redimensionadas se mantengan en la memoria caché durante al menos 180 minutos (a menos que la memoria caché haya excedido max_size
y se encuentren entre las solicitadas menos recientemente) y que cualquier respuesta errónea del servidor de imágenes responsiva no se almacene en caché.
Para obtener una descripción detallada del almacenamiento en caché, consulte Una guía para el almacenamiento en caché con NGINX y NGINX Plus .
Antes de definir el servidor de imágenes responsivo, especificamos un límite de velocidad con la directiva limit_req_zone
. La directiva en sí no impone un límite de velocidad: define un límite de velocidad de dos solicitudes por segundo que luego se aplica al servidor de imágenes responsivo al incluir la directiva limit_req
en su bloque de servidor
(consulte el siguiente párrafo). Normalmente, un límite de velocidad está vinculado a un atributo de la solicitud, pero en este caso especificamos el valor de clave estática "1"
para que el límite se aplique a todos los solicitantes. Establecemos el tamaño de la zona de memoria compartida en el valor más pequeño posible, 3 KB, porque nuestra clave tiene una cardinalidad fija de uno.
El bloque del servidor
para el servidor de imágenes responsivo escucha en el puerto 9001. Incluimos las directivas allow
y deny
para especificar que solo localhost (el servidor web frontend) puede conectarse al servidor de imágenes responsivo. Luego aplicamos el límite de velocidad definido previamente incluyendo la directiva limit_req
; el parámetro burst
permite 10 solicitudes simultáneas antes de aplicar el límite de velocidad. Una vez que el límite de velocidad entra en vigor, las solicitudes excedentes se retrasan hasta que puedan procesarse dentro del límite.
El bloque de ubicación
es idéntico al de Coincidencia de tamaño de imagen con densidad de píxeles, pero ahora se ejerce solo cuando la imagen solicitada no está en la memoria caché y mientras no se haya excedido el límite de velocidad.
En esta configuración básica, una única instancia de NGINX Plus actúa como servidor web frontend y como servidor de imágenes responsivo. El procesamiento de imágenes puede ser muy intensivo en términos computacionales, lo que puede generar cargas de trabajo extremadamente altas y hacer que NGINX Plus quede expuesto a ataques DoS. Para evitar la situación en la que el servidor web frontend no puede aceptar nuevas solicitudes de inmediato porque todos los procesos de trabajo están ocupados con solicitudes de cambio de tamaño de imágenes, recomendamos ejecutar una instancia NGINX Plus separada dedicada al procesamiento de imágenes. Esto aísla los procesos de trabajo del servidor web frontend de aquellos que realizan el procesamiento de imágenes. Para ejecutar una instancia independiente de NGINX Plus en el mismo host, especifique un archivo de configuración diferente en la línea de comando:
$ sudo nginx -c /etc/nginx/resize-server.conf
La forma más efectiva de ver imágenes responsivas en acción es observar un navegador que toma decisiones sobre qué variante de imagen srcset
utilizar a medida que cambia el tamaño de la ventana gráfica. Aquí está el código fuente HTML de una galería de imágenes sencilla. Tenga en cuenta que, para fines de demostración, las variantes de tamaño son ligeramente diferentes para cada imagen, lo que crea muchos “puntos de interrupción” posibles en los que el navegador puede elegir una variante diferente.
<!DOCTYPE html>
<html>
<cabeza>
<título>Galería de imágenes adaptable</título>
</cabeza>
<cuerpo>
<h2>Galería de imágenes adaptable</h2>
<imagen origen="/img100/1-dominos.jpg" tamaños="(ancho mínimo: 20em) 40vw, 100vw" srcset= "/img110/1-dominos.jpg 110w, /img210/1-dominos.jpg 210w, /img310/1-dominos.jpg 310w, /img410/1-dominos.jpg 410w, /img510/1-dominos.jpg 510w, /img610/1-dominos.jpg 610w" > < img src= "/img100/2-sign.jpg" sizes= "(ancho mínimo: 20em) 40vw, 100vw" srcset= "/img120/2-sign.jpg 120w, /img220/2-sign.jpg 220w, /img330/2-sign.jpg 330w, /img420/2-sign.jpg 420w, /img520/2-sign.jpg 520w, /img620/2-sign.jpg 620w" > < img src= "/img100/3-thruppence.jpg" sizes= "(ancho mínimo: 20em) 40vw, 100vw" srcset= "/img130/3-thruppence.jpg 130w, /img230/3-thruppence.jpg 230w, /img330/3-thruppence.jpg 330w, /img440/3-thruppence.jpg 440w, /img550/3-thruppence.jpg 550w, /img660/3-thruppence.jpg 660w" > < img src= "/img100/4-aces.jpg" sizes= "(ancho mínimo: 20em) 40vw, 100vw" srcset= "/img140/ 4 - aces.jpg 140w , /img240/4-aces.jpg 240w, /img340/4-aces.jpg 340w, /img440/4-aces.jpg 440w, /img540/4-aces.jpg 540w, /img640/4-aces.jpg 640w " >
Las capturas de pantalla a continuación muestran el contenido de esta página web en un navegador Chrome con el Inspector abierto en la pestaña Red . La columna Nombre muestra la ruta de cada variante de imagen solicitada al servidor, lo que nos permite ver el tamaño elegido sin tener que consultar los logs en el servidor web.
Con la ventana gráfica estrecha de la Figura 2, el navegador ha elegido imágenes entre 220 y 310 píxeles de ancho (los sufijos numéricos en los nombres del directorio /img en la columna Nombre varían entre esos valores).
Cuando ampliamos la ventana del navegador en la Figura 3, el navegador elige imágenes entre 440 y 540 píxeles de ancho (las últimas cuatro imágenes enumeradas). El valor de estas imágenes en la columna Iniciador es Otro .
Con NGINX Plus y el módulo Image‑Filter, podemos ofrecer el tamaño de imagen óptimo para las condiciones actuales del navegador. Y podemos hacer esto sin tener que cambiar el tamaño de las imágenes antes de la producción, ni procesarlas por lotes, ni tener que gestionar cientos de variantes de activos de imágenes en el disco. Otra forma en la que NGINX Plus le ayuda a lograr una entrega de aplicação perfecta.
Pruebe usted mismo las imágenes responsivas con NGINX Plus: comience hoy su prueba gratuita de 30 días o contáctenos para analizar sus casos de uso .
"Esta publicación de blog puede hacer referencia a productos que ya no están disponibles o que ya no reciben soporte. Para obtener la información más actualizada sobre los productos y soluciones F5 NGINX disponibles, explore nuestra familia de productos NGINX . NGINX ahora es parte de F5. Todos los enlaces anteriores de NGINX.com redirigirán a contenido similar de NGINX en F5.com.