La tête dans le Flux !

RSS

Posts tagged with "performance"

Avr 6

Contribution à WedDesign Friday

“Introduction à la performance pour le Web mobile” est le sujet que j’ai traité sur le site du Webdesign Friday.

Comme je le précise, il s’agit d’une mise en bouche. Il y aurait matière à décortiquer chaque conseil et aller beaucoup plus loin que ce court article, mais il faut bien commencer par quelque chose, non ? ;)

Voici donc le billet en question : “Introduction à la performance pour le Web mobile”. Bonne lecture et n’hésitez pas à laisser vos retours directement sur l’article.

media queries et performances web mobile

Ce billet fait suite à mes expérimentations continues concernant la performance web pour les mobiles. J’en étais arrivé à un billet nommé “comment cibler les mobiles de manière optimales (bis) ?”.

Voici la suite de mes élucubrations…

Un point sur l’existant

Il existe grosso-modo 6 méthodes d’application des CSS3 media queries :

  1. un fichier CSS composé de styles généraux pour tous et de media queries pour mobiles.
    Problème : un navigateur mobile respecte les deux conditions à la fois (les styles globaux et ceux pour pour mobile), il va donc en toute logique charger les ressources… puis les masquer.
  2. un élément <link> appelant une feuille CSS globale et une autre feuille CSS pour mobiles (via media queries).
    Problème : identique au précédent.
  3. un fichier CSS unique composé de media queries exclusifs, par exemple @media (min-width : 641px) {…} / @media (max-width : 640px) {…}
    Problème : les anciens navigateurs dont Internet Explorer inférieur à IE9 ne reconnaissent pas media queries et n’auront qu’une page HTML brute de styles.
  4. un élément <link> appelant des feuille CSS exclusives via media queries (une pour grands écrans et une autre pour mobiles).
    Problème : identique au précédent.
  5. appliquer une rustine sous forme de commentaires conditionnels pour cibler les anciennes versions d’Internet Explorer.
    Problème : cette méthode nécessite une requête de fichier CSS supplémentaire, généralement non parallélisée.
  6. se baser sur des alternatives JavaScript telles que Respond qui émule les media queries sur les anciennes versions d’Internet Explorer.
    Problème : cette méthode nécessite une requête de fichier JavaScript ainsi que son traitement par le navigateur.

Une méthode pour les réunir toutes ?

Plus j’y réfléchis, plus je suis persuadé qu’une solution intermédiaire est de distinguer 3 parties dans le fichier CSS :

  1. les styles de base, qui doivent être affichés sur tous les supports (pas de media query)
  2. les ressources lourdes, qui doivent être chargées uniquement sur écrans larges (via media queries)
  3. les styles et adaptations spécifiques pour petits écrans (via media queries)

Grâce aux classes conditionnelles, nous pourrons également en faire profiter les anciennes versions d’Internet Explorer sans douleur.

Voici un exemple concret :

