Entrega de aplicaciones rápidas y ligeras con Save-Data

El encabezado de solicitud de sugerencia del cliente Save-Data disponible en los navegadores Chrome, Opera y Yandex permite a los desarrolladores ofrecer aplicaciones más ligeras y rápidas a los usuarios que habilitan el modo de ahorro de datos en sus navegadores.

La necesidad de páginas ligeras

Estadísticas de WebLight

Todos coinciden en que las páginas web más rápidas y ligeras brindan una experiencia del usuario más satisfactoria, permiten una mejor comprensión y retención del contenido, y generan más conversiones y mayores ingresos. La investigación de Google demostró que "…las páginas optimizadas se cargan cuatro veces más rápido que las originales y usan un 80% menos de bytes. Debido a que estas páginas se cargan mucho más rápido, también observamos un aumento del 50% en el tráfico hacia ellas".

Y, aunque la cantidad de conexiones 2G finalmente está en descenso, en 2015, la tecnología de red 2G seguía siendo la dominante. La penetración y la disponibilidad de las redes 3G y 4G crecen rápidamente, pero los costos de propiedad asociados y las limitaciones de la red siguen siendo un factor importante para cientos de millones de usuarios.

Estos son argumentos sólidos para la optimización de la página.

Existen métodos alternativos para mejorar la velocidad del sitio sin la participación directa de los desarrolladores, como los navegadores proxy y los servicios de transcodificación. Si bien estos servicios son muy populares, tienen desventajas importantes: compresión simple (y, a veces, inaceptable) de imágenes y texto, incapacidad para procesar páginas seguras (HTTPS), optimización solo de las páginas que se visitan a través de un resultado de la búsqueda, entre otras. La popularidad de estos servicios es un indicador de que los desarrolladores web no satisfacen adecuadamente la alta demanda de los usuarios por aplicaciones y páginas rápidas y livianas. Sin embargo, alcanzar ese objetivo es un camino complejo y, a veces, difícil.

El encabezado de la solicitud Save-Data

Una técnica bastante sencilla es dejar que el navegador ayude, usando el encabezado de la solicitud Save-Data. Al identificar este encabezado, una página web puede personalizar y ofrecer una experiencia del usuario optimizada para los usuarios con limitaciones de costos y rendimiento.

Los navegadores compatibles (que se indican a continuación) permiten que el usuario habilite un modo de ahorro de datos que le otorga permiso al navegador para aplicar un conjunto de optimizaciones que reducen la cantidad de datos necesarios para renderizar la página. Cuando se expone o anuncia esta función, es posible que el navegador solicite imágenes de menor resolución, posponga la carga de algunos recursos o enrute las solicitudes a través de un servicio que aplique otras optimizaciones específicas del contenido, como la compresión de recursos de imágenes y texto.

Navegadores compatibles

  • Chrome 49 y versiones posteriores anuncian Save-Data cuando el usuario habilita la opción "Ahorro de datos" en dispositivos móviles o la extensión "Ahorro de datos" en navegadores para computadoras.
  • Opera 35 y versiones posteriores anuncian Save-Data cuando el usuario habilita el modo "Opera Turbo" en computadoras de escritorio o la opción "Ahorro de datos" en navegadores para Android.
  • Yandex 16.2 y versiones posteriores anuncian Save-Data cuando el modo Turbo está habilitado en navegadores para computadoras o dispositivos móviles.

Cómo detectar el parámetro de configuración Save-Data

Para determinar cuándo ofrecer la experiencia "ligera" a tus usuarios, tu aplicación puede verificar el encabezado de solicitud de sugerencia del cliente Save-Data. Este encabezado de la solicitud indica la preferencia del cliente por un menor uso de datos debido a los altos costos de transferencia, las velocidades de conexión lentas o cualquier otro motivo.

Cuando el usuario habilita el modo de ahorro de datos en su navegador, este agrega el encabezado de la solicitud Save-Data a todas las solicitudes salientes (tanto HTTP como HTTPS). En el momento de escribir este documento, el navegador solo anuncia un token *on en el encabezado (Save-Data: on), pero es posible que esto se extienda en el futuro para indicar otras preferencias del usuario.

