Austin Grigg bio photo

Austin Grigg

Husband, father of two bright-eyed boys, dabbling theologian, web developer and app maker.

Twitter Instagram Github

Tuning a Static Site for Performance and SEO

I use jekyll, a static site generator1, to manage this blog. It is a fairly geeky tool, but it has been a lot of fun to learn and it gives me complete control over my content. I ran a test recently using Google’s PageSpeed Insights and saw some areas I could improve my site’s performance.

Now, you may be thinking, Improve performance? It’s a static site, there is no database to slow things down! You’re just serving static html files! That is true, it is already fast, but a lot of the performance issues actually happen on the front-end in the browser, especially on mobile.

I host my site on a Windows virtual server running in Azure, mostly because I already had it setup. Here are some of the challenges I faced and what I did to overcome them and improve performance and SEO.

Creating a Canonical URL

An SEO best practice is to only have your content exist at a single URL. That means you don’t want to have the same article available at two different URLs, like austingrigg.com/blog/2014-goals and www.austingrigg.com/blog/2014-goals. You want to create a canonical URL and redirect the other to it. I chose to go without the www for my canonical URL, just austingrigg.com. It is really just a matter of preference – pick one and stick with it.

So, there are two ways to do that. I could have created a separate site in IIS and added the www.austingrigg.com binding to that site and just had that whole site redirect to austingrigg.com, but I don’t like the idea of having a whole site just for redirecting. That is where the URL Rewrite Module comes in. Install this using the Web Platform Installer and then add the following to your web.config in the root of your site’s folder:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="Redirect www" stopProcessing="true">
          <match url=".*" />
          <conditions>
            <add input="{HTTP_HOST}" pattern="^www.austingrigg.com$" />
          </conditions>
          <action type="Redirect" url="http://austingrigg.com/{R:0}" redirectType="Permanent" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

Obviously replacing the URL for your blog for mine.

Minifying and Combining CSS and Javascript

One of the most important things you can do for front-end performance is reduce the number of HTTP requests (files you are serving) and making those files as small as possible. One of the ways you can do this is by combining all of your CSS into one file and all of your javascript into one file and minifying2 the content so the file size is as small as possible.

Setting up a process for minifying and combining your CSS and javascript is beyond the scope of this post, but you could use a command line tool like Grunt or something like CodeKit to do it for you.

Cache Assets

One of the best things you can do for performance is tell the browser which files are not going to change, so they don’t have to download them again. You do that with cache headers. I wanted to tell the browser that it could cache my CSS, javascript, and images for up to a year. The trick with that is you have to make sure you rename those files if you update them instead of just copying a new version out, otherwise people will not see the changes because they are looking at a cached version.

Give Unique Name

First, I installed the Jekyll Minibundle plugin which will hash3 a file and re-name it using that hash. This ensures that the filename is unique and only changes when the actual content of the file changes.

To use the Minibundle plugin, I reference my CSS stylesheet like this:

<link href="{{ site.url }}/{% ministamp _tmp/main.min.css assets/css/main.min.css %}" rel="stylesheet">

And once the site is built, it outputs this:

<link href="/assets/css/main.min-0e9d23f356784e84f2ff34bd3cac1e30.css" rel="stylesheet">

See the hash in the filename? I do the same thing for my minified and combined javascript file.

Set Cache Control Headers

Now to tell IIS to set the cache control headers so the browser will cache my assets. I added the following web.config file to my assets folder, which contains my css and javascript, and my images folder. This tells IIS to set the cache headers for the files in those folders to expire after 1 year.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <staticContent>
            <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="365.00:00:00" />
        </staticContent>
    </system.webServer>
</configuration>

404 Pages

If someone navigates to a URL on your site that doesn’t exist, you probably want to display a friendly message saying you couldn’t find the page they were looking for.

So, I created a 404.html page and setup IIS to redirect to it if the URL could not be found. Great, everything seems to be working, except that page is returned with a 200 OK status code instead of the 404 status code that indicates that the page wasn’t found. Why is this a big deal? Because, when Google (or any other search engine) indexes your site, if a page no longer exists you want to let them know. The only way you can do that is to send a 404. If you send a 200 status code Google will assume that was a legitimate page and put it in their index.

Screen shot of 404 page

So, to fix this I created an aspx (ASP.NET Web Forms page) that returned a 404 status code and the content from my 404.html page as the response body. Below is the web.config setting to redirect to the 404.aspx page and the code to send the status code and return the correct html.

web.config

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <httpErrors>
        <remove statusCode="404" subStatusCode="-1" />
        <error statusCode="404" prefixLanguageFilePath="" path="/404.aspx" responseMode="ExecuteURL" />
    </httpErrors>
  </system.webServer>
</configuration>

404.aspx

<%@ Page Title="" Language="C#" AutoEventWireup="true" CodeFile="404.aspx.cs" Inherits="_404" %>

404.aspx.cs

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Configuration;
using System.IO;

public partial class _404 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Response.TrySkipIisCustomErrors = true;
        Response.Status = "404 Not Found";
        Response.StatusCode = 404;
        Response.WriteFile(Server.MapPath("404.html"));
        Response.End();
    }
}

It is a little convoluted, but it is worth it to provide a good user experience and do the right thing for SEO.

Conclusion

So, hopefully this helped you understand a little bit more about making your static site load faster and following SEO best practices. Feel free to reach out to me on twitter as @austingrigg if you have any questions or any suggestions to make the site better.


  1. A static site generator is just a tool that takes source code, templates, and assets and builds a simple HTML site. The advantage is that you can host your site pretty much anywhere and it is super fast because there is no database, you are just serving HTML pages and static resources.

  2. Minification is the process of removing all unnecessary characters from source code without changing its functionality.

  3. A hash function is any algorithm that maps data of arbitrary length to data of a fixed length. If you hash the same data with the same algorithm you will get the same hash back every time.


comments powered by Disqus

← Where are the prophets? 2014 Goals →