Optimizing Ghost for Speed

in code

I recently decided to try Ghost, a relatively new, open-source blogging platform (you're viewing the outcome right now). The selling point was two-fold.

For one, Ghost is coded in Javascript, namely Node.js. With my recent Javascript immersion it's a natural fit.

Secondly, I want to focus on writing... not themes, widgets, plug-ins, etc. Ghost has an amazing, uncluttered UI, making it as easy as possible to write.

Out-of-the-Box Speed

One advantage of being built on Node.js is speed. The entire Ghost application, from the front-facing website to the Ghost admin runs exceptionally quick and smooth. But being obsessed with website performance like I am I decided to take a deeper look.

I ran several Ghost theme demo sites (like Urban, Meca and Wharton) through Google's PageSpeed test. The results varied from theme to theme but were less than spectacular.

Most themes scored in the 35-75 range (out of 100). On the lower end of the spectrum the Meca theme scored a 38/100 on the mobile speed test.

Not good at all.

Server-side

Improving the performance of a Ghost site involves two parts.

First, the server needs to be configured correctly. This involves enabling compression and browser caching, reducing server response time and a number of other best practices.

There are many great articles detailing how to configure a server for Ghost.

Implementing these steps will improve a Ghost site's PageSpeed score into the 70s or 80s. Good, but not great. Next comes client-side optimizations.

Client-side##

Before going into the details on client-side optimizations, one quick note: not all themes are made equal.

As I discovered in my quick sample of theme demo sites, some themes score significantly better on the Pagespeed test than others. If you want to save yourself some time and work, select a theme that scores well on the PageSpeed test out of the box.

After finding a good-looking, semi-performant theme you're ready to take the next steps.

Images####

In my case one of the biggest issues was images resizing and compression. My theme, Wharton, uses large images for each story. This requires me to upload relatively large images so they look good on large screens, but means small screens also get a really large image. Much larger than they need.

Google's PageSpeed tool is smart enough to know my site is serving up a large image, physically reduced in size to fit the small screen. To handle this correctly I should be serving a smaller version of the image to smaller screens, and the larger version of the image to larger screens.

Many CMSs can dynamically resize image to do this very task. Ghost unfortunately, can not (yet).

To remedy this I added Mobify.js - a library for improving responsive sites by providing responsive images, JS/CSS optimization, Adaptive Templating and other features. Mobify detects the screen size and serves up an appropriately sized image. Now small screens get small images and large screens get large images. It's a pretty powerful little tool.

CSS/JS Delivery####

The next issue to tackle was delivery of CSS and JS files. Linking to multiple CSS and JS files is highly frowned upon by the PageSpeed tool.

Due to my site's simple design (and small .css file - 43kb) I decided inlining the CSS was the best option. To accomplish this I created a simple gulp script.

var gulp = require('gulp');
var fs = require('fs');
var minifyCss = require('gulp-minify-css');
var plumber = require('gulp-plumber');
var gutil = require('gulp-util');
var htmlReplace = require('gulp-html-replace');
var replace = require('gulp-replace');

gulp.task('minimize', function() {
    return gulp.src('./css/**/*.css')
      .pipe(replace('../img/',          'http:///brettdewoody.com/assets/img/'))
      .pipe(minifyCss())
      .on('end', function(){ gutil.log('Compress CSS...'); })
      .pipe(gulp.dest('./dist'));
});

gulp.task('replace', ['minimize'], function() {
    return gulp.src('../default.hbs')
      .pipe(htmlReplace({'CSS': '<style>' +     fs.readFileSync('./dist/screen.css', 'utf8') + '</style>'}, {keepBlockTags: true}))
      .pipe(gulp.dest('../'));
});

gulp.task('build', ['minimize', 'replace']);

When I make changes to my site's styling a run gulp build to create the optimized build.

The above script reads my .css file, minimizes it and pastes the entire file into a <style> tag within the <head> of my site. If you view:source my site you'll see the entire CSS file within the source of the page.

For Javascript, I minimized each of the included scripts and wrapped them into a single file.

Results##

With the updates in place the site is now scoring a 98/100 on Mobile Speed, 100/100 on User Experience and 96/100 on Desktop Speed. Average load times from locations around the world is just a hair over 0.5 seconds too.

What tricks and tips do you have for speeding up your Ghost site?

Comments