Wednesday, May 23, 2012

ASP.Net MVC App Structure: Using Cassette For JS and CSS

I can't tell you how many times I remember having to put my finger in one of the holes and wind the tape back in.
I still love these things. I'm not sure why.

What Is Cassette?

Cassette is a bundling and minification tool that is very powerful and extremely easy to implement. Long before MVC4 Beta had bundling and minification, Cassette was already doing it better, IMO.

Advantages Of Using Cassette

  • Easy to debug! Bundling and minification is only performed debug="false" is set in the Web.config. 
  • No more need for @section. There will be no more reason to render a section to your layout to plop your <script/> and <link/> tags in.
  • Tracks JavaScript file dependencies. Cassette uses a nice little comment at the top of each .js file to manage what scripts need to be loaded first.
  • Automatically prevents false caching. We've all seen the issue where we've updated some script file and our browser is just dying to hang on to some old version. Cassette gets around this by appending a hash of the file(s) to the reference URL, so every time you change a file, you're pretty much guaranteed your browser will pull down a new copy, but at the same time unchanged files will remain cached.
  • Handles JavaScript templates. Cassette works well with a variety of JavaScript template providers. It actually creates a script to precompile your templates, renders a script tag that loads that script, and hosts the script. It's very slick, but I'm going to try to focus on just the JS and CSS aspects of Cassette today.

Getting Started With Cassette

First you need to install Cassette. There is a nice quick start guide on their site. Personally, I just right click References in my web project and select Manage NuGet Packages. Then I search online for Cassette and install it. Once it's installed, it will have set up your Web.configs, added references, and added a class file called CassetteConfiguration.cs. 

Once the NuGet package is installed, you're going to want to take a look at CassetteConfiguration.cs. What's going on in here is there are a few method calls to set up the root folders for your scripts, templates ans styles. JavaScript templates are disabled by default. As of this writing, it comes initially set up to minify, but not bundle, JavaScript and CSS when debug="false". You can do a lot from this area, configure bundles via file searches, all sorts of things, set up CoffeeScript, LESS, etc. for that see their documentation. Generally I just do the following:

C# - from CassetteConfiguration.cs

public class CassetteConfiguration : ICassetteConfiguration
    public void Configure(BundleCollection bundles, CassetteSettings settings)

Your Folder Structure Is Now Free!

Now that Cassette is going to be bundling everything in production, I like to structure my folders for css and JavaScript to mirror my Views directories. So if I have a view that requires a script called /Views/Foo/Bar.html, I'm going to have a JavaScript file at /Scripts/Foo/Bar.js, and maybe a style sheet at /Content/Css/Foo/Bar.css. The world is your oyster now, because once Cassette is done with this, it won't matter where you have your files or how many of them there are, really. Also, for support methods in JavaScript I tend to break them out by their namespace names (for more information on namespacing in JavaScript have a look here).

Where To Place .JS and .CSS References In Markup

I always put my CSS files in the <head/> tag, and my JS file references just before the closing </body> tag. I do this because I want the CSS to be loaded and processed right away so the styles can be applied to the objects in the DOM as soon as possible. I also want my JavaScripts to be one of the last things loaded because most browsers will only pull down two or three external resources at a time, and I don't want all of the images on the page to wait for my JavaScripts to get pulled down, when 99% of the time my JavaScripts aren't even going to be executed until the entire document is ready anyhow.

Razor - _Layout.cshtml


<!DOCTYPE html>

Where Not To Place JavaScript and Styles In Markup

  • Do not use inline scripts, do not use inline styles. I'm not going to get into the "whys" here, becasue that's a whole different post... For now, I'll just leave it at "you want to seperate your styles from your behaviors from your markup". Be unobtrusive.
  • Do not put css or styles in your Partial Views! This is a really common mistake I see. What's going to end up happening here, is you're going to end up loading the same scripts or css twice, which can cause unexpected behavior.
  • Try not to put JavaScript in the <head/> tag if you can avoid it. It's not always avoidable, but for reasons I previously mentioned, put them just before the closing </body> tag.

Setting Up JavaScript File Dependencies For Cassette

This is pretty simple as long as you stay on top of it. What needs to be done here is you need to add a little comment to the top of your JS file referencing any .js files that are prerequisite to that file. For example:

JS - Cassette Reference Example

/// <reference path="Scripts/jquery.js" />

/* be sure to note that above there are three "///"
 * and also the path="" is root relative even without
 * the leading "/". */

  alert('Omg, wee! The document is ready!!!11');

Referencing Your .js and .css Files With Cassette

This is probably the easiest part of all. In a C# code block in your .cshtml files, I recommend at the top of the file, just as I demonstration in my _Layout.cshtml example above. All you do is just add a line that says Bundles.Reference("~/Path/Your/File.js") for each .js or .css file you want to add into a bundle. The syntax is the same for both .js and .css files. It gets a little trickier if you want to reference an external file, although I'm not sure why you'd want to do that, they do detail referencing external scripts in their documentation.

That's really all there is to it! Now I'd recommend setting debug="true" and "false" in your Web.config and checking the page out in your browser a few times so you can marvel at the differences.

No comments:

Post a Comment

This form allows some basic HTML. It will only create links if you wrap the URL in an anchor tag (Sorry, it's the Blogger default)