Réduire le nombre de requêtes grâce aux data URIs
Posté le Tuesday 26 June 2012 | Catégories : PHP, CSS, Linux, Optimisation
Sur une page web classique, chaque élément (image, icône, fichier de police de caractère ...) nécessite une nouvelle requête vers le serveur pour télécharger l'élément en question. Ceci ralentit naturellement l'affichage de la page.
Il existe actuellement 3 techniques pour réduire le nombre de requêtes:
- Les sprites : consistent à grouper plusieurs petites images ou icônes en une seule;
- SPDY : ce protocole développé par Google permet de télécharger plusieurs éléments en parallèle, et en une seule connexion, mais il n'est actuellement supporté que par Chrome;
- Les data URIs.
Les data URIs sont comme leur nom l'indique des URIs, mais au lieu d'indiquer où télécharger les données, elles intègrent les données directement. Par exemple, pour une image, au lieu d'utiliser une URL classique:
<img src="mon_image.png">
On pourrait utiliser la data URI suivante:
<img src="data:image/png;base64,R0lGODlhEAAOALM...">
Cette technique possède cependant des inconvénients:
- Elle n'est pas supportée par Internet Explorer 7 et plus anciens (soit environ 8% des navigateurs actuellement utilisés);
- L'encodage Base64 est environ 40% plus gros que le fichier d'origine.
Heureusement, si la compression gzip est utilisée, l'encodage Base64 est alors environ 9% plus gros que le fichier d'origine.
Data URIs et CSS
La technique des data URIs peut également être utilisée dans les fichiers CSS. Vu leurs inconvénients, un bon compromis consiste justement à utiliser les data URIs pour encoder tous les petits fichiers, comme les icônes par exemple, utilisés dans une CSS.
datauri.php
Le script datauri.php ci-dessous permet de faire la conversion automatiquement:
#! /usr/bin/php
<?php
// datauri.php
$minsize = 10240; // 10KB
$options = getopt("i:o:r:");
$file = $options["i"];
$out = $options["o"];
$root = $options["r"];
$subject = file_get_contents($file);
$dir = dirname($file);
$pattern = "/url\((.*)\)/i";
$matches = array();
preg_match_all ($pattern, $subject, $matches);
$finfo = finfo_open(FILEINFO_MIME_TYPE);
foreach ($matches[1] as $image) {
$image = trim(trim(trim($image, "'"), '"'));
if (strpos($image, "/") === 0 ) {
// Absolute path
$filename = $root . "/" . $image;
} else {
// Relative path
$filename = $dir . "/" . $image;
}
if (!is_file($filename)) {
echo "$image not found!\n";
continue;
}
if (filesize($filename) > $minsize) {
echo "$image is too big!\n";
continue;
}
$encoding = finfo_file($finfo, $filename);
$encoded = base64_encode(file_get_contents($filename));
$subject = str_replace("url('$image')", "url('data:$encoding;base64,$encoded')",$
}
file_put_contents($out, $subject);
?>
Il convertit en data URI tous les éléments plus petits que 10KB. L'utilisation nécessite 3 paramètres:
datauri.php -i style.css -o style.out.css -r /var/www/mon_site
Le paramètre -r (root) est nécessaire pour que le script puisse trouver le fichier si le fichier CSS utilise des URLs absolues.