/* styles pour tous */
body {width: 960px; background: #fff;}

/* ressources CSS lourdes uniquement */
@media (min-width : 641px) {body {background: url(concombre_big.jpg);}}

/* ressources lourdes aussi pour IE6-IE8 */
.oldie body {background: url(concombre_big.jpg);}

/* styles pour petits écrans */
@media (max-width : 640px) {body {width: auto; background: url(concombre_small.jpg);}}

Au final, il me semble que tous les écueils de performance sont évités, au prix d’une répartition plus réfléchie des ressources.

Cette méthode a actuellement ma préférence car ne nécessite pas de fichier CSS (donc de requête) supplémentaire, ni d’alternative et de traitement via JavaScript.

Test perso : hacks CSS et performances des sélecteurs

Avec l’émergence du “Web mobile”, le concept de performance web est en pleine ébullition : on peut comprendre que chaque milliseconde de perdue sur une connexion 3G est un désatre.

Parmi les thèmes où l’on entend tout et son contraire, on trouve l’idée de “Sélecteurs CSS efficients” qui prône l’usage de certains types de sélecteurs au détriment d’autres censés être plus coûteux en performance.

On en vient à diaboliser certains sélecteurs autrefois propres sur eux, voire certaines méthodes de commentaires conditionnels.

J’ai voulu procéder à une petite expérience personnelle pour en tirer quelques conclusions qui n’engagent que moi…

Le test

Le test se déroule ainsi : je crée 4 fichiers HTML composés d’un div de class=”lol” dans lequel se trouve un paragraphe.

Par ailleurs, au sein d’une feuille de styles externe, j’applique la propriété border-radius (reconnue pour être assez gourmande) sur le paragraphe. Le tout répété 1000 fois dans le fichier CSS !

Les seules différences entre les 4 feuilles de styles est le type de déclaration :

  1. fichier CSS 1 : 1000x un sélecteur existant + propriété existante :
    .lol p {border-radius: 1337px;}
  2. fichier CSS 2 : 1000x un sélecteur introuvable + propriété existante :
    .ie7 p {border-radius: 1337px;}
  3. fichier CSS 3 : 1000x un sélecteur existant + propriété inexistante (hack) :
    .lol p {*border-radius: 1337px;}
  4. fichier CSS 4 : 1000x un sélecteur introuvable + propriété inexistante (hack) :
    .ie7 p {*border-radius: 1337px;}

Le but du jeu est de vérifier qu’il existe bel et bien une différence de performances selon les types de sélecteurs et les propriétés.

Résultats

1 : .lol p {border-radius: 1337px;} x1000
  • Chargement des styles : 266ms
  • (Chargement total : 518ms)
  • (Chargement total sur mobile iPhone4 : 2.83s)
2 : .ie7 p {border-radius: 1337px;} x1000
  • Chargement des styles : 265ms
  • (Chargement total : 468ms)
  • (Chargement total sur mobile iPhone4 : 2.79s)
3 : .lol p {*border-radius: 1337px;} x1000
  • Chargement des styles : 360ms
  • (Chargement total : 568ms)
  • (Chargement total sur mobile iPhone4 : 2.49s)
4 : .ie7 p {*border-radius: 1337px;} x1000
  • Chargement des styles : 265ms
  • (Chargement total : 504ms)
  • (Chargement total sur mobile iPhone4 : 2.5s)

Interprétation personnelle

Ce petit test amateur ne prétend pas jouer dans la cour des grands, je n’ai déployé que de maigres moyens (Firebug pour les temps de chargement bureau, et Blaze.io pour le mobile).

Cependant, s’il n’y avait qu’une seule conclusion à en tirer, c’est que les inégalités de latence entre les sélecteurs paraîssent bien minimes, voire négligeables !

A quelques exceptions près, quel que soit le sélecteur (que le navigateur le trouve ou non) et quelle que soit la propriété (hack ou non), le temps de chargement est quasiment identique, en tout cas pour des feuilles CSS de 1000 lignes et environ 34ko.

De très légères disparités apparaissent pour les cas suivants : il semble qu’une propriété “hack” appliquée à un sélecteur existant (cas n°3) soit un peu plus coûteuse en performance pour le navigateur.

J’espère que les conditions d’expérience n’étaient pas trop biaisées et que mes déductions n’en sont pas complètement fausses.

Requêtes, parallélisation et mobiles

En 2009, Steve Souders, un expert dans le domaine de la performance web, avait annoncé qu’il ne fallait pas utiliser @import pour appeler ses feuilles de styles CSS.

L’explication est simple : plusieurs fichiers CSS appelés via <link> peuvent être “parallélisés”, c’est à dire chargés en même temps; ce qui n’est pas le cas de fichiers appelés via @import : les styles sont chargés un par un.

Il est bien entendu possible d’utiliser @import de façon pertinente, mais pour des raisons de facilité et de performances, il est devenu conventionnel de se limiter aux appels de styles via <link>.

Mais ça, c’était avant… la propagation du Web sur smartphones et tablettes.

En effet, il semble que tous les navigateurs mobiles ne soient pas sur un même pied d’égalité en ce qui concerne la gestion intelligente des requêtes et des ressources. Grâce à une discussion intéressante avec Simon Boudrias, j’ai procédé à quelques tests de performances mobile, et ma conclusion personnelle est assez édifiante.

Présentation et principe du test

L’idée générale est d’observer comment sont chargées (ou non) différentes feuilles de styles dédiées testant une page HTML dans l’outil en ligne de Blaze.io/mobile, qui semble unanimement pertinent.

Dans tous les cas, les 4 feuilles CSS sont appelées via <link> dans le <head> du document.

<link href="styles.css" media="screen">
<link href="print.css" media="print">
<link href="tv.css" media="tv">
<link href="mobile.css" media="screen and (max-width:800px)">

Observation 1 : Safari mobile est un cancre

Résultat du test sur iPhone 4

performances de chargement sur iPhone4

Résultat du test sur iPad 2

performances de chargement sur iPad 2

Que ce soit sur iPhone ou iPad, Safari mobile ne semble pas gérer les téléchargements simultanés : les fichiers de styles sont chargés l’un après l’autre et le navigateur attend que le dernier soit chargé avant de poursuivre le chargement de toutes les autres ressources de la page !

La page a mis 2.86s a être intégralement chargée sur iPhone et 1.94s a être intégralement chargée sur iPad.

Observation 2 : d’autres navigateurs mobiles s’en sortent mieux

Résultat du test sur Android 3

performances de chargement sur Android 3

Résultat du test sur Android 2.3

performances de chargement sur Android 2.3

La page a mis 0.55s a être intégralement chargée sur Android 3, et 1.21s sur Android 2.3.

La solution réside-t-elle dans l’unification ?

Puisque Safari ne gère pas correctement la parallélisation des chargements, voyons quel est le résultat en regroupant tous les fichiers de styles en un seul fichier CSS unique.

Résultat du test (CSS unique) sur iPhone 4

performances avec feuille CSS unique

La page de test contenant une feuille de style unifiée a mis 1.95s a être intégralement chargée sur iPhone 4, soit près d’une seconde de différence pour une page de moins 2ko !

Il paraît donc évident que le nombre de requêtes (en tout cas pour certains navigateurs) a une incidence non négligeable sur le délai d’affichage des sites sur mobiles.

Résultat du test (CSS unique et minifié) sur iPhone 4

performances avec feuille CSS unique et minifiée

Dans ce dernier test, j’ai poussé jusqu’à minifier au maximum la taille du fichier CSS unique à l’aide de CleanCSS. Le fichier a ainsi été réduit de 45%, mais la différence de performance n’est pas flagrante : la page a mis 1.8s a être intégralement chargée sur iPhone 4.

Nous sommes encore loin des performances d’affichage sur Android, mais on a fait ce qu’on a pu :)

