Faster sprite download

Weeks ago I participated in the webperf-contest. An excellent WPO contest with a clear objective: To speed up one site. In order to do that I re-wrote the frontend code using all WPO techniques I knew:
  • Unify CSS and move at document head
  • Unify Javascript
  • Async loading for javascript
  • Minify JS, CSS and HTML
  • Lazy load for images (img-ondemand my onw plugin:) )
  • Set cache headers
  • Clean unused CSS
  • Clean unused JS
  • Make an sprite or dataURI/MHTML for background images
  • Add extra JS functionality after onLoad
  • Join Ajax request
  • Async icon load
  • Make Shadows and rounded box using CSS3
  • Optimize Images size
  • Preload Iframe and set src attribute on timer
  • split base domain for paralleled download

The new Tip

In addition, when trying to get a faster startRender time I figured out that sprite loading is a key to start render.

In the common way to css and sprite loading

The browser starts loading the image sprite when it found some “sprite css rule” match with some body tag.
ie:
-HTML document
......
<link ref="stylesheet" type="text/css" href="style.css" />
</head>
<body>
.....
-Style.css
....
body{ background-image:url(sprite.png); }
...

In this case the browser  downloads first the style.css, and then the sprite.png.

Try this online demo (the style is delayed for demo purposes ).


Css and sprite parallel downloads

We can preload the image at head using a classic script likes this:
-HTML document
......
<script>
setTimeout(function(){
    var s = document.createElement('image');
    s.src =  'sprite.png';
    (document.getElementsByTagName('head')[0]).appendChild(s);
},5);
</script>
<link ref="stylesheet" type="text/css" href="style.css" />
</head>
<body>

The browser now will have the sprite image faster.

Try the Online Demo.

To summarize

IMHO dataUris/MHTML of Stoyan is a better technique,  because you save the sprite request. However, using dataUris you must encode the image data to base64. This encoding increase the image weight ~20%, bad point. Furthermore, the use of sprite is more common than dataUris .  So, parallel sprite seems good for me.

Feel free to comment

Martín :)

Posted in wpo | Tagged , , , | 1 Comment

Google Analytics Web Performance Tracker – Real Monitoring

(Versión en español)

Google Analytics is an excellent service to know users’ behavior on your site.  We only have to copy and paste an snippet, and we can know a lot of things . But this service doesn’t tell us how fast/slow our pages are. Performance information is very important as we known.

So, how can we use google analytics as performance monitoring service?

I wrote a tiny script to use eventTrack function of Google Analytics API and track measures of performance. Using this script you can store and analyze the real performance time from your visitors.

The demo here

Steps

1) Insert this script just after  <head> tag
<script>
var _gameasures = [['start',(new Date()).getTime()]];
function addGAMearsure(mark){
_gameasures.push([mark,((new Date()).getTime()-_gameasures[0][1])]);
}
</script>
2) Insert this script just before </body> tag
<script>addMeasure("Perceived Ready Time");function sendGAMeasures(){addMeasure("load");if(_gaq)for(var a=_gameasures.length,b=encodeURI(window.location);a-- >1;)_gameasures.push(["_trackEvent","Performance",b,_gameasures[a][0],_gameasures[a][1]])}if(typeof window.onload=="function"){var prevOnload=window.onload;window.onload=function(){prevOnload();sendGAMeasures()}};</script>

Optional

if you want you can add measures where ever you want.  Call addGAMearsure(‘my mark’)  Ej:
........
</head>
<body>
<script> addMeasure('Perceived ResponceTime'); </script>

The complete code (feel free to comment):

