Compression (deflate) and HTML, CSS, JS Minification in ASP.NET
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.