Minification de fichiers JavaScript
Le problème
Considérant un dossier de fichiers JS dont un sous-ensemble est quotidiennement modifié, le problème de leur minification se pose : je veux que ces fichiers minimisés puissent être générés automatiquement en utilisant yui-compressor (pour l'instant). En Bash, ça donne :
find . -maxdepth 1 -name "*js" | while read f; do
[[ `stat -c %Y minified/${f%.js}-min.js` -gt `stat -c %Y $f` ]] && continue;
echo $f
yui-compressor --type js --charset utf-8 -v -o minified/${f%.js}-min.js $f;
done 2> minified.logLe meilleur compresseur
Même si le script précédent fonctionne, YUI-Compressor n'est pas terrible (ou je ne sais pas l'utiliser). Je vais donc m'orienter vers le Google Closure Compiler qui est plus lent à l'exécution (10x) mais BEAUCOUP plus intéressant. A noter que l'on peut utiliser deux modes pour ce minificateur : le mode par défaut (sans option particulière) et le mode ADVANCED_OPTIMIZATIONS, qui donne des résultats très intéressants. Par contre, le code à minimiser/obfusquer doit être adapté. Ainsi, pour utiliser le mode ADVANCED_OPTIMIZATIONS et obtenir ainsi des scripts extrêmement petits et obfusqués, il faut :
- ajouter, selon le format jsDoc, le fait qu'une fonction est un constructeur : ainsi, elle pourra utiliser "this" sans warning de la part de Google Closure. D'autres types d'annotations sont disponibles.
- ajouter window["MonConstructeur"] = MonConstructeur;
- si le code utilise un hash externe il faut utiliser la notation des tableaux a.["nom-du-membre"] plutôt que la notation objet : a.nomDuMembre
- on n'écrit PLUS JAMAIS :
MonObjet.prototype = { ... }; MonObjet.prototype.constructor = MonObjet;mais on va déclarer une par une toutes les propriétés d'un objet, aussi bien les méthodes que les variables comme indiqué par les 4 points suivants - pour les fonctions publiques :
MonObjet.prototype["NomDeLaFonctionPublique"] = function(...) { ... Corps de la fonction publique ... }; - pour les fonctions privées :
MonObjet.prototype.NomDeLaFonctionPrivée = function(...) { ... Corps de la fonction privée ... }; - pour les variables publiques :
MonObjet.prototype["NomDeLaVariablePublique"] = ...;
- pour les variables privées :
MonObjet.prototype.NomDeLaVariablePrivée = ...;
java -jar ~/closure/compiler.jar --charset UTF-8 --compilation_level ADVANCED_OPTIMIZATIONS --js "$f" --js_output_file ${f%.js}-min.jsRésultats
...