// mark startTime
var _gameasures = [['start',(new Date()).getTime()]];
//
// Add measure
// @mark string
//
function addMeasure(mark){
    _gameasures.push([mark,((new Date()).getTime()-_gameasures[0][1])]);
}
//
// add load event
//
function sendGAMeasures(){
    //add final measure
    addMeasure('load');
    // if _qaq is defined means that google analytics is set ok
    if(_gaq){
        // set page name
        // by default it get the page url, if you want you can change the value of pname
        var len = _gameasures.length, pname = encodeURI(window.location);
        // send all measures
        while(len-- > 1){
            _gaq.push(['_trackEvent', 'Performance', pname, _gameasures[len][0], _gameasures[len][1]]);
        }
    }
}
// set onload event checking if has been set previoully
if (typeof window.onload != 'function') {
    _sendGAMeasures;
}else{
    var prevOnload = window.onload;
    window.onload = function(){
        prevOnload();
        sendGAMeasures();
    };
}

I hope this script help you to monitoring the speed of your site :)

Martin

Posted in wpo | Tagged , , | 3 Comments

The evolution of ga.js and The best google analytics snippet.

A lot of posts show the blocking problem loading normal javascript files.  To sumarize:  when the browser finds <script src=…, it blocks executing and rendering until js file are downloaded and executed.
Steve Souder presented a complete analysis about the techniques to solve this issue for web performance. I’m using this to load async js files on sonico.com:
(function(d){
   s = d.createElement('script');
   s.src =  'file.js';
   s.type = 'text/javascript';
   (d.getElementsByTagName('head')[0]).appendChild(s);
})(document);
But, I figure out that is better to replace the closure statement by setTimeout funcion and set 0 milisecs. The setTimeout function has a nice performance over IE.  I discovered this trick while watching google.com home page source :P . So, my snippet is:
setTimeout(function(){
   s = document.createElement('script');
   s.src =  'file.js';
   s.type = 'text/javascript';
  (document.getElementsByTagName('head')[0]).appendChild(s);
},0);
The most common 3rd party widget is Google Analytics script, and some time ago google announced a new script improving the loading method. The main changes were: 1) move the script to the end of head tag 2) change the js code like this:
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXXXX-X']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www')   '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
I found a few articles analysing this snippet, for example Mathias that makes some improvements
var _gaq = [['_setAccount', 'UA-XXXXX-X'], ['_trackPageview']];
(function(d, t) {
   var g = d.createElement(t),
   s = d.getElementsByTagName(t)[0];
   g.async = true;
   g.src = '//www.google-analytics.com/ga.js';
   s.parentNode.insertBefore(g, s);
}(document, 'script'));
Another interesting article was writed by HTTPWatch team, they concluded that the new script is not faster than the previous one. But, I think this might be due the fact that they are not testing on a real environment.
I took the Mathias script and change the closure by the setTimeout. My final script is:
var _gaq = [['_setAccount', 'UA-XXXXX-X'], ['_trackPageview']];
setTimeout(function() {
   var g = document.createElement('script'),
   s = document.getElementsByTagName('script')[0];
   g.async = true;
   g.src = '//www.google-analytics.com/ga.js';
   s.parentNode.insertBefore(g, s);
},0);
Another good idea I found is load the script after onload event, using window.onload = function()…  but this idea has the big problem that you can lose tracks if the user goes to other page before the tracker do the mark. So, if you don’t care to lose a few hits, the best is the onload method.
The script:
var _gaq = [['_setAccount', 'UA-XXXXX-X'], ['_trackPageview']];
window.onload = function() {
   var g = document.createElement('script'),
   s = document.getElementsByTagName('script')[0];
   g.async = true;
   g.src = '//www.google-analytics.com/ga.js';
   s.parentNode.insertBefore(g, s);
};

Martin

Posted in wpo | Tagged , , , , | 5 Comments

Load images ondemand and get a faster web

(Versión en Español)

I wrote a small script based on jquery to improve a web page performance. It is very easy to use.

Your only have to serve all the images on the page channging src by longdesc property, and adding class img-ondemand

Example: <img src=”foto.jpg” /> now it must be <img src=”” longdesc=”foto.jpg” class=”img-ondemand” />

Here you find the code and the easy steps to use it.

http://code.google.com/p/jquery-images-ondemand/

See the demo online

http://tips.freedev.com.ar/demos/load-images-ondemand.html

enjoy ;)

Posted in wpo | Tagged , , | 7 Comments