Además, es posible detectar si Save-Data está activado en JavaScript:

if ('connection' in navigator) {
  if (navigator.connection.saveData === true) {
    // Implement data saving operations here.
  }
}

Verificar la presencia del objeto connection dentro del objeto navigator es fundamental, ya que representa la API de Network Information, que solo se implementa en los navegadores Chrome, Chrome para Android y Samsung Internet. A partir de ahí, solo debes verificar si navigator.connection.saveData es igual a true y puedes implementar cualquier operación de guardado de datos en esa condición.

El encabezado Save-Data que se muestra en las Herramientas para desarrolladores de Chrome junto con la extensión Ahorro de datos.
Cómo habilitar la extensión Ahorro de datos en Chrome para computadoras

Si tu aplicación usa un service worker, puede inspeccionar los encabezados de la solicitud y aplicar la lógica pertinente para optimizar la experiencia. De forma alternativa, el servidor puede buscar las preferencias anunciadas en el encabezado de la solicitud Save-Data y devolver una respuesta alternativa (marcado diferente, imágenes y videos más pequeños, etcétera).

Sugerencias y prácticas recomendadas para la implementación

  1. Cuando uses Save-Data, proporciona algunos dispositivos de IU que lo admitan y permitan a los usuarios alternar fácilmente entre las experiencias. Por ejemplo:
    • Notifica a los usuarios que Save-Data es compatible y anímalos a usarlo.
    • Permite que los usuarios identifiquen y elijan el modo con mensajes adecuados y botones o casillas de verificación intuitivos para activar o desactivar la función.
    • Cuando se selecciona el modo de ahorro de datos, anuncia y proporciona una forma fácil y obvia de inhabilitarlo y volver a la experiencia completa si lo deseas.
  2. Recuerda que las aplicaciones livianas no son aplicaciones inferiores. No omiten datos ni funciones importantes, sino que son más conscientes de los costos involucrados y la experiencia del usuario. Por ejemplo:
    • Una aplicación de galería de fotos puede ofrecer vistas previas de menor resolución o usar un mecanismo de carrusel con menos código.
    • Una aplicación de búsqueda puede mostrar menos resultados a la vez, limitar la cantidad de resultados con mucho contenido multimedia o reducir la cantidad de dependencias necesarias para renderizar la página.
    • Un sitio orientado a las noticias puede mostrar menos historias, omitir categorías menos populares o proporcionar vistas previas de medios más pequeñas.
  3. Proporciona lógica del servidor para verificar el encabezado de la solicitud Save-Data y considera proporcionar una respuesta de página alternativa más ligera cuando esté habilitado (p.ej., reduce la cantidad de recursos y dependencias necesarios, aplica una compresión de recursos más agresiva, etcétera).
    • Si publicas una respuesta alternativa basada en el encabezado Save-Data, recuerda agregarlo a la lista Vary (Vary: Save-Data) para indicarles a las cachés upstream que deben almacenar en caché y entregar esta versión solo si está presente el encabezado de la solicitud Save-Data. Para obtener más detalles, consulta las prácticas recomendadas para la interacción con las memorias caché.
  4. Si usas un service worker, tu aplicación puede detectar cuándo se habilita la opción de ahorro de datos verificando la presencia del encabezado de solicitud Save-Data o verificando el valor de la propiedad navigator.connection.saveData. Si está habilitada, considera si puedes reescribir la solicitud para recuperar menos bytes o usar una respuesta ya recuperada.
  5. Considera aumentar Save-Data con otros indicadores, como información sobre el tipo de conexión y la tecnología del usuario (consulta la API de NetInfo). Por ejemplo, es posible que desees ofrecer la experiencia liviana a cualquier usuario con una conexión 2G, incluso si Save-Data no está habilitado. Por el contrario, el hecho de que el usuario tenga una conexión 4G "rápida" no significa que no le interese ahorrar datos, por ejemplo, cuando está en roaming. Además, puedes aumentar la presencia de Save-Data con la sugerencia del cliente Device-Memory para adaptarte aún más a los usuarios en dispositivos con memoria limitada. La memoria del dispositivo del usuario también se anuncia en la sugerencia del cliente navigator.deviceMemory.

