Performance Optimization for Websites Built With Craft

Performance optimization is an increasingly important consideration for every web project. Fast load times are essential not only for SEO, but also for your website visitors. According to Kissmetrics, 40% of users abandon a website that takes more than 3 seconds to load. What they see— or don’t see— in the first few seconds is going to leave an impression of the quality of your site.

Rules for speeding up a web page

Steve Souders, former Head Performance Engineer at Google, composed a popular list of 14 rules for faster loading web sites, which remains valid today:

  1. Make Fewer HTTP Requests
  2. Use a Content Delivery Network
  3. Add an Expires Header
  4. Gzip Components
  5. Put Stylesheets at the Top
  6. Put Scripts at the Bottom
  7. Avoid CSS Expressions
  8. Make JavaScript and CSS External
  9. Reduce DNS Lookups
  10. Minify JavaScript
  11. Avoid Redirects
  12. Remove Duplicate Scripts
  13. Configure ETags
  14. Make AJAX Cacheable

Performance Testing Tools

Here are a few resources you can use to test performance:

We’ve found it very helpful to test a web page in several different testing tools and to save the results before and after each step of optimization. This shows us the performance gains we make after each step, and tracks our overall progress.

How We Optimized Our Own Site

Optimizing Performance for websites built with Craft
Results on Google PageSpeed Insights before and after optimization

The screenshot above shows the process of how we optimized our web site in Craft CMS, our content management system of choice. First, we tested our site on webpagetest.org. Then we selected a single page to test. We chose a page from the blog as opposed to the home page, as the home page is static, while the blog entries are dynamic.

Optimizing Performance for websites built with Craft
Result of test from webpagetest.org before optimization

Previously, we had taken a number of steps to improve performance, including:

So already we were seeing pretty good results, but we still had some work to do.

“80-90% of the end-user response time is spent on the front-end.”

While most performance optimization is related to front-end, we wanted to see what performance gains we could squeeze out of the back-end as well.

Optimizing Performance for websites built with Craft
The frontend/backend split of our tested page

Optimizing Our HTML

We began by optimizing Craft requests to the database. We use Matrix fields for content on most pages, and adding Craft Cache tags reduced the load time by 90ms. While that was a nice gain, we were really looking for some way to generate static HTML files. We came across a great Craft plugin to do just that in HTML cache, which we have customized to suit our needs. By removing the cache tags and utilizing this plugin instead, we were able to reduce load time by an additional 100ms. Now every page on our site is served up as a static HTML file, and there are no longer any requests to the database (after the page is generated/loaded for the first time). Furthermore, we minimized our HTML in order to save every last byte we could.

Optimizing Performance for websites built with Craft
PD Cache Craft plugin

Another step we took was to move the source for SVG sprites from HTML into an external file that we saved to local storage. By doing this, we reduced the size of the document from 12.3 KB to 7.9 KB and load time from 184ms to 172ms. Finally, we added expire headers on HTML pages with the duration of one hour, so if a user returns to the same page within that timeframe, the load time will be just 1ms from the browser’s cache.

Optimizing Performance for websites built with Craft
Document sizes and load times after each step of optimization

Compressing Images in Craft Assets

For images, we searched for a way to compress images transforms in Craft. We tried Tiny Image, a Craft plugin for optimizing images in Craft Assets using the TinyPNG API. But this plugin can’t optimize generated thumbs, so we need to find a better solution or create our own.

Adding an Expires Headers

We added a far-future expires headers in .htaccess file and we unset ETag headers for that resources as you can see on HTML5 Boilerplate htaccess file. We cached CSS and JavaScript files for one year, images and other media files for one month. When we update these files, we add a hashtag to the filename of new version like so: “main.12345.css”.

Using Web Font Loader

We load fonts from Google and Typekit asynchronously via Web Font Loader library to avoid page blocking while loading the fonts. The primary downside to loading fonts this way is Flash of Unstyled Text (FOUT). When this occurs, the rest of a page may render before the fonts are loaded. Google and Typekit fonts have some performance issues which may affect our optimization score.

Optimizing Performance for websites built with Craft
Performance issuse with Google and Typekit fonts tested on Pingdom Website Speed Test

Adding Lazy Load for Images

Lazy load scripts delay the loading of images until they become visible in the viewport. Using this technique, we reduce the initial server load so that a page renders more quickly. We’ve been using the Unveil.js plugin on our page and have found that it works well.

Coding for Speed

Here are a few pointers for writing faster CSS and JavaScript:

  • Pay attention to performance consideration as you write the code. Don’t wait until later and optimize.
  • Avoid unnecessary nesting of selectors in CSS, and use short names for CSS classes.
  • Use CSS animations instead of JavaScript animations.
  • For JavaScript animations, use requestAnimationFrame for timer loops.
  • Remember that object-oriented JavaScript will run slower than non object-oriented JavaScript.

Plans for the Future

Going forward, we plan to eliminate .htaccess files. Instead, we’ll add all logic into the main server configuration file, as using .htaccess files slows down the Apache HTTP server. We’ll also replace Typekit and Google fonts with fonts generated on Font Squirrel. This will allow us to load fonts via Font Face observer and cache them with expires headers on CDN.
We’ll also make use of a cookie-free domain for static resources, and generate different image sizes for each device (retina, non-retina, mobile). Finally, we plan to test out Critical CSS and load the most important files first, then other files asynchronously.

Getting Started with Performance Optimization

As you can see, there is a lot that can be done to improve the performance of your web sites. If all of this feels a bit overwhelming, here are the three steps you should take right away:

  1. Enable Gzip Compression
  2. Minify & Concatenate CSS and JavaScript files.
  3. Compress your images

These will give you the best performance gains for your effort. After you’ve implemented these steps, work through the other recommendations above.

What’s your experience? What steps have you taken to improve performance on your sites?