Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC4 Beta Minification and Bundling: Ordering files and debugging in browser

I've started using bundling and minification included with the MVC4 Beta. I'm running into a few issues with it:

For one thing, if I use the classic <script src="Folder/js" type="text/javascript"/> bundling, it seems like I have to rename my files to make sure they're bundled in the proper order.

  • Let's say I have three javascript files: "ants.js", "bugs.js", "insects.js"
  • ants.js depends on bugs.js
  • bugs.js depends on insects.js
  • Default bundling seems to bundle them in alphabetical order.
  • To get them to bundle properly, I have to rename them to: "0.insects.js", "1.bugs.js", "2.ants.js"
  • That's really hackish and there has to be a cleaner way.

The next problem I'm having is debugging. I like to step through the javascript in my testing browsers, is there a way to turn off just the minification while in DEBUG mode?

EDIT: To be clear, I know I can create bundles and register them from C#, it just seems really ugly to have to do it that way.

like image 825
Ben Lesh Avatar asked Mar 11 '12 18:03

Ben Lesh


People also ask

What is bundling and minification?

Bundling and minification are two techniques you can use in ASP.NET 4.5 to improve request load time. Bundling and minification improves load time by reducing the number of requests to the server and reducing the size of requested assets (such as CSS and JavaScript.)

What is difference between bundling and minification?

Both bundling and minification are the two separate techniques to reduce the load time. The bundling reduces the number of requests to the Server, while the minification reduces the size of the requested assets.

How do you use bundling and minification in MVC 5?

Bundling and minification can be enabled or disabled in two ways: either setting the value of the debug attribute in the compilation Element in the Web. config file or setting the enableOptimizations property on the BundleTable class. In the following example, debug is set to true in web.


2 Answers

To temporarily get non-minified output use this

  public class NonMinifyingJavascript : IBundleTransform
{
    public void Process(BundleContext context, BundleResponse bundle)
    {
        if(bundle == null)
        {
            throw new ArgumentNullException("bundle");
        }

        context.HttpContext.Response.Cache.SetLastModifiedFromFileDependencies();

        foreach(FileInfo file in bundle.Files)
        {
            HttpContext.Current.Response.AddFileDependency(file.FullName);
        }

        bundle.ContentType = "text/javascript";
        //base.Process(context, bundle);
    }
}

If you wanted it based totally on a config setting, I imagine you could create an IBundle transform that delegates to this one or JsMinify depending on your config setting

In order to control the ordering of the javascript files you need to use the BundleFileSetOrdering

 var javascriptBundle = new Bundle("~/site/js", new NonMinifyingJavascript());

         //controls ordering for javascript files, otherwise they are processed in order of AddFile calls
         var bootstrapOrdering = new BundleFileSetOrdering("bootstrap");
         //The popover plugin requires the tooltip plugin
         bootstrapOrdering.Files.Add("bootstrap-tooltip.js");
         bootstrapOrdering.Files.Add("bootstrap-popover.js");
         BundleTable.Bundles.FileSetOrderList.Add(bootstrapOrdering);
         javascriptBundle.AddDirectory("~/Scripts", "bootstrap-*.js");
like image 172
chrisortman Avatar answered Sep 18 '22 19:09

chrisortman


I use the MVC default NoTransform instead of the NonMinifyingJavascript proposed by chrisortman. As far as I know it does the same. But still not optimal. Ideally I want a script tag for each idividual script file when I want to debug. This makes debugging a lot easier with VS11, which I like to use (one debugger so I can debug js and c# in one debug session). So I created this little helper:

@helper RenderScriptTags(string virtualPath)
{
    if (Minify /* some appsetting */)
    {
        <script src="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl(virtualPath)"></script>
    }
    else
    {
        foreach (var file in System.Web.Optimization.BundleResolver.Current.GetBundleContents(virtualPath))
        {
            <script src="@Url.Content(file)"></script>
        }
    }
}

@RenderScriptTags("~/libraries")

I have a single page app, so I have this in my main cshtml file, but it can easily be generalized by moving this to an htmlhelper extension method. Works nice!

This code takes also into account the BundleFileSetOrdering if you have set one!

like image 24
Jaap Avatar answered Sep 19 '22 19:09

Jaap