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

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

La necesidad de páginas ligeras

Estadísticas de Weblight

Todos coinciden en que las páginas web más rápidas y livianas proporcionan una experiencia del usuario más satisfactoria, permiten una mejor comprensión y retención del contenido, y generan más conversiones y más ingresos. La investigación de Google demostró que "…las páginas optimizadas se cargan cuatro veces más rápido que la página original 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 por fin está disminuyendo, la tecnología de red dominante en 2015 seguía siendo la 2G. La penetración y la disponibilidad de las redes 3G y 4G están creciendo con rapidez, pero los costos de propiedad asociados y las limitaciones de la red siguen siendo un factor significativo 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 del desarrollador, como los navegadores proxy y los servicios de transcodificación. Aunque estos servicios son bastante populares, tienen inconvenientes sustanciales, como compresión simple (y, a veces, inaceptable) de imágenes y texto, incapacidad para procesar páginas seguras (HTTPS), solo optimización de páginas visitadas a través de un resultado de la búsqueda y mucho más. La popularidad de estos servicios es un indicador de que los desarrolladores web no están abordando adecuadamente la alta demanda de los usuarios de 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 permitir que el navegador ayude con el encabezado de solicitud Save-Data. Cuando se identifica este encabezado, una página web puede personalizar y ofrecer una experiencia del usuario optimizada a los usuarios con limitaciones de costo y rendimiento.

Los navegadores compatibles (que se indican a continuación) permiten al usuario habilitar 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 se anuncia esta función, el navegador puede solicitar imágenes de menor resolución, aplazar la carga de algunos recursos o enrutar las solicitudes a través de un servicio que aplique otras optimizaciones específicas del contenido, como la compresión de recursos de imagen y texto.

Navegadores compatibles

  • Chrome 49 y versiones posteriores publican 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 la configuración de Save-Data

Para determinar cuándo entregar la experiencia "ligera" a los usuarios, tu aplicación puede verificar el encabezado de la solicitud de sugerencia de cliente Save-Data. Este encabezado de solicitud indica la preferencia del cliente por reducir el uso de datos debido a costos de transferencia altos, velocidades de conexión lentas o por otros motivos.

Cuando el usuario habilita el modo de ahorro de datos en su navegador, este agrega el encabezado de solicitud Save-Data a todas las solicitudes salientes (HTTP y HTTPS). En el momento de escribir este artículo, el navegador solo anuncia un token *on en el encabezado (Save-Data: on), pero es posible que 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.
  }
}

Es fundamental verificar la presencia del objeto connection dentro del objeto navigator, 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 Data Saver.
Habilitación de la extensión Ahorro de datos en Chrome para computadoras.

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

