Category Archives: css

advantages and disadvantages of using a content delivery network (CDN)

What are the advantages and disadvantages of using a content delivery network (CDN)?

  • The disadvantages may be that it costs money, and it adds a bit of complexity to your deployment procedures.
  • The main advantage is an increase in the speed with which the content is delivered to the users.

When to use a CDN?

  • It will be most effective when you have a popular public website with some type of static content (images, scripts, CSS, etc.).

Is a CDN a performance booster?

  • In general, yes. When a specific request is made by a user, the server closest to that user (in terms of the minimum number of nodes between the server and the user) is dynamically determined. This optimizes the speed with which the content is delivered to that user.

Advantages

  • It increases the parallelism available.
    (Most browsers will only download 3 or 4 files at a time from any given site.)
  • It increases the chance that there will be a cache-hit.
    (As more sites follow this practice, more users already have the file ready.)
  • It ensures that the payload will be as small as possible.
    (Google can pre-compress the file in a wide array of formats (like GZIP or DEFLATE). This makes the time-to-download very small, because it is super compressed and it isn’t compressed on the fly.)
  • It reduces the amount of bandwidth used by your server.
    (Google is basically offering free bandwidth.)
  • It ensures that the user will get a geographically close response.
    (Google has servers all over the world, further decreasing the latency.)
  • (Optional) They will automatically keep your scripts up to date.
    (If you like to “fly by the seat of your pants,” you can always use the latest version of any script that they offer. These could fix security holes, but generally just break your stuff.)

 

Web Optimization conditional for browsers

If you have a look into the default format System.Web.Optimization.Scripts.DefaultTagFormat, you will find that you have something like:

<script src='{0}'></script>

So, the only thing you have to do is define a new format. You can do this using the “RenderFormat” method, like:

<%: System.Web.Optimization.Scripts.RenderFormat("<!--[if lt IE 9]><script src='{0}'></script><![endif]-->", "~/bundles/IE9js") %>

 @Scripts.RenderFormat("<!--[if IE 6]><link rel='stylesheet' type='text/css' href='{0}'></link><![endif]-->", "~/bundles/ie6js")
 @Scripts.RenderFormat("<!--[if IE 7]><link rel='stylesheet' type='text/css' href='{0}'></link><![endif]-->", "~/bundles/ie7js")
 @Scripts.RenderFormat("<!--[if IE 8]><link rel='stylesheet' type='text/css' href='{0}'></link><![endif]-->", "~/bundles/ie8js")

CDN in ASP.NET MVC bundling

Once you create ASP.NET MVC project and you looked into the App_start folder BundleConfig.cs file you will fine following code for jQuery bundle.

bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
        "~/Scripts/jquery-{version}.js"));

Here you can see that there is a ScriptBundle object created with new. This ScriptBundle object also contains another constructor which also take path of cdn as parameter.

Now let’s first run application without adding CDN and see how its works.

bundle-without-cdn-asp-net-mvc

You can see its loaded from bundle not using any CDN there. So Let’s see how we are going to use CDN there. There are lots of CDNs are available there but I’m going to use Microsoft Hosted CDN file in our sample application.

You can find all CDN hosted file on following location.

http://www.asp.net/ajaxlibrary/cdn.ashx

and here all the jQuery CDN listing for all the versions.

http://www.asp.net/ajaxlibrary/cdn.ashx#jQuery_Releases_on_the_CDN_0

I’m going to use jQuery 1.10.2 version as ASP.NET MVC application by default comes with that version only. Following is a code for that.

bundles.UseCdn = true;
   bundles.Add(new ScriptBundle("~/bundles/jquery",
   @"//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.10.2.js"
   ).Include(
    "~/Scripts/jquery-{version}.js"));

Here you can see that I have used path without http so that whether you use https or http it will work on both side. Also you can see that I have enabled UseCdn proper to true that will tell bundle to use CDN whenever its available.

As CDN is used in release version, to test application we need to set Debug=”False” in our web.config check that in local machine. So once you are done with that and run in browser you can see in below image its using CDN instead of local file.

cdn-for-bundling-asp-net-mvc-browser-demo

bundle files in specific order

 

internal class AsIsBundleOrderer : IBundleOrderer
{
    public virtual IEnumerable<BundleFile> OrderFiles(BundleContext context, IEnumerable<BundleFile> files)
    {
        return files;
    }
}

internal static class BundleExtensions
{
    public static Bundle ForceOrdered(this Bundle sb)
    {
        sb.Orderer = new AsIsBundleOrderer();
        return sb;
    }
}

Usage:

    bundles.Add(new ScriptBundle("~/content/js/site")
        .Include("~/content/scripts/jquery-{version}.js")
        .Include("~/content/scripts/bootstrap-{version}.js")
        .Include("~/content/scripts/jquery.validate-{version}")
        .ForceOrdered());

I like using fluent syntax but it also works with a single method call and all the scripts passed as parameters.

Bundling and Minification

The CSS and Script bundling should work regardless if .NET is running 4.0 or 4.5. I am running .NET 4.0 and it works fine for me. However in order to get the minification and bundling behavior to work your web.config must be set to not be running in debug mode.

<compilation debug="false" targetFramework="4.0">

Take this bundle for jQuery UI example in the _Layout.cshtml file.

@Styles.Render("~/Content/themes/base/css")

If I run with debug="true" I get the following HTML.

