Bonnes pratiques pour créer une application Web plus rapide grâce au HTML5

Introduction

Une grande partie du langage HTML5 vise à assurer la compatibilité des navigateurs natifs avec les composants et les techniques que nous avons réalisés jusqu'à présent via les bibliothèques JavaScript. Lorsqu'elles sont disponibles, ces fonctionnalités peuvent finir par offrir une expérience beaucoup plus rapide à vos utilisateurs. Dans ce tutoriel, je ne vais pas récapituler les excellents résultats de recherche sur les performances que vous avez pu voir sur le site Exceptional Performance de Yahoo, ou dans la documentation Page Speed de Google, ainsi que sur le site Accélérons le Web. Voyons plutôt comment utiliser les langages HTML5 et CSS3 aujourd'hui pour rendre vos applications Web plus réactives.

Conseil 1: Utilisez le stockage Web à la place des cookies

Bien que les cookies soient utilisés pour suivre les données d'utilisateurs uniques depuis des années, ils présentent de sérieux inconvénients. Le principal défaut est que toutes les données de vos cookies sont ajoutées à chaque en-tête de requête HTTP. Cela peut avoir un impact mesurable sur le temps de réponse, en particulier lors des requêtes XHR. Il est donc recommandé de réduire la taille des cookies. En HTML5, nous pouvons faire mieux que cela: utiliser sessionStorage et localStorage à la place des cookies.

Ces deux objets de stockage Web peuvent servir à conserver les données utilisateur côté client pendant toute la durée de la session ou indéfiniment. Leurs données ne sont pas non plus transmises au serveur via chaque requête HTTP. Il dispose d'une API qui vous fera plaisir de vous débarrasser des cookies. Voici les deux API, qui utilisent des cookies en remplacement.

// 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;
}

Conseil 2: Utilisez des transitions CSS plutôt que des animations JavaScript

Les transitions CSS constituent une transition visuelle attrayante entre deux états. La plupart des propriétés de style peuvent faire l'objet d'une transition, par exemple pour manipuler l'ombre du texte, la position, l'arrière-plan ou la couleur. Vous pouvez utiliser des transitions vers des états de pseudo-sélecteur, tels que :hover, ou à partir de formulaires HTML5, :invalid et :valid (exemple avec les états de validation de formulaire). Mais ils sont beaucoup plus puissants et peuvent être déclenchés lorsque vous ajoutez une classe à un élément.

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; }

En ajoutant l'activation et la désactivation des classes de totheleft et totheright, vous pouvez déplacer la zone. Comparez cette quantité de code à celle d'une bibliothèque d'animation JavaScript. De toute évidence, le nombre d'octets envoyés au navigateur est bien inférieur lorsque vous utilisez une animation CSS. De plus, grâce à l'accélération au niveau du GPU, ces transitions visuelles seront aussi fluides que possible.

Conseil 3: Utiliser des bases de données côté client plutôt que des allers-retours du serveur

Les bases de données Web SQL et IndexedDB introduisent des bases de données côté client. Au lieu du schéma courant consistant à publier des données sur le serveur via XMLHttpRequest ou à envoyer un formulaire, vous pouvez exploiter ces bases de données côté client. La diminution du nombre de requêtes HTTP est l'objectif principal de tous les ingénieurs en performances. Par conséquent, leur utilisation comme magasin de données peut permettre d'économiser de nombreux trajets via XHR ou de renvoyer des messages au serveur. localStorage et sessionStorage peuvent être utilisés dans certains cas, par exemple pour enregistrer la progression de l'envoi d'un formulaire. Ils ont été nettement plus rapides que les API de base de données côté client. Par exemple, si vous disposez d'un composant de grille de données ou d'une boîte de réception contenant des centaines de messages, le stockage local des données dans une base de données vous permettra d'éviter les allers-retours HTTP lorsque l'utilisateur souhaite rechercher, filtrer ou trier. Une liste d'amis ou une saisie semi-automatique peut être filtrée à chaque frappe, ce qui rend l'expérience utilisateur beaucoup plus réactive.

Conseil n° 4: les améliorations apportées à JavaScript offrent des avantages considérables en termes de performances.