Je pense qu’il y a encore beaucoup à dire sur ce sujet brûlant… et ça tombe bien, la discussion est ouverte. N’hésitez pas à laisser vos commentaires, vos avis et tests personnels.

Think Mobile First !

Le courant de pensée “Think Mobile First” (penser mobile d’abord) prend de plus en plus d’essor pour de multiples raisons, notamment :

  1. L’utilisation de mobile explose
  2. Le Web mobile va à l’essentiel
  3. Le Web mobile permet bien plus

Think Mobile First, c’est quoi ?

Cette philosophie est pour le moins séduisante puisqu’elle nous oblige à repenser nos codes et carcans de design web : commencer par le plus dénominateur commun (le mobile), puis enrichir progressivement pour les écrans larges; or les éléments inutiles n’ont pas de place dans un écran de 480 pixels de large !

L’idée, bien que récente, n’est pas nouvelle. Elle a été introduite par Luke Wroblewski (dont le livre “Mobile First” sera très prochainement traduit en français), reprise dans plusieurs conférences de webdesign mobile, et traduite sur Pompage.net.

Oui mais…

Le principal écueil de cette méthode est qu’elle repose généralement sur de la détection via des fonctions CSS3 MediaQueries, non reconnues par Internet Explorer 6 à 8.

Il existe bien entendu des polyfills (alternatives) tels que Respond.js, mais je ne suis guère fan de tout ce qui surcharge les requêtes, les traitements et les performances de navigateurs déjà mal en point.

Vers une solution idéale ?

Du coup, j’ai peut-être une solution qui devrait fonctionner assez bien partout, quel que soit le navigateur…

Première étape : par défaut, les styles CSS pour la version mobile
<link rel="stylesheet" href="styles.css">
Deuxième étape : des styles enrichis pour les écrans larges

