Minifying Your JS and CSS with Cassette

I’ve recently investigated Minifying CSS and JavaScript for a client. Minifying compiles your CSS and JavaScript to a smaller optimised version; increasing a sites performance for its users. Ideally we wanted to place all JavaScript into a single file, a single request to the server.

We needed to find a solution that would be easy to use so developers at the client’s remote site would know how to use the solution once code was handed over.

At TrueClarity we use .NET for our solutions therefore we wanted a tool that would fit directly into the .NET framework neatly and intuitively. So after investigating various Minifying tools I decided to give Cassette a try an Asset bundling solution that neatly plugs into your projects in Visual Studio. Cassette comes with various functions one of them being Minification.

Cassette requires NuGet to be installed so the Cassette.Aspnet package can be downloaded and installed into your project. Once installed you will notice a new “.cs” file in your solution, this is where you add your configurations for Cassette. The installation will make alterations to your projects Web.Config to add the Cassette namespace to your project and http handlers.

Cassette uses ‘Bundles’ each bundle will resolve as a single file, html, css or js. This is where new bundles are added & removed.

bundles.Add<StylesheetBundle>("/Styles");

bundles.Add<ScriptBundle>("/Scripts");

Cassette will locate all of the Styles and Scripts within the given directories recursively and generate a single file.

Ordering is important
To ensure the generated CSS and JavaScript files work correctly I needed to inform Cassette of the ordering for the generated files. This can be accomplished through a bundle.txt located within the given directory in the Configuration file. Within the bundle.txt you will need to write the filenames for the required JS/CSS in the order required.

For instance your bundle.txt files will need to be located in:

~/Styles/bundle.txt
~/Scripts/bundle.txt

Referencing the generated files in Markup
To then inject the Javascript/CSS into your documents <head> or before </body> you will need to replace the current static reference in your mark-up with C# code which injects your new JavaScript/CSS.

JavaScript

<%Bundles.Reference("/Mobile/Scripts"); %> 
<%: Bundles.RenderScripts() %>

CSS

<% Bundles.Reference("/Mobile/Styles/stylesheets"); %>
<%: Bundles.RenderStylesheets() %>

The reference needs to be the same string specified in CassetteConfiguration.cs.

Build
When the project is built the JS/CSS is generated and accessible through the cassette http handler. For each build/change to CSS/JS cassette generates a random string for CSS and JS references. So this ensures all users are given the new changes without their cache being cleared locally. A cool feature!

Viewing Source
When you view source on your site you will now notice CSS in the head being referenced like so:

<link href="/cassette.axd/stylesheet/kKTh3QhojEGH-OUCjweN5PBrzOw=/Mobile/Styles/stylesheets" rel="stylesheet" type="text/css" />

You will also notice the new JS reference at the bottom of the page as a single reference which contains a concatenation of all the previous JavaScript files:

<link href="/cassette.axd/stylesheet/kKTh3QhojEGH-OUCjweN5PBrzOw=/Mobile/Styles/stylesheets" rel="stylesheet" type="text/css" />

When the web.config debug=”false” the output of cassette will be as above, but when its set to “true” cassette will output each js/css file independently without being minified so that you can debug through your code!

The Result
The following table shows the before and after comparison of the projects CSS and JavaScript.

The compiling was able to reduce the file size from 74KB to 14KB!

Cassette uses Microsoft’s Ajaxmin.dll a compiler for .NET. Cassette is an intuitive way of getting your project to consolidate your assets into single files; Potentially Cassette can support other compilers such as Yahoo’s YUICompressor or Google’s Closure compiler. Both are jar files so would need some tinkering through .bat files to perfect the automation.

Some Big Questions

10 years in business is one of those milestones that gives you a chance to stop and think. You can carve some time to reflect on what has been achieved both good and bad. A chance to contemplate some of the bigger questions. Why do we exist? What do we believe? What makes us unique?

It was important for us to answer these questions honestly. No point producing answers that our clients or people would not recognised. Any answers would need to be held up against our 10 year history and shown to be true. While we will focus on the positives this is not a time for aspirational thinking. We needed to keep it real.

We believed the answers to these questions lay in the ideas, values and emotions sitting behind the work we’ve done. This stuff is hard to articulate, hard to write down and hard to agree on. So a process began where we talked things out, trying to build a shared understanding of why the company did what it did.

Our search for answers settled on a feeling. The shared sense of achievement we get from helping the people we work with successfully realise their goals. The goal needs to be challenging, never the same thing twice and unless we can make a real difference to the outcome it probably isn’t for us. That said the goal is a means to an end, the real driver here is how people feel when their ideas, aspirations and intent become reality.

Therefore our whole reason for being can be distilled down to a single point in time. It is the moment when our work first starts to meet the real needs of the people we work with. It is all about how the people feel in this instant. The point when our work is out there in the wild.

These moments can be big, launching new functionality on the easyJet website, supporting the Conservative Party during the election campaign, launching two new online collections for AMD or building Dyson a new platform for all their websites. But size really isn’t important, what is important is delivering the moment. In fact if we can start delivering value earlier all the better.

While the moment we are talking about is very much a point in time, how it meets the needs of all the stakeholders involved will vary, and therefore the way it makes each person feel will be different. This is where the shared sense of achievement comes from.

The multifaceted nature of these moments means we often encounter conflict along the way. Our aim is to find a mutually beneficial solution and wherever possible avoid compromise. We usually do this by focusing on the underlying intent, and having the courage to make sure we do the right thing for everyone involved.

“It’s not what the moment is, it’s what the moment does.”