Blog

Where we discuss our work, thoughts, and process

Why Minify?

HiFi has most of Yahoo’s best practices for high performance websites built in, right out of the box. In particular, our custom CSS and JavaScript handling system takes care of six items on the checklist with zero effort on the part of the front-end developer. Let’s take a look at these techniques, and how they improve the final page-load speed.

First, though, a preview of how HiFi handles stylesheets and scripts. We added two new tags to our templating language: {% css %} and {% js %}. These are designed to be used every time a script or stylesheet is included in a template, and they take care of all the details for you. Each tag is given a comma-separated list of file names that will be included. For example, a standard js tag might be {% js 'jquery,jquery.cycle,jquery.validate,setup' %}.

The Benefits

Choose over @import: Back when Netscape Navigator 4.0 was still in wide use, developers would often include their CSS files using , which would hide the stylesheet entirely from Netscape and its buggy CSS rendering. Fortunately Netscape is not an issue anymore, but certain other browsers have trouble with the @import statement. Using the @import rather than a standard element prevents the browser from starting to render the page until the stylesheet is completely downloaded, decreasing the apparent speed of the website. HiFi will always use the element for including stylesheets, so you don’t ever need to worry about this.

Add an Expires or a Cache-Control Header: Unless a file has changed since last time a visitor has seen it, there is no reason for their browser to download it again. Fortunately, the HTTP protocol includes an Expires header, which tells the browser “this file won’t change for X number of days, so don’t bother downloading it again until then”. HiFi automatically sets the expires header as far in the future as possible. So what happens when a developer actually has changed a stylesheet or script and you do want visitor’s browsers to download the new version? To work around that, the {% js %} and {% css %} tags add a timestamp to the end of the filename they write into the final HTML document. Some server magic redirects this new filename to the actual file, but since the timestamp changes every time the files themselves change, the visitor’s browser sees it as a new file and will ask the server for a fresh copy.

Gzip Components: Just as you can create a zip file to compress files on your desktop, a web server can compress files using a standard called gzip before sending them to the visitor’s browser. HiFi takes care of this by default, only gzipping files if the browser knows how to uncompress them.

Split Components Across Domains: Most browsers will not download more than two files at one time from any particular domain name. This is a holdover from a decade ago when servers and internet connections were both slower and it was an attempt to prevent one person from slowing everyone else down by retrieving a large number of files at once from a single server. Until the HTTP specification catches up with modern technology, we can trick browsers into getting more than two files at the same time by splitting the files across multiple subdomains. HiFi uses three subdomains for each site: The main "www" subdomain contains all the HTML files, the "ui" subdomain contains all the other files a front-end developer creates—stylesheets, javascript, and images—and the "files" subdomain contains the various images and other files that are uploaded to individual pages throughout the site. This way, five files can be downloaded in parallel (since, typically, only one HTML file is used for each page), potentially more than doubling the total speed of the pageload.

Minimize HTTP Requests and Minify JavaScript and CSS: Although spreading our files across three subdomains helps, it is still much faster to download one large file rather than several small ones. Most websites use a number of JavaScript files and many also have more than one stylesheet, so this is an obvious inefficiency to work on. Additionally, since both JS and CSS typically use a lot of whitespace for readability, even very basic minification (removing any unnecessary characters from the file) can result in massive reductions in file size. For example, the jQuery library goes from 155kb down to 24kb.

We use a customized implementation of the minify script to both combine and compress all the JS and CSS files used on each page. Since compressing these files makes them difficult to read, we needed a way to leave this feature off while developing a site and then turn it on in a single step when the site is ready to go live. Both of our asset tags take an optional “min” keyword, which does everything needed to combine and compress the asset files. For instance, if you had three CSS files that should be combined, you would use {% css 'reset,typography,layout' min %}. (The final compressed file will always keep the sources files in the same order you list them in, so cascading styles will work properly.)

Screenshot of minified CSS file

Taking the GetHiFi.com website for example, before minification the scripts and stylesheets came in at 63.36kb spread over seven HTTP requests (excluding jQuery, which we are hotlinking from Google's CDN). With the JavaScript and CSS files minified, their size is almost halved to 36.92kb and two requests.

A future post will go into more detail on the mechanics of our minification technique, but what really matter are the results.

Comments

albertpaul68's avatar
albertpaul68
One likely reason is that markup typically changes MUCH more often, and would have to be minified for every page load. For instance on a given Stack Overflow page, there are timestamps, usernames, and rep counts that cwna dumps could change with every page load, meaning you would have to minify for each page load as well. With "static" files like css and javascript, you can minify far less often, so in the minds of some, it is worth the work up front.

Consider also that every major web server and browser support gzip, which compresses all of your markup (quickly) on the fly anyway. Because minifying is slower and much less effective than gzipping anyway, webmasters may decide that minifying for every page load isn't worth the processing cost.
Joel Sutherland's avatar
Joel Sutherland NMC team member
Albert,

We don't actually minify the HTML itself for many of the reasons we mention. Instead we automatically combine and minify the included CSS and JS.

Even with gzip, it is worthwhile to minify first. Minifiy gzip is more effective than gzip alone. This is because gzip doesn't know anything about the rules of CSS or JS and can't do clever things like renaming variables and eliminating whitespace.

The biggest value to performance is the combination of files since it eliminates http requests. Since we're doing that anyway it makes sense to minify as well.
Mica's avatar
Mica
Hi,
I was building exactly the same mechanism as yours when I've discover your website and your project.

I've done a big part of the work. I'm using custom bash script to do the minification and combine files.

Where I came to an issue was when building a plugin system for my template manager to transform css and js tags to those minified ... and surprise : I use Twig too (with Symfony2).

So I was wondering if you've used a Twig Extension with custom TokenParser or something else ... And if it is the case could you, please, post your extension code (or email me) ? (with usage/licence specs)

You've done a great job, bravo (french congrats) !

PS : sorry for my english mistakes ... I'm french
P's avatar
P NMC team member
@Joel

You replied to a human spammer and left their link up. What does a Certified Wireless Network Administrator have anything to do with this subject? Why does the linked site have footer links for Ralph Lauren? If you remove the arbitary link, surprisingly the comment content does not change.

Leave a comment

Real Time Web Analytics