Recetas

Lo que puedes lograr con Save-Data solo está limitado por tu imaginación. Para que te hagas una idea de lo que puedes hacer, veamos algunos casos de uso. A medida que leas este artículo, es posible que se te ocurran otros casos de uso, así que no dudes en experimentar y ver qué es posible.

Cómo verificar Save-Data en el código del servidor

Si bien el estado Save-Data es algo que puedes detectar en JavaScript a través de la propiedad navigator.connection.saveData, a veces es preferible detectarlo en el servidor. En algunos casos, JavaScript puede fallar en su ejecución. Además, la detección del servidor es la única forma de modificar el lenguaje de marcado antes de que se envíe al cliente, lo que se incluye en algunos de los casos de uso más beneficiosos de Save-Data.

La sintaxis específica para detectar el encabezado Save-Data en el código del servidor depende del lenguaje que se use, pero la idea básica debería ser la misma para cualquier backend de la aplicación. En PHP, por ejemplo, los encabezados de solicitud se almacenan en el array superglobal $_SERVER en índices que comienzan con HTTP_. Esto significa que puedes detectar el encabezado Save-Data verificando la existencia y el valor de la variable $_SERVER["HTTP_SAVE_DATA"] de la siguiente manera:

// false by default.
$saveData = false;

// Check if the `Save-Data` header exists and is set to a value of "on".
if (isset($_SERVER["HTTP_SAVE_DATA"]) && strtolower($_SERVER["HTTP_SAVE_DATA"]) === "on") {
  // `Save-Data` detected!
  $saveData = true;
}

Si colocas esta verificación antes de que se envíe cualquier marcado al cliente, la variable $saveData contendrá el estado Save-Data y estará disponible en cualquier lugar para su uso en la página. Con este mecanismo ilustrado, veamos algunos ejemplos de cómo podemos usarlo para limitar la cantidad de datos que enviamos al usuario.

Entrega imágenes de baja resolución para pantallas de alta resolución

Un caso de uso común para las imágenes en la Web implica publicar imágenes en conjuntos de dos: una imagen para pantallas "estándar" (1x) y otra imagen que es el doble de grande (2x) para pantallas de alta resolución (p.ej., pantalla Retina). Esta clase de pantallas de alta resolución no se limita necesariamente a los dispositivos de alta gama y se está volviendo cada vez más común. En los casos en los que se prefiera una experiencia de aplicación más ligera, podría ser prudente enviar imágenes de menor resolución (1x) a estas pantallas, en lugar de variantes más grandes (2x). Para lograr esto cuando el encabezado Save-Data está presente, simplemente modificamos el lenguaje de marcado que enviamos al cliente:

if ($saveData === true) {
  // Send a low-resolution version of the image for clients specifying `Save-Data`.
  ?><img src="butterfly-1x.jpg" alt="A butterfly perched on a flower."><?php
}
else {
  // Send the usual assets for everyone else.
  ?><img src="butterfly-1x.jpg" srcset="butterfly-2x.jpg 2x, butterfly-1x.jpg 1x" alt="A butterfly perched on a flower."><?php
}

Este caso de uso es un ejemplo perfecto de lo poco que cuesta satisfacer a alguien que te pide específicamente que le envíes menos datos. Si no te gusta modificar el lenguaje de marcado en el backend, también puedes lograr el mismo resultado con un módulo de reescritura de URLs, como mod_rewrite de Apache. Existen ejemplos de cómo lograr esto con relativamente poca configuración.

También puedes extender este concepto a las propiedades background-image de CSS simplemente agregando una clase al elemento <html>:

<html class="<?php if ($saveData === true): ?>save-data<?php endif; ?>">

Desde aquí, puedes segmentar la clase save-data en el elemento <html> de tu CSS para cambiar la forma en que se entregan las imágenes. Podrías enviar imágenes de fondo de baja resolución a pantallas de alta resolución, como se muestra en el ejemplo de HTML anterior, o bien omitir ciertos recursos por completo.

Omitir imágenes no esenciales

