Compression et obfuscation des fichiers JavaScript avec Atlas
Lorsque j'avais examiné les fichiers JavaScript de Microsoft Ajax Extensions beta 1 une question m'était venue à l'esprit.
La plupart des méthodes sont écrites de la sorte :
Sys.Serialization.JavaScriptSerializer.serialize =
function Sys$Serialization$JavaScriptSerializer$serialize(object) {
// doSomething
}
Je pense que la plupart des développeurs non JavaScript ne voient pas le soucis, en fait cette ligne déclare une méthode dans deux variables (Sys.Serialization.JavaScriptSerializer.serialize et Sys$Serialization$JavaScriptSerializer$serialize) !!! La question que je me suis posé est pourquoi dans deux variables plutôt qu'une ? Cela a une conséquence non négligeable puisque cela grossis le fichier JavaScript inutilement ! Le nom de la variable est répété deux fois alors qu'une seule aurait largement suffit !
J'ai donc cherché et la première idée qui m'est venu est pour des raisons de perf, en effet à cause du late binding de JavaScript la méthode Sys$Serialization$JavaScriptSerializer$serialize serait plus rapide que la méthode rangé dans des namespaces ? Malheureusement les méthodes avec des $ ne sont jamais utilisées ! Ces méthodes sont donc complètement inutiles !
Je vois alors deux autres solutions :
- C'est une nécessité pour Orcas et son IntelliSens;
- C'est utile pour un outil de prétraitement des fichiers JavaScript.
J'en ai parlé avec Aurélien qui lui non plus ne savait pas quelle était l'utilité de ces méthodes.
Je pense avoir découvert aujourd'hui le pourquoi ! Prenons par exemple la méthode Date._parse (exemple pris au hasard ;-))
Date._parse = function Date$_parse(value, cultureInfo, args) {
var custom = false;
for (var i = 1, il = args.length; i < il; i++) {
var format = args
;
if (format) {
custom = true;
var date = Date._parseExact(value, format, cultureInfo);
if (date) return date;
}
}
if (! custom) {
var formats = cultureInfo._getDateTimeFormats();
for (var i = 0, il = formats.length; i < il; i++) {
var date = Date._parseExact(value, formats
, cultureInfo);
if (date) return date;
}
}
throw Error.format(Sys.Res.formatBadDate);
}
Comparons cette méthode avec la méthode présente dans la version release du script c'est à dire la version compressé qui est envoyé au client :
Date._parse=function(g,c,h){var e=false;for(var a=1,i=h.length;a<i;a++){var f=h
;if(f){e=true;var b=Date._parseExact(g,f,c);if(b)return b}}if(!e){var d=c._getDateTimeFormats();for(var a=0,i=d.length;a<i;a++){var b=Date._parseExact(g,d
,c);if(b)return b}}throw Error.format(Sys.Res.formatBadDate)};
Si on déplie tout ça cela nous donne :
Date._parse=function(g,c,h){
var e=false;
for(var a=1,i=h.length;a<i;a++){
var f=h
;
if(f){
e=true;
var b=Date._parseExact(g,f,c);
if(b)return b
}
}
if(!e){
var d=c._getDateTimeFormats();
for(var a=0,i=d.length;a<i;a++){
var b=Date._parseExact(g,d
,c);
if(b)return b
}
}
throw Error.format(Sys.Res.formatBadDate)
};
En plus d'avoir supprimé les espaces inutiles, l'équipe Atlas à surtout réussit à renommer toutes les variables avec des noms incompréhensible !!! L'avantage immédiat est que le fichier JavaScript est beaucoup plus léger et surtout le script JavaScript devient incompréhensible c'est donc une première approche pour protéger son code JavaScript !
Autre exemple : lorsque l'on construit un type, le code ressemblait à :
Sys._ScriptLoader = function Sys$_ScriptLoader() {
// constructor
}
function Sys$_ScriptLoader$dispose() {
// some Code
}
Sys._ScriptLoader.prototype = {
dispose: Sys$_ScriptLoader$dispose,
// ...
}
Là encore il y a l'utilisation inutile d'une variable, en release ce code se transforme en :
Sys._ScriptLoader = function() {
// constructor
}
Sys._ScriptLoader.prototype = {
dispose:function Sys$_ScriptLoader$dispose() {
// some Code
},
// ...
}
C'est donc un excellent travail de la part de Microsoft que je viens de découvrir !
J'espère vraiment que l'outil qu'ils ont utilisé pour compresser le code JavaScript sera disponible pour tous ! Le besoin d'un outil qui compresse et rend illisible le code JavaScript va devenir de plus en plus fort suite à l'engouement pour les applications Ajax (Web 2.0 oblige ...).
Cet outil sera t'il intégré à Orcas ? Sera t'il disponible avant ? En tout cas j'espère qu'il le sera très bientôt, puisque je vais en avoir besoin d'ici quelques mois ...