<link href="/Content/themes/base/jquery.ui.core.css" rel="stylesheet"/>
<link href="/Content/themes/base/jquery.ui.resizable.css" rel="stylesheet"/>
<link href="/Content/themes/base/jquery.ui.selectable.css" rel="stylesheet"/>
<link href="/Content/themes/base/jquery.ui.accordion.css" rel="stylesheet"/>
<link href="/Content/themes/base/jquery.ui.autocomplete.css" rel="stylesheet"/>
<link href="/Content/themes/base/jquery.ui.button.css" rel="stylesheet"/>
<link href="/Content/themes/base/jquery.ui.dialog.css" rel="stylesheet"/>
<link href="/Content/themes/base/jquery.ui.slider.css" rel="stylesheet"/>
<link href="/Content/themes/base/jquery.ui.tabs.css" rel="stylesheet"/>
<link href="/Content/themes/base/jquery.ui.datepicker.css" rel="stylesheet"/>
<link href="/Content/themes/base/jquery.ui.progressbar.css" rel="stylesheet"/>
<link href="/Content/themes/base/jquery.ui.theme.css" rel="stylesheet"/>

But if I run with debug="false". I’ll get this instead.

<link href="/Content/themes/base/css?v=myqT7npwmF2ABsuSaHqt8SCvK8UFWpRv7T4M8r3kiK01" rel="stylesheet"/>

I've found that what you need to have is the Nuget package Microsoft.AspNet.Web.Optimization installed in your project. It's included by default in an MVC4 RTM app regardless if you specify the target framework as 4.5 or 4.0. This is the namespace that the bundling classes are included in, and doesn't appear to be dependent on the framework. I've deployed to a server that does not have 4.5 installed and it still works as expected for me. Just make sure the DLL gets deployed with the rest of your app.

public static void RegisterBundles(BundleCollection bundles)
{
  bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
             "~/Scripts/jquery-{version}.js"));

   // Code removed for clarity.
   BundleTable.EnableOptimizations = true;
}

3. make sure to add debug false in web.config (when you start local debuging VS2013 will give you a popup saying that you need to make sure to putting it back before deploying into prod. that itself explains much.

<system.web>
  <compilation debug="true" />
  <!-- Lines removed for clarity. -->
</system.web>

Controlling Bundling and Minification

Bundling and minification is enabled or disabled by setting the value of the debug attribute in the compilation Element  in the Web.config file. In the following XML, debug is set to true so bundling and minification is disabled.

<system.web>
    <compilation debug="true" />
    <!-- Lines removed for clarity. -->
</system.web>

To enable bundling and minification, set the debug value to “false”. You can override the Web.config setting with theEnableOptimizations property on the BundleTable class. The following code enables bundling and minification and overrides any setting in the Web.config file.

public static void RegisterBundles(BundleCollection bundles)
{
    bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                 "~/Scripts/jquery-{version}.js"));

    // Code removed for clarity.
    BundleTable.EnableOptimizations = true;
}
Note: Unless EnableOptimizations is true or the debug attribute in the compilation Element  in the Web.config file is set to false, files will not be bundled or minified. Additionally, the .min version of files will not be used,  the full debug versions will be selected.EnableOptimizations  overrides the debug attribute in the compilation Element  in theWeb.config file

I had successfully been able to bund my JS script and CSS style sheet on one file each using the bundling functionally offered by “system.web.optimization”

public static void RegisterBundler(BundleCollection bundles)
        {
            bundles.Add(new StyleBundle("~/CDN/Content/_LayoutNotAuth").Include("~/CDN/Content/style.css", "~/CDN/Content/select2.css", "~/CDN/Content/StyleUpdates.css", "~/CDN/Content/jquery-ui-1.8.21.custom.css", "~/CDN/Content/jquery.qtip.min.css", "~/CDN/Content/htmlfeedback.css", "~/CDN/Content/facebookInputToken.css", "~/CDN/content/notifications/jquery.gritter.css"));
            bundles.Add(new ScriptBundle("~/CDN/Scripts/_LayoutNotAuth").Include("~/CDN/Scripts/jquery-1.7.1.min.js", "~/CDN/Scripts/modernizr-1.7.min.js", "~/CDN/Scripts/notifications.js", "~/CDN/Scripts/jquery.unobtrusive-ajax.min.js", "~/CDN/Scripts/menu.js", "~/CDN/Scripts/jquery-ui-1.8.23.custom.min.js", "~/CDN/Scripts/Notifications/jquery.gritter.js", "~/CDN/Scripts/jquery.qtip.min.js", "~/CDN/Scripts/json2.min.js", "~/CDN/Scripts/jquery.signalR.min.js", "~/CDN/Scripts/jquery.validate.js", "~/CDN/Scripts/jquery.validate.unobtrusive.min.js", "~/CDN/Scripts/inputs.js", "~/CDN/Scripts/select2.js", "~/CDN/Scripts/jquery.simplemodal.1.4.2.min.js", "~/CDN/Scripts/htmlfeedback/html2canvas.js", "~/CDN/Scripts/htmlfeedback/jquery.htmlfeedback.js", "~/CDN/Scripts/jquery.blockUI.js", "~/CDN/Scripts/jquery.tokeninput.js", "~/CDN/Scripts/RechercheProjet/ProjectSearch.js", "~/CDN/Scripts/jquery.address-1.5.min.js", "~/CDN/Scripts/RechercheProjet/ContractorSearch.js", "~/CDN/Scripts/Contact/ProfileContact.js", "~/CDN/Scripts/RechercheProjet/resultats_recherche.js"));

        }
 

To disable bundling and minification use this (this will disable optimization even if debug=true in web.config)

System.Web.Optimization.BundleTable.EnableOptimizations = false;

If you put EnableOptimizations = true this will bundle and minify even if debug=true in web.config

By default all files included in the Bundle would indeed be minified as well, but only in Release mode.

If you want to enable it in Debug mode as well, try adding this to your RegisterBundle method:

BundleTable.EnableOptimizations = true;