Parte del contenido de imágenes en la Web es simplemente no esencial. Si bien estas imágenes pueden ser un buen complemento para el contenido, es posible que no sean deseables para quienes intentan aprovechar al máximo los planes de datos medidos. En el caso de uso más simple de Save-Data, podemos usar el código de detección de PHP que vimos antes y omitir por completo el lenguaje de marcado de imágenes no esenciales:

<p>This paragraph is essential content. The image below may be humorous, but it's not critical to the content.</p>
<?php
if ($saveData === false) {
  // Only send this image if `Save-Data` hasn't been detected.
  ?><img src="meme.jpg" alt="One does not simply consume data."><?php
}

Esta técnica puede tener un efecto pronunciado, como se puede ver en la siguiente figura:

Comparación de las imágenes no críticas que se cargan cuando no está presente Save-Data, en comparación con las mismas imágenes que se omiten cuando Save-Data está presente.
Comparación de las imágenes no críticas que se cargan cuando no está presente Save-Data, en comparación con las mismas imágenes que se omiten cuando Save-Data está presente.

Por supuesto, omitir imágenes no es la única posibilidad. También puedes actuar en función de Save-Data para evitar enviar otros recursos no críticos, como ciertos tipos de letra.

Omitir fuentes web no esenciales

Si bien las fuentes web no suelen representar una parte tan grande de la carga útil total de una página como las imágenes, siguen siendo muy populares. Tampoco consumen una cantidad insignificante de datos. Además, la forma en que los navegadores recuperan y renderizan las fuentes es más complicada de lo que crees, con conceptos como FOIT, FOUT y la heurística del navegador que hacen que la renderización sea una operación matizada.

Por lo tanto, es posible que desees omitir las fuentes web no esenciales para los usuarios que desean experiencias más sencillas. Save-Data hace que esto sea algo razonablemente sencillo de hacer.

Por ejemplo, supongamos que incluiste Fira Sans de Google Fonts en tu sitio. Fira Sans es una excelente fuente para el cuerpo del texto, pero tal vez no sea tan importante para los usuarios que intentan ahorrar datos. Si agregamos una clase de save-data al elemento <html> cuando el encabezado Save-Data está presente, podemos escribir estilos que invoquen el tipo de letra no esencial al principio, pero que luego lo rechacen cuando el encabezado Save-Data esté presente:

/* Opt into web fonts by default. */
p,
li {
  font-family: 'Fira Sans', 'Arial', sans-serif;
}

/* Opt out of web fonts if the `save-Data` class is present. */
.save-data p,
.save-data li {
  font-family: 'Arial', sans-serif;
}

Con este enfoque, puedes dejar el fragmento de <link> de Google Fonts, ya que el navegador carga de forma especulativa los recursos CSS (incluidas las fuentes web) aplicando primero los estilos al DOM y, luego, verificando si algún elemento HTML invoca alguno de los recursos de la hoja de estilo. Si alguien pasa por allí con Save-Data activado, Fira Sans nunca se cargará porque el DOM con estilo nunca la invoca. En su lugar, se usará Arial. No es tan agradable como Fira Sans, pero puede ser preferible para los usuarios que intentan aprovechar al máximo sus planes de datos.

Resumen

El encabezado Save-Data no tiene muchas variantes; está activado o desactivado, y la aplicación tiene la responsabilidad de proporcionar experiencias adecuadas según su configuración, independientemente del motivo.

Por ejemplo, es posible que algunos usuarios no permitan el modo de ahorro de datos si sospechan que habrá una pérdida de contenido o funciones de la app, incluso en situaciones de conectividad deficiente. Por el contrario, algunos usuarios podrían habilitarlo de forma predeterminada para mantener las páginas lo más pequeñas y simples posible, incluso en situaciones de buena conectividad. Lo mejor es que tu app suponga que el usuario desea la experiencia completa e ilimitada hasta que tengas una indicación clara de lo contrario a través de una acción explícita del usuario.

Como propietarios de sitios y desarrolladores web, asumamos la responsabilidad de administrar nuestro contenido para mejorar la experiencia del usuario de los usuarios con limitaciones de datos y costos.

Para obtener más detalles sobre Save-Data y ejemplos prácticos excelentes, consulta Ayuda a tus usuarios Save Data.