Cette feuille de style pourra bien entendu comporter des media queries internes sous forme @media (min-width: 1200px) par exemple pour faire des distinctions et des styles différents selon les tailles.

<link rel="stylesheet" href="styles_big.css" media="screen and (min-device-width:640px)">
Troisième étape : cibler Internet Explorer

Puisqu’il ne reconnaît pas les mediaqueries avant IE9, on lui charge la feuille CSS “big” via commentaire conditionnel. Seul Explorer de bureau est ciblé; IE mobile se contente de la feuille de base mobile.

<!--[if lt IE 9]>
	<link rel="stylesheet" href="styles_big.css">
<![endif]-->
Tout réuni

Au final, on obtient :

<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="styles_big.css" media="screen and (min-device-width:640px)">

<!--[if lt IE 9]>
	<link rel="stylesheet" href="styles_big.css">
<![endif]-->

Au final, nous avons 2 feuilles de styles appliquées. Les avantages principaux étant non-seulement de ne plus avoir à se soucier de savoir comment détecter les mobiles, mais également de ne pas leur faire charger des ressources inutiles pour eux.

Que pensez-vous de la philosophie générale et de la technique proposée ?

EDIT : suite à de nouveaux rebondissements, il s’avère que cette méthode nécessitant deux fichiers CSS n’est pas forcément la plus performante pour les mobiles. Ce billet sera sans-doute remanié en conséquence.

Performances : toutes les feuilles de styles sont chargées

La performance dans le Web mobile est une notion capitale : il est crucial de prendre en compte le poids des éléments, les temps de chargement, les requêtes superflues, sous peine de grosses désillusions selon les projets.

J’ai lu récemment qu’une feuille de style CSS dédiée “mobile” était chargée par le navigateur même si elle n’était pas applicable (par exemple avec une condition de taille alors que l’écran ne respecte pas cette taille) et qu’il était nécessaire de procéder à plein de bidouilles pour éviter ce chargement inutile.

Du coup, je me suis amusé à faire un petit test sur une page web hébergée (temporairement) sur http://goetter.fr/tmp/test.html

Principe du test

L’idée générale est d’observer comment sont chargées (ou non) différentes feuilles de styles dédiées à des médias très différents (mobile, mais aussi print et TV) en ouvrant la page HTML dans mon navigateur de bureau préféré.

Les différentes feuilles de styles appelées sont :

<link rel="stylesheet" href="styles.css" media="screen">
<link rel="stylesheet" href="print.css" media="print">
<link rel="stylesheet" href="tv.css" media="tv">
<link rel="stylesheet" href="mobile.css" media="screen and (max-width:800px)">

Pour rajouter un peu de piment, la feuille de style “mobile” a le bon goût d’appeler un fichier d’image d’arrière-plan appliqué sur body dès lors que la largeur de fenêtre est inférieure à 800px

Observations

  • Quel que soit le périphérique ou taille d’écran, toutes les feuilles de styles (même non appliquées/applicables) sont chargées,
  • L’image d’arrière-plan présente dans les règles CSS de mobile.css n’est chargée que lorsque la taille d’écran est inférieure ou égale à 800 pixels,
  • Le navigateur charge tout d’abord séparément le fichier HTML, puis le premier fichier CSS, puis parallélise les chargements des feuilles CSS suivantes.
  • Note en passant : j’ai utilisé Firefox 8, qui n’applique pas le média TV mais qui charge quand-même la feuille de style (au cas où ;))

requetes sur grand écran

requetes sur petit écran

Ma conclusion

Les inconvénients que l’on prête aux feuilles CSS dédiées mobiles sont exactement les mêmes que pour les autres médias : la feuille de style est inexorablement chargée, au cas où elle serait interprétée un jour.

Par contre, la bonne nouvelle - et c’est rassurant - est que les médias (images de fond par exemple) appelés dans cette feuille CSS mobile ne sont chargés par le navigateur que lorsqu’il en a besoin, c’est à dire lorsque la taille d’écran correspond au Media Query désiré.

Bref, rien de très excitant mais le “problème” de performance est, selon moi, assez négligeable, et je vais continuer un petit moment à employer ma technique préférée pour cibler les mobiles de manière optimale :)