As most of you know, performance improvement is an ongoing effort. Pages change, new stuff arrives, and your once so fast and optimized page becomes slower and slower… So it is good, to check your page regularly. Which I did with our site http://www.alice-dsl.de
When doing this, with the great help of webpagetest.org, I stumbled across some interesting behaviour with IE 8. So let’s see, what we got here. The beginning of the page loads like this in a waterfall chart:
What caught my suspicion was the strange “gap” between combobox.css and errorboxes.css.css (sic!).
What is happening there? IE8, by default using 6 connections in parallel with HTTP1.1, is simply waiting ~0,15 seconds apparantly doing nothing. And then re-using its connections, to fetch two further CSS files. What happens here?
So I looked at the source of the page, and this is what I found right between these two objects:
<!–[if IE 6]> <link rel=”stylesheet” type=”text/css” href=”http://static.alice.de/provider/content/staticcode/std/anbieter/9011180/2010-05-07-10-39-28/rs_iefix.css.css”/> <![endif]–>
Hmmm… Weird. This is an CSS file, that only IE 6 should load, to fix some CSS issues with that Browser. IE 8 should not be affected by this at all, and the Waterfall indeed showed, that the asset is not downloaded. Well, let’s try and see what happens, if I remove this comment from the source code.
Voila! The “gap” is gone. And IE 8 fetches all the CSS files at once, using all 6 connections in parallel. So we found the culprit.
Unfortunately simply removing this is not an option, as obviously somebody wanted on purpose a backwards compatibility to IE 6. And I was curious, if it could be fixed, by simply doing some re-sorting. So my first try was to place this piece of code right BEHIND the regular CSS files. And the result was this:
Hm, unfortunately not really a leap forward. We simply have moved the “gap” from within the CSS files now to a position behind the files, right in front of JS files.
Other try. Let’s put it first! And the result is:
Wow, this comes a suprise. The “gap” is gone! I was pretty glad with that result, up until one of our Web Designers told me, that even though this looks pretty nice, I probably would break the functionality by doing so. Because IE 6 would load its CSS fixes, and when afterwards loading the default CSS objects, would overwrite its own fixes. We have to check on that.
So maybe it would be better, to deliver IE6 its own page by varying by User-Agent or whatsoever. But the lesson I learnt now: Using the current mechanism for IE 6 surprisingly puts quite some penalty on IE 8. If possible, avoid this approach.
With a time to render of 1 second that our page has, this effect is responsible for 15% of that.
In case somebody knows a best practice, that doesn’t come with penalties, please feel free to comment.
Seems there is indeed a best practice, that solves the issue, without breaking functionality. And is easy. A small snippet of code solves the issue, placed in the HEAD before any CSS/JS Files being loaded. It looks like this:
<meta http-equiv=”X-UA-Compatible” content=”IE=edge” />
Meanwhile our page has changed a bit, concatenating most of the CSS files. So let me show you just briefly the Waterfall BEFORE adding this code:
And now AFTER this code has been added to the HEAD in front of loading the CSS Files:
Thanks to Stoyan, who found a serious flaw with my solution, which you can see in the comments below.
So I was going back to one of my initial ideas, putting the conditional comment in front of ALL CSS-Files. But this time, I left it empty. And had a second one, were it was originally placed, right between the two CSS-Files, which would be used as intended, to download the file.
What can I say, now it works, and IE 6 still gets its CSS File.
So the correct, stupid, solution is, to place this code before any CSS/JS gets loaded:
Visible here: http://www.im-mai-an-der-elbe.de/full8.htm
Sometimes reality bites… The first solution was from an analytical point much more convincing. Now I do have an workaround, but with the much more unsatisfying feeling left, to not really understanding, why it works.
Thanks to Stoyan for finding this serious flaw!
I have seen in some boards recently a lot of comments like “Well, 0.15 seconds… So what. I won’t fix this just for a tenth of a second.” Be carefully: The delay depends on your specific site! Or, to be more precise: The transfer time of the CSS, that is loaded directly BEFORE the Conditional Comment.
Here is another case from WPT.org, where the delay is almost half a second (!), instead of a tenth of a second:
With a time to render of 1.2 seconds, this is a good third of it!
So you should test your sites behaviour, before deciding not to tackle this issue.