Exceptional Performance without mod_pagespeed or apache (Page Speed score:99)
At last I have managed to get Google Page Speed Score of 99 and YSlow score of 97 for this blog. As mentioned earlier, this blog is generated using Pelican and deployed on heroku Cedar Stack which supports Python applications. It is served from great wsgi app called ‘static‘, gunicorn and gevent. I had to make a lot of changes in static to make it possible.
Gzip Compression
As we are serving static content, there is no need to compress the content with each and every request. We can have gzipped content generated along with the other static content and serve it when requested. This approach, in my opinion, is faster than on-the-fly gzip compression used by nginx and apache. We can save CPU time used to compress the content with each request. I used gzip_cache plugin to generate the gzipped version of all my content. Next step was to serve this static content when requested. Static does not support this by default. I had to modify it a little bit. It tries to find the gzipped copy of the content, if gzipped content request is received.
Leverage browser caching
This is purely handled by the HTTP Server serving the content. Again I had to
make a few changes in static to enable caching. I tried to keep the
syntax similar to Apache’s ExpiresByType
. Expire time can be specified in
seconds against each mime type.
Specify a character set
Again this is purely handled by the HTTP Server and I had to make a few
changes in static to make it possible. Just like Expires headers, I
tried to keep the syntax similar to apache’s AddCharset
. Charset can be
set for filename patterns.
Minify resources & Combine external resources
Using assets plugin to combine and minify resources which further uses web assets. This is done offline, so no minification & combining overhead here.
Optimize images
Lossless compression of images was done using jpegtran and optipng. This task was automated by writing a pelican plugin. Again, done offline, so no CPU needed to serve optimized images.
Remove unused CSS
This blog template was designed using twitter bootstrap and lots of custom css. Even after combining and minification, the size was 130KB. I used mincss to find unused css and remove it. Now the CSS is just 14KB (4KB gzipped). I had to re-add some styles which were used on other pages. Once again, done offline and at design time only.
What’s still missing?
Specify image dimensions
Being responsive design, it is not possible to send all images with image dimensions specified. The images resize themselves according to the screen size. Although, we could use some javascript to determine screen size and resize images accordingly, but this would have its own overheads.
Leverage browser caching for external resources
This blog uses only one external resource ga.js, which is the javascript file used by Google Analytics. It comes with Expires headers of 12 hours. There has been a lot of discussion about caching and serving it from one’s own servers but I guess anything like this would be overkill. ga.js is so common, that it is probably downloaded by some other website already.
Using CDN for static content
This task is in my todo and I am still looking for a good (preferably free) CDN.