Last time I wrote about Cassette I was talking about how to generally get up and running. How to use Cassette within an ASP.Net MVC project. What I want to write about now is (in my eyes) the most useful feature of Cassette by a country mile. This is Cassettes ability to ensure scripts are served in dependency order.
In short, what I want to do is reference a script file somewhere in my server-side pipeline. I could be in a view, a layout, a controller, a partial view, a HTML helper... - I just want to know that that script is going to turn up at the client in the right place in the HTML so it works. Always. And I don't want to have to think about it any further than that.
And this is where Cassette takes the pain away. To quote the documentation:
"Some assets must be included in a page before others. For example, your code may use jQuery, so the jQuery script must be included first. Cassette will sort all assets based on references they declare."
Just the ticket!
What does this look like in reality? Let's build on what I did last time to demonstrate how I make use of Asset References to ensure my scripts turn up in the order I require.
_Layout.cshtml file I'm going to remove the following reference from the head of the file:
I'm pulling this out of my layout page because it's presence means that every page MVC serves up is also serving up jQuery and jQuery UI (which is what
~/bundles/core is). If a page doesn't actually make use of jQuery and / or jQuery UI then there's no point in doing this.
"But wait!", I hear you cry, "Haven't you just caused a bug with your reckless action? I distinctly recall that the
Login.cshtml page has the following code in place:"
"And now with your foolhardy, nay, reckless attitude to the
~/bundles/core bundle you've broken your Login screen. How can jQuery Validation be expected to work if there's no jQuery there to extend?"
Well, I understand your concerns but really you needn't worry - Cassette's got my back. Look closely at the code below:
See it? The
~/bundles/validate bundle declares a reference to the
~/bundles/core bundle. The upshot of this is, that if you tell Cassette to reference
~/bundles/validate it will ensure that before it renders that bundle it first renders any bundles that bundle depends on (in this case the
This is a very simple demonstration of the feature but I can't underplay just how useful I find this.
Let's demo this. First of all add the following file at this location in the project:
The eagle-eyed amongst you will have noticed
- I'm mirroring the MVC folder structure inside the Scripts directory. (There's nothing special about that by the way - it's just a file structure I've come to find useful. It's very easy to find the script associated with a View if the scripts share the same organisational approach as the Views.).
- Lastly and most importantly, do you notice that
// @reference ~/bundles/coreis the first line of the file? This is our script reference. It's this that Cassette will be reading to pick up references.
To make sure Cassette is picking up our brand new file let's take a look at
CassetteConfiguration.cs and uncomment the line of code below:
If you browse to the home page of the application this is what you should now see:
What this means is,
Index.js was served up by Cassette. And more importantly before
Index.js was served the referenced
~/bundles/core was served too.
There is a gotcha which I've discovered whilst using Cassette's Asset References. Strictly speaking it's a Visual Studio gotcha rather than a Cassette gotcha. It concerns Cassette's support for Visual Studio XML style reference comments. In the example above I could have written this:
/// <reference path="~/bundles/core" />
Instead of this:
// @reference ~/bundles/core
~/Scripts/_references.js in VS 2012. So if you value your Intellisense (and I do) my advice is to stick to using the standard Cassette references style instead.
There is also support in Cassette for CSS referencing (as well as other types of referencing relating to LESS and even CoffeeScript). I haven't made use of CSS referencing myself as, in stark contrast to my JS, my CSS is generally one bundle of styles which I'm happy to be rendered on each page. But it's nice to know the option is there if I wanted it.
Finally, as last time you can see what I've done in this post by just looking at the repository on GitHub. The changes I made are on the References branch of that particular repository.