23

Is it possible to use bundling and minification from Microsoft.AspNet.Web.Optimization without having an MVC project?

I'm creating an AngularJS site communicating with a REST API. For the REST API I'm using ASP.NET Web API. I have also created an "ASP.NET Empty Web Application". There are only HTML, js and CSS files in this project (and a web.config). I'd like for my js and CSS files to be bundled and minified, but I don't want to create a MVC project just to get that. Is it possible?

Matt
  • 25,467
  • 18
  • 120
  • 187
Joel
  • 8,502
  • 11
  • 66
  • 115
  • 1
    since it's in asp.net.web.optimization and not in one of the mvc assemblies you should be able to :) – Anders M. Mar 12 '14 at 08:10
  • @AndersM. But I'd had to add some kind of .cs file or config to trigger it? Just setting debug to false in web.config did nothing – Joel Mar 12 '14 at 08:11
  • 1
    To be honest I don't know, I never used this before but since it's under an asp.net assembly and not mvc and/or razor it can be used for asp.net as well, did a quick google search http://weblogs.asp.net/scottgu/archive/2011/11/27/new-bundling-and-minification-support-asp-net-4-5-series.aspx http://www.codeproject.com/Articles/692311/Bundling-and-Minification-ASP-NET http://surajdeshpande.wordpress.com/2013/08/28/bundling-and-minification-in-asp-net-4-5/ happy coding – Anders M. Mar 12 '14 at 08:41
  • You need to **render** the styles and scripts which you have added, see my [answer](http://stackoverflow.com/a/28738462/1016343) below. – Matt Feb 26 '15 at 09:19

6 Answers6

24

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.
Claies
  • 22,124
  • 4
  • 53
  • 77
  • 4
    I figured it out thanks to your answer. But I had to change my `index.html` to `index.cshtml` and add `@using System.Web.Optimization` to the cshtml file and manually create a `Global.asax` (since there was none) – Joel Mar 12 '14 at 14:41
  • 1
    @Joel to support `@using` in cshtml, one needs to add razor related libraries? right? – harishr Dec 21 '14 at 15:27
  • @Entre: It did not work, because one step is missing, see my [supplemental answer](http://stackoverflow.com/a/28738462/1016343) below: You need to **render** the scripts and styles by calling the render methods. – Matt Feb 26 '15 at 09:29
  • 2
    The reason this is a bad idea is because of the cost. What are you saving by bundling? A noticeable amount, sure. But you are now changing your SPA text-only app (HTML/CSS/JS) into a Razor app, and have to change your html to cshtml or something similar. Which means you are also hitting the view engine and building out pages, which takes longer than what you save with plain-ol HTML/CSS/JS. Instead, use CDN's to house your HTML/CSS/JS if you really think you need it. – Suamere May 27 '15 at 02:21
  • see stackoverflow.com/a/34508048/1545567 to use a bundle from plain html – Christophe Blin Dec 29 '15 at 09:24
8

In addition to the answers given above, I'd like to mention that there was one important step forgotten:

After you've installed the NuGet package for Microsoft.AspNet.Web.Optimization and registered the bundles in the Global.asax (as explained in Claies answer), you need to add the render methods for styles and scripts as follows:

<%= Styles.Render("~/bundles/css") %>
<%= Scripts.Render("~/bundles/MattsUIBundle/js") %>

This needs to be added to the ASPX page's head section in order to render the bundles "~/bundles/js" and "~/bundles/css" added earlier to your page. Without that it will not appear (see why do I need render?). It requires that you add

<%@ Import Namespace="System.Web.Optimization" %>

to line 2 of your page in order to register the namespace, assuming you have already added the NUGET package Microsoft.AspNet.Web.Optimization to your code.

If you want to include more related files, do it like

void Application_Start()
{
    BundleCollection bundles=BundleTable.Bundles;
    var jsMattsUIBundle = new ScriptBundle("~/bundles/MattsUIBundle/js");
    jsMattsBundle.Include("~/Scripts/lib/jquery.min.js");
    jsMattsBundle.Include("~/Scripts/lib/jquery-ui.custom.min.js");
    jsMattsBundle.Include("~/Scripts/lib/jquery.watermark.min.js");
    bundles.Add(jsMattsBundle);
}

or more simply

    jsMattsBundle.Include("~/Scripts/lib/jquery.min.js",
            "~/Scripts/lib/jquery-ui.custom.min.js",
            "~/Scripts/lib/jquery.watermark.min.js");

That will bundle together all the 3 scripts under the virtual path "~/bundles/MattsUIBundle/js".


Important: Bundling will check if you are in debug mode or release mode. Optimizations only apply if you remove the debug flag in web.config

<compilation debug="true" />

or if you explicitly define inside of Application_Start you want to optimize regardless of being in debug mode:

BundleTable.EnableOptimizations = true;

Likewise, if you're using CDN support, turn it on via

BundleTable.Bundles.UseCdn = true;   //enable CDN support

which will allow you to declare

var jqueryCdnPath = "http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js";
BundleTable.Bundles.Add(new ScriptBundle("~/bundles/jquery",
            jqueryCdnPath).Include("~/Scripts/jquery-{version}.js"));

Note that the CDN will only be used in release mode. The following script ensures that a local copy of jQuery is loaded if the CDN loading fails:

    <%= Scripts.Render("~/bundles/jquery") %>
    <script type="text/javascript">
        if (typeof jQuery == 'undefined') {
            var e = document.createElement('script');
            e.src = '@Url.Content("~/Scripts/jquery-1.7.1.js")';
            e.type = 'text/javascript';
            document.getElementsByTagName("head")[0].appendChild(e);
        }
    </script> 

assuming that you're providing a local copy of jQuery 1.7.1 at "~/Scripts".


Note: In MVC Razor syntax rendering is done in the view as follows:

@Scripts.Render("~/bundles/MattsUIBundle/js") 
@Styles.Render("~/bundles/css") 

More information can be found here.

Community
  • 1
  • 1
Matt
  • 25,467
  • 18
  • 120
  • 187
4

@Matt, actually you don't need to add

<%@ Import Namespace="System.Web.Optimization" %>
<%= Styles.Render("~/bundles/css") %>
<%= Scripts.Render("~/bundles/MattsUIBundle/js") %>

And you don't need use CSHTML-template. You can reference your bundles this way from an html page:

<link href="bundles/css" rel="stylesheet"/>
<script src="bundles/MattsUIBundle/js"></script>

It will save your page from View Engine.

Srost
  • 129
  • 4
3

To gain file-load speed in your SPA, you need manual time in the setup. The wrong answer is to implement Razor, especially if your whole goal was to stay away from MVC and its friends (Which is a good thing if your goal is an AngularJS SPA). When you implement the Optimization framework mentioned in other answers, you now have to hit the View Engine to build out CSHTML files, which is a noticeable hit to your speed, probably more than what you think you're saving.

So like I said, you'd need developer time to minimize the files. You would have to manually send them to a CDN you own (or need to set up). You can then reference your own CDN with your own packages as set up by your team, and that CDN will be cached by the user's browsers.

Then, when one or more of your SPA's need to point to updated HTML/CSS/JS, you increment the CDN version in that SPA App. Other SPA Apps can even stay the same with an old version (though I recommend trying to stick to latest-version CDN's). And the user's browsers will recognize the new CDN version and pull a new version to cache.

Suamere
  • 5,691
  • 2
  • 44
  • 58
  • can you say how to bundle and minify files without .cshtml.have any samples?? – Skull May 30 '16 at 04:54
  • 1
    You use GULP (or Grunt). With GULP, you can easily automate the actions of bundling and minifying, as well as translating LESS into CSS and moving files around. – Suamere Jun 01 '16 at 12:52
0

You can use YUI or Google Clouser Mapper

This is the example how to user YUI with Visual Studio

http://peronnemyr.wordpress.com/2012/09/26/using-yui-compressor-for-net-integrated-to-builds-in-visual-studio-2010/

This link has Visual Studio Extensions http://visualstudiogallery.msdn.microsoft.com/5469b7e2-90d7-4f54-b299-ae47e26323e6

You can User JSMIN http://www.crockford.com/javascript/jsmin.html

You can run JsMin as Post Build Event as below jsmin <"$(ProjectDir)\debug.js" >"$(ProjectDir)\min.js"

This is the link how run JSMIN http://jasonfaulkner.com/RunJSMinInVisualStudio.aspx

If this answered your question, Please check right on left side.

ineffable p
  • 1,207
  • 2
  • 22
  • 46
0

You can also use VS extention WebEssentials minification which can minify your js/css files independently from project compilation (so that you do not need any third party dll dependency). It has bundling as well, very convenient.

Anton Lyhin
  • 1,925
  • 2
  • 28
  • 34