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

Introduction

Une grande partie de la norme HTML5 vise à fournir une compatibilité native avec les composants et les techniques que nous avons obtenus jusqu'à présent via les bibliothèques JavaScript. Si elles sont disponibles, l'utilisation de ces fonctionnalités peut offrir une expérience beaucoup plus rapide à vos utilisateurs. Dans ce tutoriel, je ne vais pas récapituler les excellentes recherches sur les performances que vous avez pu consulter sur le site sur les performances exceptionnelles de Yahoo, ni dans les documents PageSpeed et sur le site Let's make the web faster (Faisons en sorte que le Web soit plus rapide) de Google. Je vais plutôt vous expliquer comment utiliser HTML5 et CSS3 dès aujourd'hui pour rendre vos applications Web plus réactives.

Conseil 1: Utiliser le stockage Web au lieu des cookies

Bien que les cookies soient utilisés depuis des années pour suivre les données utilisateur uniques, ils présentent de graves inconvénients. Le plus gros défaut est que toutes vos données de cookie sont ajoutées à chaque en-tête de requête HTTP. Cela peut avoir un impact mesurable sur le délai 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: utiliser sessionStorage et localStorage à la place des cookies.

Ces deux objets de stockage Web peuvent être utilisés pour 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 transférées vers le serveur via chaque requête HTTP. Ils disposent d'une API qui vous permettra de vous débarrasser des cookies. Voici les deux API, qui utilisent des cookies comme solution de 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 qu'une animation JavaScript

Les transitions CSS vous permettent d'effectuer une transition visuelle attrayante entre deux états. La plupart des propriétés de style peuvent être modifiées, par exemple en manipulant l'ombre portée du texte, la position, l'arrière-plan ou la couleur. Vous pouvez utiliser des transitions vers des états de pseudo-sélecteurs tels que :hover ou à partir de formulaires HTML5, :invalid et :valid (exemple avec des états de validation de formulaire). Toutefois, 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 les classes totheleft et totheright, vous pouvez déplacer la zone. Comparez cette quantité de code à celle d'une bibliothèque d'animation JavaScript. Il est clair que le nombre d'octets envoyés au navigateur est beaucoup moins élevé lorsque vous utilisez une animation basée sur CSS. De plus, avec l'accélération au niveau du GPU, ces transitions visuelles seront aussi fluides que possible.

Conseil 3: Utilisez des bases de données côté client au lieu de faire des aller-retours vers le serveur

Base de données SQL Web et IndexedDB introduisent les bases de données côté client. Au lieu du modèle courant consistant à publier des données sur le serveur via XMLHttpRequest ou l'envoi d'un formulaire, vous pouvez exploiter ces bases de données côté client. La réduction des requêtes HTTP est une cible principale de tous les ingénieurs en performances. L'utilisation de ces requêtes comme datastore peut donc économiser de nombreux aller-retour via XHR ou des envois de formulaires vers le serveur. localStorage et sessionStorage peuvent être utilisés dans certains cas, par exemple pour capturer la progression de l'envoi d'un formulaire. Ils se sont révélés 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 évitera d'effectuer des aller-retours HTTP lorsque l'utilisateur souhaite effectuer une recherche, un filtrage ou un tri. Une liste d'amis ou une saisie semi-automatique de texte peuvent être filtrées à chaque frappe, ce qui offre une expérience utilisateur beaucoup plus réactive.

Conseil 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. Ils sont désormais 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 accélère considérablement les vitesses par rapport à votre boucle for classique, par exemple: 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 avions l'habitude d'inclure depuis un certain temps. Le JSON natif est beaucoup plus rapide et plus sécurisé 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. String.trim natif est un autre bon exemple de code non seulement plus rapide que les équivalents JS manuels, mais aussi potentiellement plus correct. Aucune de ces extensions JavaScript n'est techniquement HTML5, mais elles font partie des technologies récemment disponibles.

Conseil 5: Utilisez un fichier manifeste de cache pour les sites en ligne, et 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 a essentiellement mis en cache localement de nombreuses ressources utilisées dans le panneau d'administration, ce qui a accéléré l'accès aux fichiers. Nous pouvons reproduire ce comportement avec l'applicationCache de HTML5 et cache.manifest. Le cache de l'application présente un léger avantage par rapport au paramétrage des en-têtes Expires. En effet, vous créez un fichier déclaratif indiquant les ressources statiques pouvant être mises en cache. Les navigateurs peuvent donc les optimiser considérablement, voire les pré-mettre en cache avant que vous ne les utilisiez. Considérez la structure de base de votre site comme un modèle. Vous disposez de données susceptibles de changer, mais le code HTML qui les entoure reste généralement assez cohérent. Avec le cache de l'application, vous pouvez traiter votre code HTML comme une série de modèles purs, mettre en cache le balisage via le fichier cache.manifest, puis transmettre du code JSON par ligne pour mettre à jour le contenu. Ce modèle est très semblable à celui d'une application d'actualités native pour iPhone ou Android.

