Empty Bundle Using Ms Bundling

Empty Bundle using MS Bundling

This exact scenario occurred (v=[no value]) because the Build Action value on the .less file was accidentally set to None. This happened because the file was added to the project in an unusual way and then renamed to .less. Since VS.NET didn't know originally the file type it set it's property for Build Action to none.

Make sure the .less file has its Build Action configuration set to Compile, thus allowing the actual file is included in the build. This is also why the problem will not occur locally as it will be present, but once deployed it will be missing.

Does ASP.NET store bundled scripts in memory?

Short answer

Memory. But also remember that the browser already caches the information in the client.

Long answer

First of all, the bundle will be cached by the browser as it's said in the Bundling and Minification page:

Once you update one file in a bundle, a new token is generated for the
bundle query string parameter and the full bundle must be downloaded
the next time a client requests a page containing the bundle. In
traditional markup where each asset is listed individually, only the
changed file would be downloaded. Assets that change frequently may
not be good candidates for bundling.

Bundling and minification primarily improve the first page request load time.
Once a webpage has been requested, the browser caches the assets (JavaScript,
CSS and images) so bundling and minification won’t provide any performance
boost when requesting the same page, or pages on the same site
requesting the same assets. If you don’t set the expires header
correctly on your assets, and you don’t use bundling and minification,
the browsers freshness heuristics will mark the assets stale after a
few days and the browser will require a validation request for each
asset

And also shown here, in the image taken from the same page, where they tested with Fiddler:
Fiddler

So far we are safe as it's cached by the browser.

However, I went a bit further and created a small test project with this code in the Controller:

public ActionResult Index()
{
return View(HttpRuntime.Cache);
}

And this code in the View:

<p>
@Html.DisplayForModel()
</p>

Which gave me the following results:

  1. First run:

    :ViewCacheEntry:System.Web.Mvc.RazorViewEngine, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35:View:Index:Home:::__AppStartPage__~/_appstart.cshtml
    :ViewCacheEntry:System.Web.Mvc.RazorViewEngine, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35:View:Index:Home::Mobile:__AppStartPage__~/_appstart.vbhtml
  2. Second run:

    :ViewCacheEntry:System.Web.Mvc.RazorViewEngine, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35:Partial:_LoginPartial:Home::Mobile:
    :ViewCacheEntry:System.Web.Mvc.RazorViewEngine, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35:View:Index:Home:::System.Web.Optimization.Bundle:~/bundles/modernizr
    :ViewCacheEntry:System.Web.Mvc.RazorViewEngine, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35:Partial:_LoginPartial:Home:::System.Web.Optimization.Bundle:~/bundles/bootstrap__AppStartPage__~/_appstart.cshtml
    :ViewCacheEntry:System.Web.Mvc.RazorViewEngine, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35:View:Index:Home::Mobile:System.Web.Optimization.Bundle:~/bundles/jquerySystem.Web.Optimization.Bundle:~/Content/css__AppStartPage__~/_appstart.vbhtml

On the second run you will see that modernizr, bootstrap, jquery and css (my bundles!) are in the cache. That would explain why if we load the same page in 2 different browsers we will get the same query string, even after being loaded 5mins apart:

  • Edge: Edge
  • Firefox Dev Edition: Firefox Dev Edition

BundleTable.Bundles.GetBundleFor() returns but not Items inside

You need to register your VirtualPathProvider before bundle registration, in order to be able to find your files. Any files not found will not be included in bundle.Items

var vpp = new MyVirtualPathProvider();
BundleTable.VirtualPathProvider = vpp;
BundleConfig.RegisterBundles(BundleTable.Bundles);

Unless of course you already have it registered as HostingEnvironment.VirtualPathProvider.

ASP.NET MVC bundle working on local but not in server

I found the issue, after trying everything I went back an check the build scripts on the TFS server, we have continuous integration configured, turns out the build server was removing the .js and only letting the .min.js files on the final build. I removed that instruction and it started working.

Basically the .js did not exist on the server so there was nothing to bundle.

Thank you guys for your help!

Bundling and minification without ASP.NET MVC

It is absolutely possible to use the bundling and minification in a blank project.

  1. Use Nuget to install the package: Install-Package Microsoft.AspNet.Web.Optimization
  2. Create a BundleConfig Class and define your bundles:

    using System.Web.Optimization;
    public class BundleConfig
    {
    public static void RegisterBundles(BundleCollection bundles)
    {
    bundles.Add(new ScriptBundle("~/bundles/js").Include(
    "~/Scripts/*.js"));
    bundles.Add(new StyleBundle("~/bundles/css").Include(
    "~/Styles/*.css"));
    }
    }
  3. Register the BundleConfig class within the application start in the global.asax

    void Application_Start(object sender, EventArgs e)
    {
    BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
  4. reference the bundles in your HTML document.
  5. Enable bundling by disabling debug mode.

less bundle is empty in production

I removed dotless and the transformation pakcages and only used Web optimization framework. This way You can set the framework to compile the less code at build time.

How asp.net Bundling works internally

Let's take a look at what happens when we use the bundling in System.Web.Optimization.

In this example I used the "Empty ASP.NET MVC 4 template" and grabbed the latest "Microsoft.AspNet.Web.Optimization" package from nuget.

I then proceeded to register 2 javascript files. One for jquery and another for bootstrap.

public static void RegisterBundles(BundleCollection bundles)
{
var javascriptBundle = new Bundle("~/bundles/javascripts")
.Include("~/Scripts/jquery-{version}.js")
.Include("~/Content/bootstrap/js/bootstrap.js");
bundles.Add(javascriptBundle);
}

Now that we have our setup done, let's see what happens when we view the page.

debugview

You can see that both the javascript files were just included as we would normally do. This is what happens when you have the "debug" flag set in your web.config.

Let's turn this to false and see what happens now.

debugsettofalse

Now what we see is a single reference was added but with a very unique looking location. By clicking on it, we see that it spits out a minified and combined version of both of the javascript files that were referenced in our bundle.

funnycharacters

This funny query string parameter v=loMmcAiXrKwMoVsM8Ok8Q5jVmuFQUI3fiiRVJQC33Hs1 is a reference to our content and we can see that no matter how many times we hit the website, it's going to stay the same. (i.e. refreshing multiple times).

Let's see what fiddler says about the reference to our javascript files.

cache

We can see that the response is cachable. The cache expiration has been set for "Wed, 26 Mar 2014 06:49:06 GMT". Almost a year from today.

Subsequent requests to the resource will get read from the browser's cache.
"This HTTP/304 response indicates that the existing cached response remains fresh. Cache-lifetime headers on a HTTP/304 response may be used to update the cached response's freshness."

If you require any more information, see also http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification



Related Topics



Leave a reply



Submit