8 Mbits on the left lane
Développement Web, Google, camescope, Canon HV20, Firefox, PHP, HDV, barbecue, tarte, Blu-Ray
Il y a probablement plus d'une centaine de moteurs de template en PHP (le plus connue étant Smarty). Les templates sont un bon concept : garder la présentation dans un fichier, et la logique applicative dans un autre (et le stockage dans un troisième endroit : la base de donnée). Utiliser un langage simple et facile pour les templates de sorte que n'importe quel infographiste ou amateur de HTML pourra s'en servir, et laisser les aspects complexes de la programmation à quelque chose et quelqu'un d'autre. Oui, les templates sont utiles avec Java, C#, Python ou n'importe quel langage. Sauf PHP.
Pourquoi donc ? Voilà un indice : PHP vient de "Hypertext Preprocessor". C'est à dire en clair un système de template HTML. Et de fait, PHP est bien un langage de template : il a été créé pour être simple et facile à utiliser, et pour permettre d'insérer directement son code dans une page HTML pour en contrôler l'aspect. Alors tout ces systèmes de template pour PHP ne font au final qu'un langage de template écrit avec un autre langage de template. Doh !
Prenons par exemple quelques lignes d'un template Smarty :
{$title}
{include file='header.tpl'}
{if $a}
Hello
{else}
Bye
{/if}
Et la même chose en PHP :
<?php
echo($title);
include('header.php');
if ($a)
echo('Hello');
else
echo('Bye');
?>
Vraiment, quel est l'intérêt de réinventer la roue ?
Les moteurs de template obligent à apprendre une nouvelle synthaxe, ralentisse le traitement (car il faut lire et analyser la template), et comme toute couche logicielle supplémentaire, augmente les chances de tomber sur un bug ou une faille de sécurité. Dès lors ils ne présentent un intérêt qu'avec les langages où la génération de HTML est lourde et pénible. Est-ce le cas avec PHP ? Certainement pas.
Bien sûr, il reste toujours utile de séparer la logique et la présentation. Mais on peu parfaitement le faire sans abandonner PHP : il suffit par exemple de mettre la présentation dans la page PHP principale et de placer la logique dans des fichiers externes. Ou à l'inverse, de stocker la présentation dans une template séparée écrite en PHP "classique. Ou bien les deux en mettant chaque chose dans un fichier distinct.
Dans mon premier billet sur l'optimisation de site Web j'évoquais la possibilité d'utiliser un script pour servir plusieurs fichiers Javascript (ou CSS) d'un coup pour gagner en vitesse. Voici un petit exemple de script PHP pour réaliser ce type de regroupement à la volée :
header('Cache-Control: max-age=3600, must-revalidate');
header('Content-type: text/javascript');
ob_start('ob_gzhandler');
if ($_REQUEST['f'])
{ $tab=explode(' ',trim($_REQUEST['f']));
foreach ($tab as $file)
if (preg_match('/^([0-9a-z_\-]+\/)*[0-9a-z_\-]+\.js$/i',$file)) readfile($file);
}
Le script est supposé être installé dans le répertoire où se trouvent les fichiers Javascript à servir. Ainsi, si vous avez 3 fichiers à regrouper ensemble vous pourriez utiliser une seule ligne HTML de la sorte :
<script src="/javascripts/script.php?f=file1.js+file2.js+file3.js" type="text/javascript"></script>
Quelques mots sur le code :
Il se trouve que Rakaz explore et développe la même idée, mais lui va plus loin en utilisant mod_rewrite pour présenter une URL plus lisible et qui cache le script de groupage.
Il y a des tags HTML que l'on utilise tout le temps, des fois trop, comme le div que certains se sentent obligés de placer autour du moindre autre tag. Et puis il y a ceux qu'on utilise plus rarement, par manque d'opportunité ou par ignorance. Mais si vous avez à coeur de réaliser des sites adapté aux utilisateurs, moteurs de recherche et malvoyants, alors il peut être utile de se remémorer les tags suivants :
<abbr title="Abréviation">Abr.</abbr>
Le tag abbr est utilisé pour marquer les abréviations. Utilisez l'attribut title pour donner le mot complet (la plupart des navigateurs en tiennent compte et offrent un rendu spécifique).<acronym title="Personnal Computer">PC</acronym>
Similaire au tag abbr, sauf que celui là est pour les acronymes (vous connaissez la différence, non ?).<label for="username">Votre pseudo</label>
Le tag label est utilisé pour définir une section de HTML comme étant le libellé d'un champ de formulaire (texte, boîte à cocher, etc.). C'est particulièrement utile pour les visiteurs malvoyants car leur navigateur peuvent ainsi associer à chaque champs le texte correspondant, même si l'intitulé ne figure pas directement à côté dans le code HTML. Les utilisateurs d'un navigateur graphique y gagnent aussi, ainsi avec Firefox par exemple le fait de cliquer sur l'intitulé active le champ du formulaire correspond.<address>Jean Martin, 12345 rue du commerce, Trifouilli les oies</address>
Voilà un tag qui se passe d'explications. Le code HTML à l'intérieur (retour à la ligne et autres) sont évidemment autorisés.<fieldset><legend>Vos coordonnées</legend>...</fieldset>
Le tag fieldset sert à regrouper des éléments d'un formulaire ensemble. Si vous avez par exemple un long formulaire avec une section pour le profil utilisateur, une autre pour ses préférences, etc. alors il est pratique et lisible de les regrouper en fieldset, et d'utiliser le tag legend à l'intérieur pour titrer chaque section (malheureusement le résultat visuel est plus plaisant dans Internet Explorer que Firefox, mais il est possible de styler ce tag avec CSS).<del>Un truc supprimé</del>
Les tags s et strike sont retirés du standard HTML car il ne portent pas d'information sémantique et le rendu de texte barré peut être obtenu avec CSS. Mais si vous voulez indiquer qu'une portion de page est censée être supprimée (et pas que du texte d'ailleurs), alors utilisez le tag del qui par défaut rend le texte barré.<... lang="en">My tailor is rich</...>
OK lang n'est pas un tag mais un attribut supporté par la plupart des tags HTML. Il permet d'indiquer que le contenu du tag est dans une langue spécifique, et comme il est aussi disponible pour le tag html, il permet de définir la langue par défaut du document (particulièrement utile pour les moteurs de recherce).<tbody>...</tbody>
Les tables existent en HTML depuis pas mal d'années, mais la plupart des gens ignorent qu'il faut aujourd'hui les utiliser avec les tags the thead, tbody et tfooter qui servent à définir quelles lignes constutient la tête, le corp et le pied du tableau (Firefox en tire par exemple parti pour imprimer des tables sur plusieurs pages).<noscript>Turn on your Javascript !</noscript>
Le tag noscript permet d'indiquer un contenu à afficher si, et seulement si, le navigateur ne gère pas les scripts Javascript (ou s'ils ont été désactivés par l'utilisateur). Plutôt que de laisser tomber vos visiteurs s'ils n'ont pas Javascript en place, vous pouvez utiliser ce tag pour leur donner un contenu alternatif à voir.<button type="submit" name="submit_button" value="1">Mon beau bouton, roi des forêts</button>
Tout le monde réalise ses boutons de formulaire avec le tag input. Mais ces boutons sont au format texte seulement, et nécessitent l'usage intensif de styles CSS pour les rendre un peu plus esthétiques. Et bien le tag button lui permet aussi de faire des boutons, mais avec n'importe quel ensemble de HTML en guise de contenu (y compris des images), ce qui permet plus de créativité.Ce billet sera le premier d'une série portant sur l'optimisation de sites Web, et plus spécifiquement de ceux développés avec AMP (Apache, MySQL, PHP). Optimiser un site Web est important pour deux raisons :
Commençons cette série par la partie client.
La première chose qui vient à l'esprit pour gagner en vitesse est tout simplement de réduire la taille des fichiers.
HTML : il n'y a pas beaucoup de gains à espérer ici, vous pouvez essayer de réduire votre quantité de retours à la ligne et de tabulations, mais cela nuira forcément à la lisibilité de votre code. Bien sûr il est très fortement recommandé d'écrire son code HTML "à la main" et sans le recours à un éditeur visuel, vu leur tendance à faire gonfler inutilement la taille du code.
CSS : il y a quelques gains à réaliser ici. Le premier est d'avoir un code bien organisé et structuré, de sorte que vous ayez le moins de classes et de propriétés définies et pas de redondance. N'oubliez pas qu'il est possible d'appliquer plusieurs classes à un même élément HTML. Si des éléments partagent partiellement des propriétés communes, il peut être utile de les grouper dans une même règle que vous leur appliquerez en plus de leur propriétés spécifiques. De plus, vous pouvez gagner quelques octets en utilisant les raccourcis CSS prévus à cet effet. Ainsi la règle { border-style: solid; border-width: 1px; border-color: #ffffff; } est identique à {border:solid 1px #fff}.
JPEG : vous pouvez faire de gros gains en utilisant les modules d'optimisation qu'on trouve dans les bons logiciels graphiques. D'après mes essais, les JPEG progressifs sont généralement un peu plus compacts. Jouez avec les réglages offerts pour voir quel rapport qualité/taille vous convient le mieux. Chaque image nécessite un réglage différent - par exemples celles avec des zones rouges ou des tons rouges font plus ressortir les défauts de compression et nécessitent donc une optimisation moins agressive. Si votre logiciel rajoute des données EXIF ou IPTC dans les JPEG qu'il produit, vous pouvez également les supprimer pour gagner encore en place (avec par exemple PlainViewer).
PNG : la aussi vous pouvez tirer partie des modules d'optimisation de votre suite graphique favorite. En particulier vous pourrez opter ou pas pour utiliser une palette, et le cas échéant la limiter à un certain nombre de couleurs. Ceci fait, vous pouvez réaliser encore de gros gains supplémentaires en utilisant un logiciel spécifique comme AdvanceComp qui retire les données inutiles et pousse la compression plus loin.
GIF : la seule raison valable pour utiliser des images GIF concerne les petites animation (ou bien de très petites images d'une poignée de pixels). Pour le reste utilisez PNG, qui offre une meilleure compression.
Javascript : de gros gains sont possibles en utilisant un compacteur de code comme par exemple Dojo ShrinkSafe ou Packer (conservez l'original de votre fichier pour les modifications, car la version compactée est illisible pour un être humain normalement constitué). De nombreuses librairies AJAX sont disponibles en version compacte directement ou auprès de tiers.
Plus que la taille des fichiers, le fait d'en avoir en trop grand nombre donne encore plus l'impression de "lenteur" au visiteur (à cause des aller-retour nécessaire entre le navigateur et le serveur pour effectuer chaque demande). Il faut donc tenter de limiter les fichiers connexes à une page en regroupant feuilles de style et scripts dans un nombre de fichier le plus limité possible.
Le problème est qu'en suivant cette stratégie, on oblige certaines pages à charger des données dont elles n'ont pas besoin. Ainsi si certaines pages utilisent les fichiers A et B, et d'autres B et C, et que A B et C sont assez lourds, il y a une perte importante à regrouper ces trois fichiers et à les servir systématiquement même lorsque seule une partie est nécessaire. La solution est alors d'écrire un petit script côté serveur (PHP ou autre) qui regroupera les différents fichiers CSS ou Javascript dont chaque page à besoin pour le servir d'un coup.
Ainsi au lieu d'avoir ces deux inclusions :
<link rel="stylesheet" href="A.css" type="text/css"/>
<link rel="stylesheet" href="B.css" type="text/css"/>
On aura :
<link rel="stylesheet" href="styles.php?group=AB" type="text/css"/>
Pour les images, je recommande chaudement la technique baptisée CSS sprites, qui regroupe plusieurs images en une seule et utilise des propriétés CSS pour les extraire et afficher. C'est particulièrement efficace pour les petits éléments d'interface (boutons, coins arrondis, icônes, etc.) en remplaçant des douzaines d'images par une seule.
L'ordre dans lequel sont listés vos librairies Javascript compte. En effet, le navigateur les charges séquentiellement dans leur ordre d'apparition, en bloquant pendant ce temps le traitement de la page elle même. Une solution est donc de placer ces inclusions en fin de page plutôt que dans l'en-tête (techniquement il n'y a pas de gain du temps de chargement, mais en pratique l'utilisateur verra quelque chose s'afficher plus vite).
Pour mesurer la performance côté client un bon outil est l'excellente extension FireBug pour Firefox (déjà recommandée précédemment), qui dispose d'un onglet "Net" indiquant dans quel ordre, et à quelle vitesse, sont chargé chacun des fichiers inclus dans une page.