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.
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.
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
Leverage browser caching for external resources
Using CDN for static content
This task is in my todo and I am still looking for a good (preferably free) CDN.