How to Setup a CDN to Speed Up Your Website

March 14, 2013

If you’re looking for ways to speed up your website, one of the best is to setup a CDN. You can think of a Content Delivery Network as a service that hosts your website’s static files and delivers them to the client instead of your own web server. Direct benefits of this are reduced load on your own server and faster download times for the client. Sounds good? Let’s get to it.

Considerations

This how-to will offer some high level tips and tricks that should apply to any web project. Some specifics will be shown in the examples, but this is definitely not a copy-and-paste solution that will solve your CDN ambitions.

The Basics

First you need a basic understanding of how to integrate a CDN into your website. It’s simple really: for any static resource you serve up, replace its URL with the URL of the same resource on the CDN. For example: http://mywebsite.com/img/logo.png becomes http://cdn.mycdnprovider.com/img/logo.png . This means that your CDN provider will need to host logo.png; let’s talk about that next.

The CDN hosts your static resources so somehow your files must be loaded onto its network. There are two ways this usually happens: You upload the files manually, or the CDN fetches the files automatically from an origin server. With the latter method, there’s no reason why the origin server can’t also be your web server. With both methods, the resources persist until they’re updated. This means that if you modify logo.png you must update its corresponding resource on the CDN, otherwise the old, unmodified version will continue to be delivered. You can almost think of the CDN as a type of cache that needs to be invalidated when the source changes. Regardless, there’s no doubt you’ll be making updates to your CSS, JS and images so you need to consider how you’ll easily update the CDN. Don’t worry – we’ll cover a simple, yet elegant solution for this.

Getting Started

You’re going to see immediate performance improvements by serving up your images, JS and CSS through your CDN so we’ll focus on these. You’ll want to set up some sort of convention that makes it easy to interchange URLs within your code. Basically, whenever you output a URL, use your CDN instead.

As you can see in the PHP and Javascript snippets above, it’s as simple as using a global prefix in front of all your relative URLs. But what about CSS? There’s no such thing as CSS variables, which is why you should never write vanilla CSS. If you don’t already use either SASS or LessCSS, then make the switch – NOW! We prefer LESS, so here’s how to set up your styles.

You should now have full control over the URLs used to serve up static content to the client. If you want to disable the CDN, you only need to set CDN = '/'; and resources will be pulled from your server.

Server Configuration

This might be enough to satisfy you, but there’s more. Most projects have three environments – local/dev, staging/testing and live/production so you should have a method to configure which CDN server is used based on the environment. You likely don’t want to use any CDN on your dev server and your testing server should use a different CDN from the production server to avoid versioning conflicts (discussed later). So all you need are a few configuration files. (The following example is using the CakePHP framework)

The configuration files above shouldn’t be checked into version control because they’re presumably different from server to server. Instead, check in defaults such as  cdn.php.default and cdn.less.default, with the intention that the developer deploying the code to the server for the first time will create the required config files with the server-specific settings.

Versioning & Resource Invalidation

As mentioned in the Basics section, you’re likely to deploy multiple releases of your static files. Most CDNs use some sort of TTL to invalidate resources, but if you want full control, you’re better off to version your resources. If you’re using Amazon’s CloudFront CDN service, here is a good discussion on resource invalidation. This essentially means that instead of modifying logo.png, you create a new file called logo_ver2.png or put a copy in a versioned folder such as /resources_ver2/. However, that would be a nightmare to manage wouldn’t it?

We previously mentioned that you can configure your CDN to fetch resources from an origin server. If you use the versioned folder solution for the invalidation problem, your URLs would look something like this:  http://cdn.mycdnprovider.com/ver-1.0.0/img/logo.png. To invalidate logo.png you would increment the version number to 1.0.1 thereby forcing the CDN to fetch a different copy of the resource. With a simple URL Rewrite, our web server can spoof the version number in the URL and deliver logo.png from the same path on the server.

This little piece of magic makes it a cinch to invalidate any resource without duplicating it. The CDN and the client browser think they’re downloading from some versioned folder, but we know better, don’t we!

More Configuration

You might be tempted to just modify your existing CDN configuration files to include a version number. This would work, but to keep your code and framework modular it’s best to have a separate VERSION config file. You’ll want to check this file into version control, especially if you have multiple developers working on the same project. You’ll have to come up with some sort of scheme as to when you increment the VERSION number, but that’s out of the scope of this discussion. Create your version files and make use of them:

The above LESS files are a little awkward because now you have two version files to maintain. Hopefully your environment scripts will make this easy for you to manage. If you don’t have any environment scripts, you should consider having something that makes it easy for you to increment the version number – a script that reads in the current VERSION, increments it, then writes out VERSION and version.less.

Conclusion

The key concepts to setup a CDN that is configurable and maintainable are:

  • Use a global variable to easily access the URL of your CDN
  • Prefix the URLs of your static resources with the CDN variable
  • Use configuration files to define the CDN variable
  • Set your CDN to fetch resources from an origin server
  • Invalidate your resources by putting them into a versioned directory
  • Spoof the versioned directory by using a URL Rewrite
  • Maintain a version number within a config file

There’s no doubt you’ll discover ways to improve on these ideas, but they’re a good starting point. A possible improvement to this scheme is to figure out a way to maintain separate versions of resources. For example it’s likely that logo.png won’t change often, but style.less will. It could be a waste to invalidate logo.png every time you increment the version in order to invalidate style.less. As it stands now, all your resources are invalidated even if you mean to invalidate just one of them. This might not be ideal, but perhaps simplicity trumps idealism – that’s for you to decide.

Comments

  • Very nice article. I would request you to elaborate the points which you have written in .htaccess.
    Not everybody wants CDN to access the origin server ( i.e,. one’s own web-server ). Some people might want the resources to be uploaded during build time only. Because that is where ‘css’, ‘js’ and images are to be created. So .htaccess would be of use or not in that case.
    Also purging of resources on CDN is missing from your article.
    I am new to this line, so apologizing in advance if something doesn’t make sense to you.
    Cheers,
    Siddhartha

    Siddhartha Singh December 17, 2013,  10:56 pmReply
  • […] I recently mentioned the growing benefits of establishing a CDN.  Though the language we used differed, we all agreed it was an ultimate goal.  So, I thought it might benefit everyone to provide a few resources on the topic.  To start, while the specific execution discussed in the following resource is not exactly what I have in mind, it nevertheless provides a solid perspective on setting up a CDN: Set Up a CDN to Speed Up Your Website. […]

    OAO BTS Development | About CDNs February 4, 2014,  8:39 amReply
  • If you are using Laravel as a framework (it’s great option by the way) you may use this package to manage your CDN assets easely. https://github.com/Vinelab/cdn

    Mahmoud Zalt January 26, 2015,  6:20 amReply

Leave a Reply

Your email address will not be published. Required fields are marked *

Wrap code in <code> tags.