Running my MVC4 app in debug mode (so no minification of css/scripts) works fine. As soon as I run without debug (css/scripts minified), my Twitter Bootstrap icons do not get displayed. Another thread on here suggested using bundles.IgnoreList.Clear(). But that does not seem to work for me. My BundleConfig.RegisterBundles(...) looks like this:
public static void RegisterBundles(BundleCollection bundles)
{
bundles.IgnoreList.Clear();
// Some JavaScript bundles only
// ...
bundles.Add(new StyleBundle("~/bundles/maincss").Include(
"~/Content/bootstrap.css",
"~/Content/bootstrap-responsive.css",
"~/Content/my.css"));
}
}
All packages were installed using Nuget (as I say, it works fine in debug mode). My Content folder also contains the minified versions of both the bootstrap...css files, but not a minified version of my.css. The glyph icons are in the images sub-folder.
My _Layout.cshtml looks like this:
<head>
...
@Styles.Render("~/bundles/maincss")
</head>
I should add, that by "non-debug" mode, I mean setting the debug="false" option in the Web.config file:
<compilation debug="false" targetFramework="4.5" />
Does anyone have any idea why the twitter bootstrap icons do not show in "non-debug" mode?
Thanks Rob
I'm on mobile so my apologies for brief response but I'll update later.
Long story short it had to do with relative path being fouled after bundling. But the good news is the latest bundle library resolves it.
To fill in the blanks, essentially what's happening is that the CSS files have relative paths to resources (in this case an icon sprite). When in debug mode, the files are output separately to the page so the references are retained (/Content/bootstrap.css
with a reference to images/glyphicons-halflings.png
(making the full path /Content/images/glyphicons-halflings.png
). However, when debug is removed the files are bundled and the path is now relative to whatever virtual path you gave your bundle. In the case of above, you now originate from /bundles/maincss
which makes for an erroneous /bundles/maincss/images/glyphicons-halflings.png
path.
The good news is that this was a resolved bug and as of Microsoft.AspNet.Web.Optimization
v1.1.0 you now have CssRewriteUrlTransform
that will replace all relative paths (within the CSS files) with their absolute-pathed counterpart. This means that no matter what you call the bundle, the resources will still be resolved.
So, to fix the issue, you can simple do the following:
IItemTransform cssFixer = new CssRewriteUrlTransform();
bundles.Add(
new StyleBundle("~/bundles/maincss")
.Include("~/Content/bootstrap.css", cssFixer)
.Include("~/Content/bootstrap-responsive.css", cssFixer)
.Include("~/Content/my.css", cssFixer)
);
My only qualm is how ugly this looks when you want multiple files, so to solve this you can simplify it with an extension method:
/// <summary>
/// Includes the specified <paramref name="virtualPaths"/> within the bundle and attached the
/// <see cref="System.Web.Optimization.CssRewriteUrlTransform"/> item transformer to each item
/// automatically.
/// </summary>
/// <param name="bundle">The bundle.</param>
/// <param name="virtualPaths">The virtual paths.</param>
/// <returns>Bundle.</returns>
/// <exception cref="System.ArgumentException">Only available to StyleBundle;bundle</exception>
/// <exception cref="System.ArgumentNullException">virtualPaths;Cannot be null or empty</exception>
public static Bundle IncludeWithCssRewriteTransform(this Bundle bundle, params String[] virtualPaths)
{
if (!(bundle is StyleBundle))
{
throw new ArgumentException("Only available to StyleBundle", "bundle");
}
if (virtualPaths == null || virtualPaths.Length == 0)
{
throw new ArgumentNullException("virtualPaths", "Cannot be null or empty");
}
IItemTransform itemTransform = new CssRewriteUrlTransform();
foreach (String virtualPath in virtualPaths)
{
if (!String.IsNullOrWhiteSpace(virtualPath))
{
bundle.Include(virtualPath, itemTransform);
}
}
return bundle;
}
Which makes the above code a little cleaner. (Arguably I picked a long method name, but I like to keep the method names clear with regards to purpose)
bundles.Add(
new StyleBundle("~/bundles/maincss").IncludeWithCssRewriteTransform(
"~/Content/bootstrap.css",
"~/Content/bootstrap-responsive.css",
"~/Content/my.css"
)
);