Prácticas recomendadas para una aplicación web más rápida con HTML5

Introducción

Gran parte del objetivo de HTML5 es ofrecer compatibilidad con navegadores nativos para componentes y técnicas que hemos logrado hasta ahora mediante las bibliotecas de JavaScript. Si usas estas funciones, cuando estén presentes, podrías ofrecer una experiencia mucho más rápida a tus usuarios. En este instructivo, no resumiré la excelente investigación del rendimiento que viste en el sitio de Rendimiento excepcional de Yahoo o en los documentos sobre Velocidad de la página de Google. Y el sitio de Hagamos que la Web sea más rápida. En cambio, me centraré en cómo el uso actual de HTML5 y CSS3 puede mejorar la capacidad de respuesta de tus aplicaciones web.

Sugerencia 1: Usa el almacenamiento web en lugar de cookies

Si bien las cookies se utilizan para hacer un seguimiento de los datos de usuarios únicos durante años, estas tienen graves desventajas. El mayor defecto es que todos los datos de las cookies se agregan al encabezado de cada solicitud HTTP. Esto puede tener un impacto medible en el tiempo de respuesta, especialmente durante las XHR. Por lo tanto, una práctica recomendada es reducir el tamaño de las cookies. En HTML5, podemos hacer mejor que eso: usar sessionStorage y localStorage en lugar de cookies.

Estos dos objetos de almacenamiento web pueden usarse para conservar los datos del usuario en el lado del cliente durante toda la sesión o de manera indefinida. Tampoco se transfieren al servidor a través de cada solicitud HTTP. Tienen una API que te hará feliz de deshacerte de las cookies. Estas son ambas APIs que usan cookies como resguardo.

// if localStorage is present, use that
if (('localStorage' in window) && window.localStorage !== null) {

  // easy object property API
  localStorage.wishlist = '["Unicorn","Narwhal","Deathbear"]';

} else {

  // without sessionStorage we'll have to use a far-future cookie
  //   with document.cookie's awkward API :(
  var date = new Date();
  date.setTime(date.getTime()+(365*24*60*60*1000));
  var expires = date.toGMTString();
  var cookiestr = 'wishlist=["Unicorn","Narwhal","Deathbear"];'+
                  ' expires='+expires+'; path=/';
  document.cookie = cookiestr;
}

Sugerencia 2: Usa transiciones de CSS en lugar de la animación de JavaScript

Las transiciones CSS ofrecen una transición visual atractiva entre dos estados. La mayoría de las propiedades de estilo pueden transferirse, como manipular la sombra del texto, la posición, el fondo o el color. Puedes usar transiciones a estados de seudoselector, como :hover o desde formularios HTML5, :invalid y :valid (ejemplo con estados de validación de formulario). Sin embargo, son mucho más potentes y se pueden activar cuando agregas cualquier clase a un elemento.

div.box {
  left: 40px;
  -webkit-transition: all 0.3s ease-out;
     -moz-transition: all 0.3s ease-out;
       -o-transition: all 0.3s ease-out;
          transition: all 0.3s ease-out;
}
div.box.totheleft { left: 0px; }
div.box.totheright { left: 80px; }

Si agregas activar o desactivar las clases de totheleft y totheright, puedes mover el cuadro. Compara esta cantidad de código con la de una biblioteca de animación de JavaScript. Claramente, la cantidad de bytes enviados al navegador es mucho menor cuando se usa animación basada en CSS. Además, con la aceleración a nivel de la GPU, estas transiciones visuales serán lo más fluidas posible.

Sugerencia 3: Usa las bases de datos del cliente en lugar de los recorridos del servidor

Web SQL Database e IndexedDB introducen bases de datos en el cliente. En lugar del patrón común de publicar datos en el servidor a través del envío de formularios o XMLHttpRequest, puedes aprovechar estas bases de datos del cliente. La disminución de las solicitudes HTTP es el objetivo principal de todos los ingenieros de rendimiento, por lo que usar estas solicitudes como almacén de datos puede ahorrar muchos viajes a través de XHR o publicaciones de formularios de regreso al servidor. localStorage y sessionStorage podrían usarse en algunos casos, como la captura del progreso del envío de formularios, y observaron ser mucho más rápidos que las APIs de base de datos del cliente. Por ejemplo, si tienes un componente de cuadrícula de datos o una bandeja de entrada con cientos de mensajes, almacenar los datos localmente en una base de datos te ahorrará recorridos HTTP cuando el usuario quiera buscar, filtrar u ordenar. Se podría filtrar una lista de amigos o un autocompletado de entrada de texto en cada combinación de teclas, lo que brinda una experiencia de usuario mucho más receptiva.

