As I’ve already demonstrated, I like performance. So I cache and compress a lot. When I was put onto an ASP.NET project at work, I obviously wanted to optimize the site, so here’s what I did.
Taking some hints from Y! Slow, I decided I wanted to:
- Combine all the CSS into one request
- Minify the CSS
- Minify the HTML
- Deflate everything (gzip is slightly larger, and all modern browsers support deflate, so I just ignored gzip)
Combining the CSS was not so easy, as there’s no such thing in ASP.NET as a “ScriptManager.” I had two options: make a CSS manager (and use it everywhere), or figure out another way. Never taking the easy route when there’s a more interesting (and more front end developer transparent) way, I decided to make a filter (implementer of IHttpModule) to find all the “<link>” tags in the page header and replace them with one “<link>” to a combined CSS handler (which I called “CssResource.axd” to parallel ScriptManager’s “ScriptResource.axd”). Then, in my IHttpHandler implementation which handles CssResource.axd, I read the querystring, grab the requested CSS files from the file system, combine them into one string, and return them. CSS combining done.
Finally, the last thing the filter does is check if the browser accepts deflate compression. If it does, the filter compresses the stream. In the case of “ScriptResource.axd” and “CssResource.axd” requests, the deflating is done before the response is cached, so requests for those resources don’t need to be re-deflated for every request (their content is static, unlike regular html requests, so caching the whole response is okay).
The initial (cache empty) page load was 780k before I started. When I had finished, the page load was only 234k – a 70% decrease.
You can download the code from this site. To use it, you need to modify your web.config.
<system.web> <httpModules> <add type="CompressionModule" name="CompressionModule" /><!--This must be the last entry in the httpHandlers list--> </httpModules> <httpHandlers> <add verb="GET,HEAD" path="CssResource.axd" validate="false" type="CssResourceHandler"/> </httpHandlers> </system.web>
I cannot claim 100% credit for all of this work. I got many ideas from just browsing web search results, trying things out, and combining ideas from various sources. If I have not credited you, and I should have – I apologize, and will be happy to do. But I can say, that I did not just “copy and paste” this from anywhere – I’m confident that this work cannot be classified as a derived work of anything else. With that in mind, I release it into the public domain.
Compression (deflate) and HTML, CSS, JS Minification in ASP.NET by Craig Andrews is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
7 thoughts on “Compression (deflate) and HTML, CSS, JS Minification in ASP.NET”
Wanting to give your code a try but the ZIP appears to be corrupted. Is it just me or does it need to be re-uploaded?
@Zak Sorry about the slow response – you’re comment was marked as spam.
The archive seems to be okay. I tested it on Windows and Ubuntu without issue. I hope downloading it again will solve your problem.
Very very nice. Minifying HTML seems risky to me.. (Google and MSN do it, but few others).. but if the result is solid then congrats. 🙂
Hmm, just got a chance to test this out. It works good but it’s actually breaking my Asp.Net AJAX and keps it from loading and finding my ScriptResource.axd files. I’d love to drop the toolkit, but for the time being it’s going to stay put. Any ideas on how to correct, or did you not see this issue? Oh and btw, it compresses my page source from 48k to 9k, crazy fast loading times, just wish it didnt break the toolkit.
This really helped me out. IIS7 seems to take care of most of these issues but the HTML minify was a real winner.
My only feedback is StringComparison.OrdinalIgnoreCase is a better comparer, it is quicker.
Nice job! I have only a strange problem, after having minimized the html, if I see the code, there is no character at the end of tag
Why? Many thanks! 🙂
I meant the closing tag html…