A l'origine, JSMin est un petit programme écrit en C par Douglas Crokford. Il prend un fichier Javascript et supprime tout ce qui n'est strictement nécessaire, c'est-à-dire :

  • les commentaires (/* */ et //),
  • les lignes vides et retour à la ligne,
  • les espaces (sauf dans les chaines de caractères et les expressions régulières).

Contrairement à d'autres packer, JSMin ne brouille pas le code, c'est-à-dire que le fichier compressé reste lisible, débuggable et modifiable (même si une petite ré-indentation est nécessaire), ce qui est quand même un avantage très appréciable.

Il existe une version PHP de JSMin, mais, comme son auteur l'indique, il s'agit d'une « conversion simple et brutale du C vers le PHP », entendez par là qu'elle n'est pas du tout optimisée et donc super lente. Evidemment, la version C est théoriquement utilisable en PHP via la fonction shell_exec, mais c'est totalement impensable sur un hébergement mutualisé.

Récemment, j'ai dû mettre en place un système de compression et de concaténation des javascripts « à la volée » ; c'est-à-dire que les javascripts sont compressés la première fois qu'un utilisateur les demande, puis mis en cache (vaguement inspiré de ce post). Dès qu'un fichier est mis à jour, le cache est regénéré. Ainsi, je conserve les versions commentées et indentées pour développer, et je n'ai pas à me soucier de les compresser avant de les mettre en ligne. C'est magique.

Mais, la version originale de JSMin en PHP met parfois plus de 3 secondes à compresser certains fichiers, ce qui est bien trop long. Donc je n'ai pas pû m'empêcher de faire un tour dans le code pour l'optimiser. J'ai remplacé toutes les boucles de lecture caractère par caractère (typique du C) par des fonctions natives PHP comme strpos et strlen.

J'ai également viré toute la partie qui concernait les fichiers (dans la version originale, il est possible de passer un nom de fichier à JSMin pour qu'il le lise directement), parceque en PHP c'est beaucoup plus rapide de lire d'abord le fichier (par une fonction comme file_get_contents) et de travailler sur la chaine de caractère représentant le contenu.

Le gain en vitesse dépend fortement de la taille et du contenu du fichier ; dans mon cas c'est entre 10% et 50% plus rapide.

Utilisation

Le constructeur prend 2 paramètres : le code à compresser (string) et, si besoin, un tableau de commentaires à ajouter en début de fichier (array ou rien). Ensuite il suffit d'appeller la fonction minify().

Exemple :

$code = file_get_contents('foo.js');
$compressor = new MyJsMin($code, array('Hello', 'World'));
echo $compressor->minify();

Le fichier foo.js contient :

function foo(bar)
{
bar += 1;
alert('hello world !');
}

Le résultat sera :

// hello
// world

function foo(bar)
{bar+=1;alert('hello world !');}

Sources

Test en ligne

Vous pouvez tester les performances du script grace à cette page (en anglais, parceque c'est la classe internationnale).