I'm beginning to use .NET 4.5's built in minification and bundling to minify & bundle my CSS and JavaScript. JavaScript minification works great, however, I have run into trouble with CSS minification. I create a style bundle using the below code -
var myCss = new string[]
{
"~/Content/jquery.css",
"~/Content/app.css",
};
bundles.Add(new StyleBundle("~/bundles/MySiteCss/").Include(myCss ));
and then I reference them in .cshtml (razor file) as below -
#Styles.Render("~/bundles/MySiteCss/")
It minifies the CSS file. However, if the CSS files contain styles that have background-image references, such as background-image: url('img/icon.png'), it attempts the load this icon file from a new location (derived from the bundle name) = /bundles/MySiteCss/img/icon.png
Since the icon does not exist in the location, it doesn't get loaded and displayed on the page.
You need to have your bundles and CSS served from the same place for this to work easily. For example, change your bundle line to be:
bundles.Add(new StyleBundle("~/Content/MySiteCss/").Include(myCss));
And update your reference as well:
#Styles.Render("~/Content/MySiteCss/")
This has been fixed in version 1.1.0-alpha1 of the Microsoft ASP.NET Web Optimization Framework.
You can get the update via NuGet (https://nuget.org/packages/Microsoft.AspNet.Web.Optimization) if you include Prerelease.
Related
I've added bootstrap CSS files via a StyleBundle to my asp.net mvc 5 project.
(It uses as Cdn: https://www.asp.net/ajax/cdn#Bootstrap_Releases_on_the_CDN_14 )
var bootstrapCssCdnPath = "http://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css";
var bootstrapCssBundle = new StyleBundle("~/bundles/css/bootstrap", bootstrapCssCdnPath).Include("~/Content/bootstrap.css");
//bootstrapCssBundle.CdnFallbackExpression // ?
bundles.Add(bootstrapCssBundle);
var bootstrapThemeCssCdnPath = "http://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap-theme.min.css";
var bootstrapThemeCssBundle = new StyleBundle("~/bundles/css/bootstraptheme", bootstrapThemeCssCdnPath).Include("~/Content/bootstrap-theme.css");
//bootstrapCssBundle.CdnFallbackExpression // ?
bundles.Add(bootstrapThemeCssBundle);
However there is a problem: when I add an incorrect url as CDN (e.g. adding 'ahttp' instead of 'http') my custom "fallback" css file is not used, instead it shows 'ahttp://' in my html source.
Same when I'm running my site on Debug or Release.
Why is my fallback not being used?
What is the CdnFallbackExpression for a StyleBundle? (and in particular for a bootstrap.css and bootstrap-theme.css)
Should the .Include be the .min.css file or does it automatically search for the .min. version first?
Is there a way to .Include multiple css files, using a Cdn with fallback, so that I don't have to create a new StyleBundle everytime per css file that uses a Cdn?
1) This is a bug in the Microsoft ASP.NET Optimization Framework, documented here.
2) The solution is to modify the CdnFallbackExpression to be a javascript function that both checks for the stylesheet and loads the fallback, thus ignoring the bad script from the Optimization Framework.
Here is solution which provides a StyleBundle extension method to solve the problem: Style Bundle Fallback.
3) There should be unminified version like bootstrap.css (not bootstrap.min.css). When you build your web application for release it uses .min version. More here: Bundler not including .min files.
4) No, you can't use multiple CSS files with CDN (each of them must have its own bundle). Here is an article that explains when to use a CDN (or not) and why: Know When To CDN.
i have the following bunlde inside my asp.net mvc5 web application:-
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/bootstrap.css",
"~/Content/style.css",
"~/Content/touchTouch.css",
"~/fonts/font-awesome.css"));
now will this always render the style.css after the bootstrap.css ? or this is not guaranteed ? if the order is not guaranteed in the above code then how i can control the order of the css and script files inside the bundle ?
No. I't won't always render style.css after the bootstrap.css.
If you want ordering, you have to make this (for scripts) and this (for CSS files) change to specifically give them an order.
I understand the links are old (from 2012), but I have used that with success in ASP .NET MVC 5.
ASP.NET MVC has a default order for certain files. For ex, it tries to load jQuery first. You can clear up that list this way:
bundles.FileSetOrderList.Clear();
That worked for me. If it doesn't work for you, you can explicitly indicate the order in which files should be processed in your bundles:
bundles.FileSetOrderList.Clear();
BundleFileSetOrdering ordering = new BundleFileSetOrdering("custom order");
ordering.Files.Add("jquery.js");
bundles.FileSetOrderList.Add(ordering);
Minification in asp.net seems to break the bootstrap UTF symbols. I have this in the original file:
.glyphicon-edit:before {
content: "\e065";
}
and this in the minified version:
.glyphicon-edit:before{content:""}
In theory I can add the pre-minified version instead, but that does not work for some reason either. I have asked this question earlier (Asp.Net bundling not using the .min files) but with no luck.
Any ideas how to fix the minification?
Try updating to the 1.1.3 of Optimization and in your bundleconfig, identify the css and include them using
bundles.Add(new StyleBundle("~/Content/css")
.Include("style.css", new CssRewriteUrlTransform());
and include the rest of the css files that you need which don't have a url reference or UTF char.
In an Asp.Net MVC 5 application, I am creating a style bundle in my egisterBundles method. I'm using jquery-ui. Instead of listing all of the jquery-ui css files individually I'm using all.css, which imports all the rest. The code looks like this:
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/a.css",
"~/Content/b.css",
"~/Content/themes/base/all.css"));
And all.css contains two lines:
#import "base.css";
#import "theme.css";
This works, but only when I set
BundleTable.EnableOptimizations = false.
When I set
BundleTable.EnableOptimizations = true
then none of the jquery css loads.
Of course there is an easy workaround; I can individually add the jquery-ui css files to the bundle. But I am curious: why does all.css break when the css files are bundled and minified? This does not appear to be browser-specific, as I have the same problem in both IE9 and Chrome 39.
According to this answer the default minifier simply does not support the #import directive:
MVC4 bundling CSS failed Unexpected token, found '#import'
Also, the jquery-ui css files contain relative paths to images, so the virtual path of the bundle must allow the browser to find the relative path to the images, for example:
bundles.Add(new StyleBundle("~/Content/themes/base/jqueryui")
.Include("~/Content/themes/base/core.css" [and other desired css files]));
And on the cshtml page:
#Styles.Render("~/Content/themes/base/jqueryui")
See this link for explication: MVC4 StyleBundle not resolving images
I have this:
bundles.Add(new StyleBundle("~/Content/Styles/Default").Include("~/Content/Styles/Default/Site.css"));
On my sites i have this:
#section Styles
{
#Styles.Render("~/Content/Styles/Default"))
}
My _Layout.cshtml looks like this:
#RenderSection("Styles", true)
Everything looks good, eh? Well, not really. When i compiled my application in release mode, decided to publish it, this is what it renders:
<link href="/Content/Styles/Default?v=78dkNySP_xsiuzsgxCx_GGnnHzYS-B8nNdnXqcl47XI1" rel="stylesheet">
Instead of generating href to a file, it generates some kind of id? Guid? Why? O.o
This is how bundles work. It's main purpose is for you to combine multiple CSS (and JS files for that matter) files into one package. e.g. you no longer have to put all your css (and js) into one huge file. Just split it up into sections, then add it into your bundles, and it packages it up into one item. Less web requests, the faster your page load time.
e.g. Lets say you had 2 css files. One's the main, but you had one for your menu system.
bundles.Add(new StyleBundle("~/Content/Styles/Default").Include(
"~/Content/Styles/Default/Site.css",
"~/Content/Styles/Default/Menu.css"));
This would show up as a single call with the GUID type code (to prevent caching on file changes) on the URL. This URL will link to a minified and bundled css.
But my browser cannot read that! There is no physical path to a file!
It's a sort of virtual file. MVC's bundling uses the routing engine to point it to a combined and minified version of a particle bundle.