Conseil 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 peut 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é l'accélération au niveau matériel dans la version 5. (Elle est disponible dans Mobile Safari depuis bien plus longtemps.) Chromium vient d'ajouter les 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 se déclenche que dans un ensemble assez restreint de conditions, mais les transformations 3D et l'opacité animée sont les moyens les plus courants de déclencher l'activation. Pour l'activer, procédez comme suit:

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

Aucune garantie, cependant. :) Avec l'accélération matérielle activée, la traduction, la rotation, le scaling et l'opacité animés seront certainement plus fluides avec le compositing GPU. Elles ont l'avantage d'être gérées directement sur le GPU et ne nécessitent pas de redessiner le contenu des calques. Toutefois, toute propriété qui affecte la mise en page de la page sera toujours relativement lente.

Conseil 7: Pour les opérations gourmandes en CPU, les Web Workers sont efficaces

Les Web Workers présentent deux avantages importants: 1) Ils sont rapides. 2) Pendant qu'ils effectuent vos tâches, le navigateur reste réactif. Consultez la présentation HTML5 pour découvrir les nœuds de calcul en action. Voici quelques situations dans lesquelles vous pouvez utiliser des Web Workers:

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

Conseil 8: Attributs et types de saisie des formulaires HTML5

HTML5 introduit un nouvel ensemble de types de saisie, en remplaçant text, password et file par search, tel, url, email, datetime, date, month, week, time, datetime-local, number, range et color. La compatibilité des navigateurs avec ces fonctionnalités varie, et Opera les implémente actuellement dans la plupart des cas. La détection de fonctionnalités vous permet de déterminer si le navigateur est compatible en mode natif (et si une UI telle qu'un sélecteur de date ou un sélecteur de couleur sera proposée). 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 fonctionnalités utiles ont été ajoutées à nos champs de saisie standards. La saisie placeholder propose un texte par défaut qui est effacé lorsque vous cliquez dessus. autofocus place le curseur au chargement de la page afin que vous puissiez interagir immédiatement avec ce champ. La validation des entrées est une autre nouveauté de HTML5. Si vous ajoutez l'attribut required, le navigateur n'autorisera 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 pour l'entrée à tester. Les valeurs non valides bloquent l'envoi du formulaire. Cette syntaxe déclarative constitue une grande amélioration, non seulement en termes de lisibilité des sources, mais aussi en termes de réduction du code JavaScript nécessaire. Encore une fois, vous pouvez utiliser la détection de fonctionnalités pour proposer une solution de remplacement si ces fonctionnalités ne sont pas prises en charge en mode natif. En utilisant les widgets natifs, vous n'avez pas besoin d'envoyer le JavaScript et le CSS lourds requis pour exécuter ces widgets. Vous accélérez ainsi le chargement de la page et améliorez probablement la réactivité des widgets. Pour essayer certaines de ces améliorations de saisie, consultez la présentation HTML5.

Conseil 9: Utilisez des effets CSS3 au lieu de demander des sprites d'images volumineux

Le CSS3 offre de nombreuses nouvelles possibilités de stylisation qui remplacent notre utilisation d'images pour représenter précisément la conception visuelle. Remplacer une image de 2 ko par 100 octets de CSS est un gain énorme, sans compter que vous avez supprimé une autre requête HTTP. Voici quelques-unes des propriétés que vous devez connaître:

  • Dégradés linéaires et radiaux
  • Border-radius pour les coins arrondis
  • Box-shadow pour les ombres portées et l'halo
  • RVBA pour l'opacité alpha
  • Transformations pour la rotation
  • Masques CSS

Par exemple, vous pouvez créer des boutons très soignés à l'aide de dégradés et reproduire de nombreux autres effets sans images. La plupart de ces fonctionnalités sont très bien prises en charge par les navigateurs. Vous pouvez utiliser une bibliothèque telle que Modernizr pour détecter les navigateurs qui ne les prennent pas en charge afin d'utiliser des images en cas de remplacement.

Conseil 10: Utiliser des 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. Il existe en effet des avantages à utiliser WebSockets maintenant, au lieu du modèle Comet over XHR.

Les WebSockets ont un cadrage très léger. Par conséquent, la bande passante qu'ils consomment est souvent plus faible que celle des XHR. Certains rapports indiquent une réduction de 35% du nombre d'octets envoyés par fil. De plus, à un volume plus élevé, la différence de performances en termes de diffusion de messages est plus évidente. Dans ce test, XHR a enregistré une durée globale de 3 500% plus longue que WebSockets. Enfin, Ericsson Labs a examiné les performances de WebSockets et a constaté que les temps de ping via HTTP étaient trois à cinq fois plus importants que via WebSockets en raison de besoins de traitement plus importants. Ils ont conclu que le protocole WebSocket était clairement plus adapté aux applications en temps réel.

Autres ressources

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