De nombreuses méthodes supplémentaires ont été ajoutées au prototype "Array" dans JavaScript 1.6. Ces fonctionnalités sont actuellement disponibles dans la plupart des navigateurs, à l'exception d'IE. Exemple :

// 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');
});

Dans la plupart des cas, l'utilisation de ces méthodes natives permet d'obtenir des vitesses beaucoup plus rapides que les boucles For habituelles, comme for (var i = 0, len = arr.length; i &lt; len; i++). L'analyse JSON native (via JSON.parse()) remplace le fichier json2.js que nous avons l'habitude d'inclure depuis un certain temps. Le format JSON natif est beaucoup plus rapide et plus sûr que l'utilisation d'un script externe. Il est déjà disponible dans IE8, Opera 10.50, Firefox 3.5, Safari 4.0.3 et Chrome. Le String.trim natif est un autre bon exemple d'être non seulement plus rapide que les équivalents JavaScript, mais aussi d'être potentiellement plus correct. Techniquement, aucun de ces ajouts JavaScript n'est HTML5, mais ils s'inscrivent dans le cadre des technologies qui seront bientôt disponibles.

Conseil n° 5: Utilisez le fichier manifeste du cache pour les sites en ligne, pas seulement pour les applications hors connexion

Il y a deux ans, WordPress a utilisé Google Gears pour ajouter une fonctionnalité appelée WordPress Turbo. Il mettait en cache la plupart des ressources utilisées dans le panneau d'administration localement, ce qui accélérait l'accès aux fichiers. Nous pouvons reproduire ce comportement avec applicationCache de HTML5 et cache.manifest. Le cache de l'application présente un léger avantage par rapport à la définition d'en-têtes Expires. Étant donné que vous créez un fichier déclaratif indiquant les ressources statiques pouvant être mises en cache, les navigateurs peuvent procéder à une optimisation poussée, voire les mettre en cache avant votre utilisation. Considérez la structure de base de votre site comme un modèle. Certaines de vos données peuvent changer, mais le code HTML qui les entoure reste généralement assez cohérent. Avec le cache d'application, vous pouvez traiter votre code HTML comme une série de modèles purs, mettre en cache le balisage via cache.manifest, puis transmettre le code JSON sur le réseau pour mettre à jour le contenu. Ce modèle est très semblable à celui d'une application d'actualités native Android ou iPhone.

Conseil n° 6: Activez l'accélération matérielle pour améliorer l'expérience visuelle

Dans les principaux navigateurs, de nombreuses opérations visuelles peuvent exploiter l'accélération au niveau du GPU, ce qui permet de rendre les opérations visuelles très dynamiques beaucoup plus fluides. L'accélération matérielle a été annoncée pour Firefox Minefield et IE9, et Safari a ajouté cette fonctionnalité dans la version 5. (L'application est disponible dans Safari pour mobile bien plus tôt.) Chromium venait d'ajouter des transformations 3D et l'accélération matérielle pour Windows. Les deux autres plates-formes seront bientôt disponibles.

L'accélération du GPU ne s'active que dans des conditions relativement limitées, mais les transformations 3D et l'opacité d'animation sont les moyens les plus courants de faire tomber le bouton bascule. Voici une façon assez pratique mais discrète de l'activer:

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

Ce n'est toutefois pas garanti. :) Si l'accélération matérielle est prise en charge et activée, la translation, la rotation, la mise à l'échelle et l'opacité animées seront plus fluides avec la composition GPU. Elles ont l'avantage d'être gérées directement sur le GPU et ne nécessitent pas de redessiner le contenu du calque. Toutefois, toute propriété qui affecte la mise en page sera toujours relativement lente.

Conseil n° 7: Pour les opérations gourmandes en processeur, les Web Workers fournissent

Les Web Workers présentent deux avantages majeurs: 1) Ils sont rapides. 2) Pendant qu'ils maîtrisent vos tâches, le navigateur reste réactif. Découvrez la présentation HTML5 pour Google Workers en action. Voici quelques cas d'utilisation possibles de Web Workers:

  • Mise en forme du texte d'un document long
  • Coloration syntaxique
  • Traitement des images
  • Synthèse d'images
  • Traiter de grands tableaux

Conseil n° 8: Attributs de formulaire HTML5 et types de saisie

