Accueil > Asp.Net, Asp.Net MVC > Appliquer des transformations à des fichiers via les Bundles

Appliquer des transformations à des fichiers via les Bundles

Sur toutes les applications, certaines variables sont nécessaires côté client et souvent, elles dépendent de l’environnement d’exécution, de paramétrages serveur, etc… Prenons par exemple un code que tout le monde connaît, le code d’intégration de google analytics: il contient un identifiant utilisateur et un domaine. Personne ne veut que ces variables soient initialisées de la même manière si on est en environnement de développement ou en environnement de production pour ne pas fausser les stats. Le mécanismes de bundling et surtout de transformation peut nous y aider.

Pour l’exemple, nous partons d’un projet mvc 4 vide. La première chose à faire est d’installer le package Microsoft.AspNet.Web.Optimization qui contient les utilisatires de bundling. Vous pouvez l’installer via Nuget avec la commande « Install-Package Microsoft.AspNet.Web.Optimization -Pre » dans le Package Manager.

Nous allons tenter d’afficher les variables contenant les id et domain google analytics dans une alert au lancement de la home. Ces valeurs seront mises ici dans les AppSettings du fichier web.config racine qui est spécifique à une configuration donnée, ainsi selon les environnements les valeurs pourront être personnalisées. Pour commencer, mettons le code google dans un fichier js séparé:

var googleAnalyticsId = '$GOOGLE_ANALYTICS_ID$';
var googleAnalyticsDomain = '$GOOGLE_ANALYTICS_DOMAIN$';
 
var _gaq = _gaq || [];
_gaq.push(['_setAccount', googleAnalyticsId]);
_gaq.push(['_setDomainName', googleAnalyticsDomain]);
_gaq.push(['_trackPageview']);
 
(function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();

Dans ce fichier, nous avons initialisé les variables avec des patterns reconnaissables: $GOOGLE_ANALYTICS_ID$ et $GOOGLE_ANALYTICS_DOMAIN$. Il va falloir au moment du rendu de ces fichiers par le serveur remplacer ces patterns par les vraies valeurs contenues dans les AppSettings. Nous allons ensuite créer une classe BundleConfig qui contient une méthode RegisterBundles sur le modèle de la classe FilterConfig génére par le template MVC4 et appeler cette méthode dans l’Application_Start. Cette méthode sert à déclarer le bundle qui contiendra notre fichier js:

public static void RegisterBundles(BundleCollection bundles)
{
    var gaBundle = new ScriptBundle("~/Scripts/bundles/ga").Include(
        "~/Scripts/googleanalytics.js");
    bundles.Add(gaBundle);
}

Jusque là rien de spécial, nous créons simplement un bundle contenant notre fichier. Il nous reste à remplacer les patterns au moment où le bundle est renvoyé par le serveur. Pour cela, nous allons utiliser l’interface IBundleTransform qui permet de définir des transformations à appliquer aux fichiers du bundle. Cette interface est utilisée en interne dans le package pour gérer la minification. Nous allons donc créer une classe qui implémente cette interface:

public class PatternReplacementBundleTransform:IBundleTransform
{
    private readonly Dictionary<string,string> _patterns; 
 
    public PatternReplacementBundleTransform(Dictionary<string, string> patterns)
    {
        _patterns = patterns;
    }
 
    public void Process(BundleContext context, BundleResponse response)
    {
        if (response == null) throw new ArgumentNullException("response");
 
        foreach (var pattern in _patterns)
        {
            response.Content = response.Content.Replace(pattern.Key, pattern.Value);
        }
    }
}

Elle contient un dictionnaire qui a comme clé le pattern recherché et comme valeur la vraie valeur à mettre dans le fichier. Nous allons maintenant appliquer cette transformation à notre bundle en ajoutant dans la méthode RegisterBundles les lignes suivantes:

gaBundle.Transforms.Add(
    new PatternReplacementBundleTransform(
        new Dictionary<string, string>
            {
                {"$GOOGLE_ANALYTICS_ID$",ConfigurationManager.AppSettings["GoogleAnalyticsId"]},
                {"$GOOGLE_ANALYTICS_DOMAIN$",ConfigurationManager.AppSettings["GoogleAnalyticsDomain"]},
            }
        )
);

On ajoute à la collection de transformations du bundle notre transformation personnalisée en lui passant le dictionnaire qui contient nos valeurs. Si on teste notre application en la lançant via IISExpress, voilà ce qu’on obtient:

patternsNotReplaced

On voit que les patterns ne sont pas remplacés… Mais où à-t-on fait une erreur? La réponse est…nulle part. Les transformations à appliquer aux bundles sont simplement désactivées par défaut quand on est en mode debug. Pour les forcer à s’exécuter, il faut ajouter la ligne:

BundleTable.EnableOptimizations = true;

Malheureusement, cette configuration s’applique à tous les bundles il n’est pas possible de l’appliquer à un bundle en particulier au jour d’aujourd’hui. Si on relance l’application, on voit:

replacementOK

Le remplacement est bien fait cette fois.

On peut imaginer un grand nombre de scénarii grâce au bundling et aux transformations, par exemple de l’obfuscation à la volée, de la personnalisation des feuilles de style selon l’utilisateur, etc… Le code est dispo ICI

  1. 23/04/2013 à 7:50

    Eh ben ça c’est top, je vais m’atteler à l’utiliser ce truc là😉. Merci merci merci😉.

  1. No trackbacks yet.

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

%d blogueurs aiment cette page :