Sugerencia 4: Las mejoras de JavaScript proporcionan ventajas considerables en el rendimiento

Se agregaron muchos métodos adicionales al prototipado de array en JavaScript 1.6. Actualmente, están disponibles en la mayoría de los navegadores, excepto en IE. Por ejemplo:

// Give me a new array of all values multiplied by 10.
[5, 6, 7, 8, 900].map(function(value) { return value * 10; });
// [50, 60, 70, 80, 9000]

// Create links to specs and drop them into #links.
['html5', 'css3', 'webgl'].forEach(function(value) {
  var linksList = document.querySelector('#links');
  var newLink = value.link('http://google.com/search?btnI=1&q=' + value + ' spec');
  linksList.innerHTML +=  newLink;
});


// Return a new array of all mathematical constants under 2.
[3.14, 2.718, 1.618].filter(function(number) {
  return number < 2;
});
// [1.618]


// You can also use these extras on other collections like nodeLists.
[].forEach.call(document.querySelectorAll('section[data-bucket]'), function(elem, i) {
  localStorage['bucket' + i] = elem.getAttribute('data-bucket');
});

En la mayoría de los casos, el uso de estos métodos nativos produce velocidades significativamente más rápidas que el bucle for típico: for (var i = 0, len = arr.length; i &lt; len; i++). El análisis de JSON nativo (a través de JSON.parse()) reemplaza el archivo json2.js que estamos acostumbrados a incluir durante un tiempo. El formato JSON nativo es mucho más rápido y seguro que usar una secuencia de comandos externa, y ya está disponible en IE8, Opera 10.50, Firefox 3.5, Safari 4.0.3 y Chrome. El elemento String.trim nativo es otro buen ejemplo de ser no solo más rápido que los equivalentes de JS de lenguaje extenso, sino también posiblemente más correctos. Técnicamente, ninguna de estas incorporaciones de JavaScript es HTML5, pero está dentro de la categoría de tecnologías que están disponibles recientemente.

Sugerencia 5: Usa el manifiesto de caché para los sitios activos, no solo para las apps sin conexión

Hace dos años, Wordpress usó Google Genands para agregar una función llamada Wordpress Turbo. Básicamente, almacenó en caché muchos de los recursos utilizados en el panel de administración de forma local, lo que acelera el acceso a los archivos. Podemos replicar ese comportamiento con la applicationCache de HTML5 y la cache.manifest. La caché de la app tiene una leve ventaja en comparación con la configuración de encabezados Expires: debido a que creas un archivo declarativo que indica los recursos estáticos que se pueden almacenar en caché, los navegadores pueden optimizarlo mucho, tal vez incluso almacenarlos previamente en caché antes de tu uso. Considera la estructura básica de tu sitio como plantilla. Tienes datos que pueden cambiar, pero el HTML que los rodea generalmente sigue siendo bastante coherente. Con la caché de la aplicación, podrías tratar tu HTML como una serie de plantillas puras, almacenar en caché el lenguaje de marcado a través de cache.manifest y, luego, enviar JSON por la conexión para actualizar el contenido. Este modelo es muy similar a lo que hace una aplicación de noticias nativa de iPhone o Android.

Sugerencia 6: Habilita la aceleración de hardware para mejorar la experiencia visual

En los navegadores líderes, muchas operaciones visuales pueden aprovechar la aceleración en el nivel de la GPU, lo cual hace que las operaciones visuales altamente dinámicas sean mucho más fluidas. Se anunció la aceleración de hardware para Firefox Minefield y IE9, y Safari agregó aceleración a nivel de hardware en la versión 5. (Llegó a Mobile Safari mucho antes). Chromium acaba de agregar transformaciones 3D y aceleración de hardware para Windows. Las otras dos plataformas estarán disponibles próximamente.

La aceleración de la GPU se activa solo en un conjunto de condiciones relativamente limitado, pero las transformaciones 3D y la opacidad animada son las formas más comunes de activar el interruptor. Esta es una forma un poco ingeniosa pero discreta de activarla:

.hwaccel {  -webkit-transform: translateZ(0); }

Sin embargo, no podemos garantizarlo. :) Con la aceleración de hardware habilitada y compatible, la traslación animada, la rotación, el escalamiento y la opacidad sin duda serán más fluidas con la composición de GPU. Tendrán la ventaja de que se controlan directamente en la GPU y no requerirán que se vuelva a dibujar el contenido de la capa. Sin embargo, las propiedades que afecten el diseño de la página seguirán siendo relativamente lentas.

