Grav is already one of the fastest CMS options available, but it's possible to easily transform your Grav-based site into a world-class performer. A CDN or Content Delivery Network and some new Grav features can make this possible.
Let's take a real-world example to show how this can be done. And what better example than the getgrav.org website itself.
Before starting on this endeavor I ran a test using the popular webpagetest.org service to get an initial benchmark:
The results were a mixed bag to be honest. Grav is quick, but we were not taking advantage of browser caching, some compression settings, nor a CDN for static files.
Setting up the CDN
A content delivery network (CDN) is a system of distributed servers (network) that deliver webpages and other Web content to a user based on the geographic locations of the user, the origin of the webpage and a content delivery server. -- webopedia.com
You can use pretty much any Pull Zone style CDN, but we chose MaxCDN as they are pretty much the leader in CDN services and have a great set of control panels, tools, and APIs to make the process of integrating as simple as possible. They are also very open source friendly and provide CDN services for many great open source projects such as Bootstrap, FontAwesome, and jQuery.
Creating the initial Pull Zone is a simple affair with MaxCDN by following their detailed instructions.
After the zone is created, you will probably want to tweak a few settings:
- Setup a custom DNS entry with name
cdn.getgrav.orgthat aliases to our provided CDN name (optional)
- Set the
Default Cache Timeand
Cache-Control Headerboth to 7 days
- Set the Edge Setting options for
Strip All Cookiesand
Ignore Cache Control
CDN Plugin for Grav
Pull Zone CDNs work by having the request for static resources (CSS, JS, Images, etc) made via the CDN and then caching and distributing those files among the CDN network to ensure that users always receive a cached copy from the closest server. This ensures your site is fast no matter the geolocation of the end user. In order for this to be a seemless process in Grav, we need a plugin to rewrite standard local URLs such as:
<img style="" src="/user/pages/02.blog/state-of-grav-apr2015/github-trending.png">
<img style="" src="http://cdn.getgrav.org/user/pages/02.blog/state-of-grav-apr2015/github-trending.png">
This is can be done pretty easily with Grav's plugin hooks and a little Regex magic. Yesterday I wrote a simple plugin eloquently named Grav CDN Plugin. To install this plugin simply install it via GPM:
$ bin/gpm install cdn
This will install and activate the CDN plugin, If you view the source, you will see the URLs for CSS, JS, and images are being rewritten to use a specific pull zone name. You need to update this to use your own domain as outlined by your CDN provider. To accomplish this simply create a new file:
user/config/plugins/cdn.yaml and put the following:
enabled: true pullzone: your-cdn-domain.com
your-cdn-domain.com is either the custom domain name you setup, or the domain name as provided to you. In our case it was
cdn.getgrav.org. Save this file to ensure your changes get picked up by Grav.
Enable GZip Compression
A feature that we recently added to Grav was the ability to enable GZip compression for the page. This compresses the HTML file on the server and sends this smaller compressed file to the browser, which means less data transfered, and consequently faster performance.
gzip: true to your
cache: section of your
cache: gzip: true
One thing we were missing in Grav was the expires tag for the rendered pages. We added this (will be available in Grav 0.9.24+) and that expires time is configurable vis the
system.yaml configuration. This is automatically added and defaults to 7 days which is minimum recommended setting.
You can modify this value by providing another
expires: value in the
pages: section of your
The expires tags on the static resources will be set automatically by the CDN and the settings we setup previously will be used to also set these expires dates to 7 days in the future.
One feature of a CDN is that it caches your static resources to ensure that they can be served as quickly as possible. The downside of this however, is that if you change one of these files, the CDN doesn't necessarily know to grab the latest copy, and will still serve the outdated version to users.
You have two options here.
- You can manually clear the CDN cache via the CDN Services's control panel
- You can use a timestamp in the query string of the resource URL to signify unique versions.
In Grav version 0.9.24+, there are two options to enable these timestamps to be automatically added to Assets and Media objects. These settings can be toggle in your
user/config/system.yaml file via:
assets: enable_asset_timestamp: true media: enable_media_timestamp: true
When enabled the URLs will look something like this (notice the
?21e95106 appended to the URL):
<img style="" src="http://cdn.getgrav.org/user/pages/02.blog/state-of-grav-apr2015/grav-themes.png?21e95106">
Ok so now we have completed our fixes let's test again with the same webpagetest.org site and see how we faired:
Wow, That's a great improvement. We have now aced every category and the detailed output tells the true story:
Details: First Byte Time (back-end processing): 100/100 122 ms First Byte Time 126 ms Target First Byte Time Use persistent connections (keep alive): 100/100 Use gzip compression for transferring compressable responses: 100/100 93.3 KB total in compressible text, target size = 93.3 KB - potential savings = 0.0 KB Compress Images: 100/100 108.0 KB total in images, target size = 108.0 KB - potential savings = 0.0 KB Use Progressive JPEGs: 100/100 108.0 KB of a possible 108.0 KB (100%) were from progressive JPEG images Leverage browser caching of static assets: 90/100 FAILED - (No max-age or expires) - http://fonts.googleapis.com/css?family=Montserrat:400|Muli:300,400|Inconsolata WARNING - (2.0 hours) - http://www.google-analytics.com/analytics.js Use a CDN for all static assets: 100/100 CDN's Used: cdn.getgrav.org : NetDNA fonts.googleapis.com : Google fonts.gstatic.com : Google www.google-analytics.com : Google
The only non 100/100 score comes from resources provided by Google CDNs which our outside of our control. Overall a very satisfactory result!
Just a few simple steps and the addition of a good CDN solution were able to propel Grav to a truly world-class performer!
Let us know below if you have any questions.