HTML5 introduit un nouvel ensemble de types d'entrées, qui met à jour notre ensemble de text, password et file pour inclure search, tel, url, email, datetime, date, month, week, time, datetime-local, number, range et color. Les navigateurs pris en charge varient, et Opera est la plupart d'entre eux en implémentation pour le moment. Grâce à la détection des fonctionnalités, vous pouvez déterminer si le navigateur est compatible de façon native (et proposer une UI telle qu'un sélecteur de date ou un sélecteur de couleur). Si ce n'est pas le cas, vous pouvez continuer à utiliser les widgets JavaScript pour effectuer ces tâches courantes. En plus des types, quelques caractéristiques utiles ont été ajoutées aux champs de saisie habituels. Le texte placeholder d'entrée s'efface par défaut lorsque vous cliquez dessus, et autofocus sélectionne le curseur de saisie au chargement de la page afin que vous puissiez interagir immédiatement avec ce champ. La validation des entrées est une autre étape à suivre avec HTML5. Si vous ajoutez l'attribut required, le navigateur ne permettra pas l'envoi du formulaire tant que ce champ n'aura pas été renseigné. L'attribut pattern vous permet également de spécifier une expression régulière personnalisée par rapport à l'entrée à tester. Des valeurs non valides bloquent l'envoi de formulaires. Cette syntaxe déclarative représente une nette amélioration de la lisibilité du code source, mais également une réduction significative des besoins en JavaScript. Là encore, vous pouvez utiliser la détection de caractéristiques pour diffuser une solution de remplacement si elles ne sont pas compatibles de façon native. Grâce aux widgets natifs, vous n'avez pas besoin d'envoyer les fichiers JavaScript et CSS nécessaires pour extraire ces widgets, ce qui accélère le chargement des pages et améliore probablement la réactivité du widget. Pour essayer certaines des améliorations apportées à la saisie, consultez la présentation HTML5.

Conseil n° 9: Utilisez des effets CSS3 au lieu de demander des sprites sous forme d'images épaisses.

Le CSS3 offre de nombreuses nouvelles possibilités de style qui supplantent l'utilisation d'images pour représenter fidèlement la conception visuelle. Le remplacement d'une image 2K par 100 octets CSS est une grande victoire, sans oublier que vous avez supprimé une autre requête HTTP. Voici quelques-unes des propriétés à connaître:

  • Dégradés linéaires et radiaux
  • Arrondi de la bordure pour les angles arrondis
  • Ombre de la boîte pour les ombres projetées et le halo
  • RVBA pour l'opacité alpha
  • Transformations pour la rotation
  • Masques CSS

Par exemple, vous pouvez créer des boutons très soignés avec des dégradés et reproduire de nombreux autres effets sans image. La compatibilité du navigateur pour la plupart de ces cas d'utilisation est très efficace. Vous pouvez utiliser une bibliothèque telle que Modernizr pour identifier les navigateurs qui ne sont pas compatibles avec ces fonctionnalités afin d'utiliser des images dans une demande de remplacement.

Conseil n° 10: WebSockets pour une diffusion plus rapide avec moins de bande passante qu'avec XHR

WebSockets a été conçu en réponse à la popularité croissante de Comet. L'utilisation de WebSockets présente effectivement des avantages par rapport au modèle Comet sur XHR.

WebSockets présente un cadrage très léger. La bande passante qu'il consomme est donc souvent plus légère que celle de XHR. Certains rapports indiquent une réduction de 35% du nombre d'octets envoyés sur le réseau. En outre, dans les volumes plus élevés, la différence de performances en termes de distribution des messages est plus flagrante. XHR a été enregistré dans ce test avec une durée agrégée 3 500% plus longue que celle de WebSockets. Enfin, Ericcson Labs a examiné les performances de WebSockets et a constaté que les temps de ping sur HTTP étaient trois à cinq fois plus importants que sur WebSockets en raison d'exigences de traitement plus importantes. Ils en ont conclu que le protocole WebSocket était clairement plus adapté aux applications en temps réel.

Autres ressources

Pour obtenir des recommandations sur les mesures et les performances, vous devez absolument utiliser les extensions Firefox Page Speed et YSlow. De plus, Speed Tracer pour Chrome et DynaTrace Ajax pour IE fournissent un niveau de journalisation d'analyse plus détaillé.