[ASP.NET MVC 4+] Erreur 403 ou 404 après bundling/minification

Avec la version 4.5 d’ASP.NET, Microsoft a intégré une fonctionnalité relativement intéressante : le bundling.

Bundling

Le bundling permet de combiner ou d’empaqueter plusieurs fichiers CSS ou JavaScript en un seul fichier. Il s’agit alors d’un simple bundle qui contiendra tous les fichiers de la liste, permettant ainsi d’accélérer le chargement des pages : moins de fichiers signifie moins de requêtes HTTP.

Exemple de bundles :

bundles.Add(new ScriptBundle("~/bundles/site").Include(
"~/Scripts/noty/packaged/jquery.noty.packaged.min.js",
"~/Scripts/softit.utils.js",
"~/Scripts/main.js"));
 
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/bootstrap.css",
"~/Content/site.css"));
De plus, il est assez intelligent pour que, lorsque votre site est compilé en release, seuls les fichiers JS/CSS minifiés (.min) soient utilisés. Par exemple, si j’ai un fichier bootstrap.js et un fichier bootstrap.min.js. Et j’ai un bundle sur bootstrap.js. Lorsque je compile en Debug il utilise boostrap.js; lorsque je compile en Release, il utilise bootstrap.min.js

Compression de fichiers JavaScript et CSS

L’écriture et l’architecture des fichiers dans un projet est faite dans deux buts : être compris par le navigateur et par l’être humain.
Là où le navigateur a besoin que les fichiers soient référencés et contiennent ce qui est nécessaire pour être interprété, l’être humain lui a besoin de s’y repérer et d’avoir un contenu lisible et compréhensible.
Ainsi nous nous retrouvons avec plusieurs fichiers séparés, avec des logiques différentes, de plus ceux-ci sont indentés (Ctrl+K + Ctrl+D sont souvent les bienvenus) de façon à ce que l’on puisse s’y retrouver et nos collègues également.
Sauf que le navigateur n’a pas besoin de tout cela, toute l’aération que l’on donne à notre fichier lui fait perdre du temps, ce sont des caractères inutiles (saut de ligne, espaces…). Ainsi, la minification opère une variété d’optimisations de code pour les scripts / css, telles que le fait de retirer les espaces inutiles, les commentaires et réduire les noms de variables à un caractère.
Par exemple la fonction JS suivante :
AddAltToImg = function (imageTagAndImageID, imageContext) {
    ///<signature>
    ///<summary> Adds an alt tab to the image
    // </summary>
    //<param name="imgElement" type="String">The image selector.</param>
    //<param name="ContextForImage" type="String">The image context.</param>
    ///</signature>
    var imageElement = $(imageTagAndImageID, imageContext);
    imageElement.attr('alt', imageElement.attr('id').replace(/ID/''));
}

Donnera la fonction suivante après minification

AddAltToImg = function (n, t) { var i = $(n, t); i.attr("alt", i.attr("id").replace(/ID/"")) }

 

Il est très facile de gagner en performance en minifiant les fichiers, vous pourrez remarquer par exemple, que lorsque vous téléchargez une librairie comme jQuery, les fichiers ont leurs équivalents « .min » qui sont la version minifiée des originaux indentés.

Erreur d’interprétation du bundle

Récemment, nous avons eu un cas d’erreur 403 et 404 :

 GET http://xxxx/Content/bootstrap/?v=MDbdFKJHBa_ctS5x4He1bMV0_RjRq8jpcIAvPpKiN6U1

 
Sur les fichiers JS et CSS lorsque nous passions en environnement de préproduction. La seule différence était que le site passait en Release.
Pour créer un bundle, il faut lui donner un nom qui est, par nomenclature, souvent de la forme « ~/Content/bootstrap » pour les fichiers .css (en l’occurrence, pour celui de Bootstrap).
En fait, le problème est que, si, ici, votre site contient un dossier « bootstrap » dans le dossier « Content« , ce dernier n’arrivera pas à faire la différence entre le bundle et le vrai dossier. Il choisira donc le second.
Par conséquent, il ne faut jamais utiliser des noms de bundles qui correspondent à des dossiers existants.
Si vous avez une arborescence de la forme « Content/bootstrap/bootstrap.css » votre bundle ne doit pas être :
new StyleBundle("~/Content/bootstrap").Include(
"~/Content/bootstrap/bootstrap.css");
Mais devra plutôt ressembler à :

new StyleBundle("~/Content/btp").Include(
"~/Content/bootstrap/bootstrap.css");
 

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