Sugerencias y prácticas recomendadas de implementación

  1. Cuando uses Save-Data, proporciona algunos dispositivos de IU que lo admitan y permitan a los usuarios cambiar fácilmente entre experiencias. Por ejemplo:
    • Notifica a los usuarios que se admite Save-Data y sugiéreles que la usen.
    • Permite que los usuarios identifiquen y elijan el modo con mensajes adecuados y botones o casillas de verificación intuitivos de activación/desactivación.
    • Cuando se selecciona el modo de ahorro de datos, se anuncia y se proporciona una forma fácil y obvia de inhabilitarlo y volver a la experiencia completa si se desea.
  2. Recuerda que las aplicaciones livianas no son inferiores. No omiten datos ni funciones importantes, solo son más conscientes de los costos involucrados y de la experiencia del usuario. Por ejemplo:
    • Una aplicación de galería de fotos puede mostrar vistas previas de menor resolución o usar un mecanismo de carrusel menos cargado de 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 noticias, omitir categorías menos populares o proporcionar vistas previas de contenido multimedia más pequeñas.
  3. Proporciona una lógica de servidor para verificar el encabezado de solicitud Save-Data y considera proporcionar una respuesta de página alternativa y más liviana cuando esté habilitada (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 agregarla a la lista Vary (Vary: Save-Data) para indicar a las cachés upstream que deben almacenar en caché y publicar esta versión solo si está presente el encabezado de solicitud Save-Data. Para obtener más detalles, consulta las prácticas recomendadas para la interacción con las cachés.
  4. Si usas un trabajador de servicio, tu aplicación puede detectar cuándo se habilita la opción de ahorro de datos verificando la presencia del encabezado de la solicitud Save-Data o 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 que ya se recuperó.
  5. Considera aumentar Save-Data con otros indicadores, como la 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 entregar la experiencia ligera a cualquier usuario con una conexión 2G, incluso si Save-Data no está habilitada. Por el contrario, solo porque 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 de 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 de cliente navigator.deviceMemory.

Recetas

Lo que puedes lograr a través de Save-Data se limita solo a lo que puedes idear. Para darte una idea de lo que es posible, veamos algunos casos de uso. Es posible que se te ocurran otros casos de uso a medida que lees esto, así que no dudes en experimentar y ver lo que 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 del lado del servidor. En algunos casos, es posible que JavaScript no se ejecute. Además, la detección del servidor es la única forma de modificar el marcado antes de que se envíe al cliente, lo que participa 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 debe 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 realizas 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.

Publica 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 entregar imágenes en conjuntos de dos: una imagen para pantallas "estándares" (1x) y otra imagen que es el doble de tamaño (2x) para pantallas de alta resolución (p.ej., Retina Display). 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 que se prefiera una experiencia de aplicación más liviana, podría ser conveniente enviar imágenes de resolución más baja (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 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 adaptarse a alguien que te pide específicamente que le envíes menos datos. Si no te gusta modificar el marcado en el backend, también puedes lograr el mismo resultado con un módulo de reescritura de URL, como mod_rewrite de Apache. Hay ejemplos de cómo lograr esto con una configuración relativamente pequeña.

También puedes extender este concepto a las propiedades background-image de CSS. Para ello, solo debes agregar 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> en tu CSS para cambiar la forma en que se entregan las imágenes. Puedes 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.

Omite las imágenes no esenciales

Parte del contenido de imágenes en la Web simplemente no es esencial. Si bien este tipo de imágenes puede ser útil para complementar el contenido, es posible que no sean adecuadas para quienes intentan aprovechar al máximo los planes de datos medidos. En lo que podría ser el caso de uso más simple de Save-Data, podemos usar el código de detección de PHP anterior y omitir por completo el marcado de imagen no esencial:

<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 puedes ver en la siguiente figura:

Una comparación de las imágenes no esenciales que se cargan cuando no hay Save-Data, en comparación con esas mismas imágenes que se omiten cuando Save-Data está presente.
Una comparación de las imágenes no esenciales que se cargan cuando no está presente la función para ahorrar datos en comparación con las que se omiten cuando está presente.

Por supuesto, omitir las imágenes no es la única posibilidad. También puedes realizar acciones en Save-Data para evitar enviar otros recursos no esenciales, como ciertos tipos de letra.

Omite las fuentes web no esenciales

Si bien las fuentes web no suelen representar tanto de la carga útil total de una página determinada como las imágenes, siguen siendo bastante populares. Tampoco consumen una cantidad mínima de datos. Además, la forma en que los navegadores recuperan y renderizan las fuentes es más complicada de lo que podrías pensar, con conceptos como FOIT, FOUT y las heurísticas del navegador que hacen que la renderización sea una operación con matices.

Por lo tanto, es posible que desees omitir las fuentes web que no sean esenciales para los usuarios que desean experiencias del usuario más eficientes. Save-Data hace que esto sea bastante sencillo.

Por ejemplo, supongamos que incluiste Fira Sans de Google Fonts en tu sitio. Fira Sans es una excelente fuente de cuerpo, pero tal vez no sea tan importante para los usuarios que intentan ahorrar datos. Si agregas 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 inhabiliten 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 <link> de Google Fonts en su lugar, ya que el navegador carga de forma especulativa los recursos de CSS (incluidas las fuentes web) aplicando primero estilos al DOM y, luego, verificando si algún elemento HTML invoca alguno de los recursos de la hoja de estilo. Si alguien pasa con Save-Data activado, Fira Sans nunca se cargará porque el DOM con diseño nunca lo invoca. En su lugar, se activará Arial. No es tan agradable como Fira Sans, pero puede ser preferible para los usuarios que intentan estirar sus planes de datos.

Resumen

El encabezado Save-Data no tiene muchos matices; está activado o desactivado, y la aplicación tiene la responsabilidad de proporcionar experiencias adecuadas en función de su configuración, independientemente del motivo.

Por ejemplo, es posible que algunos usuarios no permitan el modo de ahorro de datos si sospechan que se perderá el contenido o la función de la app, incluso en una situación 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 una situación de buena conectividad. Es mejor que tu app asuma que el usuario quiere 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 que tiene limitaciones de datos y costos.

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