submit to reddit       

On Site Optimization

Page load times are important for a good user experience. People are more engaged with sites that load quickly, and usually visit more pages.

Making pages load quickly isn't just about making web servers faster. When browsers load pages, first they have to download the page from a web server. If the page references other files, like CSS, Javascript and image files, the browser also needs to fetch those files. Once all the files have been downloaded, the browser has to render the page. Pages can be optimized so that browsers can load them quickly and efficiently.

This kind of optimization isn't about tuning the server, it's about optimizing your site's pages so that browsers can load them easily. This involves spending time tuning a site's HTML template.

A good place to get ideas on how to optimize your site is Google PageSpeed Insights. You can use PageSpeed Insights to analyse pages on a site and determine ways to improve page load times. PageSpeed Insights gives detailed suggestions on how you can improve performance. Your site is assigned a page rank score which improves as you work through the list of issues.

Inline CSS

I used to keep the CSS code for my site in a seperate file in /var/www/default_theme.css. It was referenced in the head section of my HTML template with this line:

<link type="text/css" rel='stylesheet' href='/default_theme.css' >

When pages from my site were loaded by browsers, they wouldn't be able to carry on rendering that page until they had made another request to my server and downloaded the CSS file. I have eliminated that delay by including the CSS code directly in the head section of my HTML template. I added the following tags to my template's head section, and pasted the contents of my CSS file between them:

<style> </style>

This makes each web page larger, but reduces the number of requests that my server has to handle. It also means that browsers can render the page more efficiently.

Deferred Javascript Loading

It's quite common to reference javascript source files in the head section of a web page. I used to have the following tag in my site's head so that images can be viewed using the Lightbox Javascript plugin:

<script src="/js/lightbox.js"></script>

The problem with this is that when a page is downloaded, the browser has to pause the processing of the page to download the Javascript file. This interrupts the browser before it can begin rendering the page.

The solution is to move the references to Javascript files 'below the fold'. I updated my HTML template to include this line just after the footer instead of in the head section. When pages on my site are loaded in a browser, most of the page renders before the browser has to get the Javascript file.

Asynchronous Javascript Sharing Buttons

Sharing buttons are a great way to boost traffic to your site. Visitors click the sharing buttons to share your site with their friends and followers on social media, thus increasing the amount of traffic that your site gets from social networks. There are many companies that provide plugins that can be added to a site. The downside with some sharing plugins is that they can reduce page load speed because of Javascript issues.

Instead of using a single plugin to display sharing buttons, you can use buttons from different sites. Each social network has it's own sharing buttons that you can use to put sharing buttons on your site, and most of them are asynchronous (but not Reddit at the time of writing). Asynchronous buttons are loaded after the page has rendered, so the page loads faster.

Since I removed the sharing plugin and replaced it with individual sharing buttons, page load times displayed in Google Analytics have become much more consistent, and a lot lower.

Minify CSS and Javascript

CSS and Javascript files often contain a lot of white space such as space and new line characters. Using white space helps to make code more readable, but it also adds to file sizes. Removing white space characters makes code unreadable, but it can significantly reduce the load on your server. I decided not to minify my CSS code as I want to be able to read it, but I have deleted a lot of white space, while still preserving some basic formatting. This is how my CSS code used to look:

.navbar li { display:inline; border-left: solid 1px black; padding-left:6px; } first { border-left: none; } .navbar li:first-child { border: none; }

This is how it looks with some white space removed:

.navbar li { display:inline; border-left: solid 1px black; padding-left:6px; } first { border-left: none; } .navbar li:first-child { border: none; }

Javascript code can also be minified. I don't plan to modify the Javascript code, so I have minified it completely. There are two Javascript files that browsers download from my site every time they load a page, /js/lightbox.js, for displaying images, and /js/jquery-1.7.2.min.js. The jquery file is already minified.

The Lightbox code isn't minified by default, so I went to this Javascipt minifier tool and pasted the code from lightbox.js into the input text area, and hit the submit button. I created a new file in /var/www/js called lightbox.min.js and pasted the output from the minifier tool into the file. I changed my site's HTML template to reference this new file instead of the original unminified version. The unminified version of this file was 11.6KB, and the minified version was 6.2KB.

Leverage browser caching

Web browsers can cache pages so that they don't need to be downloaded again if a users goes back to a page that they have already visited. Browsers can be told to cache pages by sending a cache control header before the page is sent by the server. This requires a couple of modifications to Apache's configuration. First, the headers module needs to be installed:

$ sudo a2enmod headers

Next, the following code needs to be pasted somewhere in /etc/apache2/apache2.conf:

<FilesMatch "\.(ico|png|gif|jpg|js)$"> Header set Cache-control "public, max-age=2592000" </FilesMatch> <FilesMatch "\.html$"> Header set Cache-control "public, max-age=604800" </FilesMatch>

This tells Apache that any file with a .ico, .png, .gif, .jpg or .js endings should be cached for 2592000 seconds (30 days) and files with a .html ending should be cached for 604800 seconds (7 days). The final step is to restart Apache:

$ sudo service apache2 restart

I executed this command on another computer to ensure that caching worked properly:

$ wget --save-headers http://raspberrywebserver.com/feed-icon-14x14.png

When I opened the downloaded file in a text editor, these HTTP headers were at the top:

HTTP/1.1 200 OK Date: Sun, 13 Oct 2013 01:24:25 GMT Server: Apache/2.2.22 (Debian) Last-Modified: Tue, 01 Oct 2013 03:40:50 GMT ETag: "226f0-2b1-4e7a5b80cb907" Accept-Ranges: bytes Content-Length: 689 Cache-control: public, max-age=259200 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: image/png

The cache control header can now be seen amongst the other HTTP headers.

Google Analytics Page Timings View

The Google Analytics screen shot on the right shows how page load times have improved. Page load times fluctuated a lot while I was using a sharing plugin, but levelled out at as soon as I got rid of it on the 10th of October. Over the next few days page load time reduced even more as I minified CSS and Javascript.



comments powered by Disqus

Follow me