Sugerencia 7: Para las operaciones pesadas en la CPU, los Web Workers brindan

Los trabajadores web tienen dos beneficios importantes: 1) Son rápidos. 2) Mientras se omiten en tus tareas, el navegador no deja de responder. Consulta la presentación de diapositivas de HTML5 para Workers en acción. Estas son algunas situaciones posibles en las que podrías usar Web Workers:

  • Formato de texto de un documento largo
  • Resaltado de sintaxis
  • Procesamiento de imágenes
  • Síntesis de imágenes
  • Cómo procesar arrays grandes

Sugerencia 8: Atributos de formulario HTML5 y tipos de entrada

HTML5 presenta un nuevo conjunto de tipos de entrada y actualiza nuestro conjunto de text, password y file para incluir search, tel, url, email, datetime, date, month, week, time, datetime-local, number, range y color. La compatibilidad de los navegadores con estas opciones varía, y Opera está implementando la mayoría en este momento. Con la detección de funciones, puedes determinar si el navegador cuenta con compatibilidad nativa (y ofrecerá una IU como un selector de fecha o un selector de color) y, de lo contrario, puedes continuar usando los widgets JS para realizar estas tareas comunes. Además de los tipos, se agregaron algunos atributos útiles a nuestros campos de entrada normales. La entrada placeholder ofrece texto predeterminado que se borra cuando haces clic en ellas y autofocus enfoca el signo de intercalación en la carga de la página para que puedas interactuar inmediatamente con ese campo. La validación de entrada es otro aspecto que se está expandiendo con HTML5. Si agregas el atributo required, el navegador no permitirá que se envíe el formulario hasta que se complete el campo. Además, el atributo pattern te permite especificar una expresión regular personalizada para que se pruebe la entrada, con valores no válidos que bloquean el envío de formularios. Esta sintaxis declarativa implica una gran actualización, no solo en la legibilidad de la fuente, sino también en una reducción significativa del código JavaScript necesario. Nuevamente, puedes usar la detección de funciones para entregar una solución de resguardo si no hay compatibilidad nativa para estas. Usar los widgets nativos aquí significa que no necesitas enviar el código JavaScript y CSS intensivo para obtener estos widgets, lo que acelera la carga de la página y probablemente mejora la capacidad de respuesta del widget. Para probar algunas de estas mejoras de entrada, consulta la Presentación de diapositivas de HTML5.

Sugerencia 9: Usa efectos CSS3 en lugar de solicitar imágenes pesadas

CSS3 ofrece muchas posibilidades de diseño nuevas que sustituyen nuestro uso de imágenes para representar el diseño visual con precisión. Reemplazar una imagen 2K por 100 bytes de CSS es una gran ventaja, sin mencionar que quitaste otra solicitud HTTP. Estas son algunas propiedades que debes conocer:

  • Gradientes lineales y radiales
  • Radio del borde de las esquinas redondeadas
  • Sombra paralela para sombras paralelas y resplandor
  • RGBA para opacidad alfa
  • Transformaciones para rotación
  • Máscaras CSS

Por ejemplo, puedes crear botones muy pulidos mediante gradientes y replicar muchos otros efectos sans-images. La compatibilidad de los navegadores con la mayoría de ellos es muy sólida, y puedes usar una biblioteca como Modernizr para detectar navegadores que no admitan las funciones y usar imágenes en un caso de resguardo.

Sugerencia 10: WebSockets para una entrega más rápida con menos ancho de banda que XHR

WebSockets se diseñó en respuesta a la creciente popularidad de Comet. De hecho, ahora hay ventajas de usar WebSockets en lugar del modelo Comet sobre XHR.

WebSockets tiene un enmarcado muy ligero, por lo que el ancho de banda que consume suele ser más ligero que el de XHR. Algunos informes indican una reducción del 35% en los bytes enviados por el cable. Además, en mayor volumen, es más evidente la diferencia de rendimiento en cuanto a la entrega de mensajes. XHR se registró en esta prueba con un tiempo agregado de un 3,500% más largo que WebSockets. Por último, Ericcson Labs consideró el rendimiento de WebSockets y descubrió que los tiempos de ping en HTTP eran entre 3 y 5 veces mayores que en WebSockets debido a requisitos de procesamiento más sustanciales. Concluyeron que el protocolo WebSocket era claramente más adecuado para aplicaciones en tiempo real.

Recursos adicionales

Para las recomendaciones de medición y rendimiento, sin duda debes usar las extensiones de Firefox Page Speed e YSlow. Además, Speed Tracer para Chrome y DynaTrace Ajax para IE ofrecen un nivel más detallado de registro de análisis.