MODX Revolution has a robust cacheing system that allows you to easily control what parts of your content are cached for speed, and what parts are loaded fresh. One of the things that initially gained my interest in MODX, was realizing that by utilizing Chunks and Snippets in your Templates, you can control the caching of your content down to the character. That’s pretty amazing.
While odds are the first several MODX sites you build you may barely even need to think about cacheing (MODX lets you get away with a lot), once your site and user base grows to a certain scale, it’s time to start looking at customizing your cacheing strategy so that it best serves the needs of you and your audience. A few simple optimizations can make a world of difference, so let’s explore some options.
By default, when a MODX Resource is saved, it clears what’s called the “resource cache” to ensure that any updates you’ve made are immediately seen across the site. It also means that many if not all of your pages, will be loaded uncached on the next visit, and will later be cached as and if only you’ve instructed them to.
This means that if content is being published rapidly at a time when the site is under heavy load you may start noticing performance issues like slow page load times. We don’t want that now do we?
MODX is an extremely robust site building tool, and thus there is no one right answer to how you build your website, let alone cache it. This post does not aim to declare exactly how you should approach managing the cacheing of your website, as there are simply too many options and use cases to compare. If anything in fact, it aims to spark a conversation and hear your thoughts and questions.
getCache is a MODX Extra developed by core developer Jason Coward. It’s described as a generic caching snippet for caching the output of any MODX Element. What is does is simple, you wrap a Chunk or Snippet with getCache, it processes the element with the parameters you supply and saves the output to a cache file that lives for as long as you specify.
[[!getCache? &element=`twitterWidget` &cacheExpires=`900` ]]
This would process your Snippet and cache it for 15 minutes. Awesome, so even if your twitterWidget Snippet is doing a bunch of crazy stuff like hitting the Twitter API, it’s only going to be processed every 15 minutes.
Now as is, the output is not going to survive the resource cache being cleared. That means that when your client makes changes to or publishes new resources, this cache is going to need to be reloaded. How do we prevent that?
Surviving Resource Cache
By using the cacheKey parameter we can tell the output to be saved outside of the resource cache. We will use a cacheKey of ‘twitter’ so our output will be cached at core/cache/twitter relative to your MODX Installation.
[[!getCache? &element=`twitterWidget` &cacheExpires=`900` &cacheKey=`twitter` ]]
Managing the Cache
What if we have another element that we want to be loaded fresh every so often. Maybe it’s a Chunk, that can live for an indefinite amount of time.
[[!getCache? &element=`new-posts` &elementClass=`modChunk` &cacheExpires=`0` &cacheKey=`news` ]]
Great, that will live forever. But as we learned above, it’s not going to be cleared when Resources are updated, nor is it going to be cleared on Site > Clear Cache. Luckily as of getCache 1.1.0, we can easily create a custom menu item to clear our custom cache area. Create as many as needed!
It’s also possible to put together a simple MODX Plugin that listens to different manager actions and intuitively clears application caches, but that’s outside the scope of this post. Maybe another ;).
Sharing the Cache
You may have already realized practical applications for your next project but before you head to the pub for the night, we need to talk. This twitterWidget Snippet, does it always return the same content, regardless of which resource it’s being called from? If so, we aren’t done yet. With utilizing one more getCache parameter, we are going to share this cache across multiple resource, rather than per resource. Especially if you have a large number of resources, cleverly sharing the cache where possible can have a dramatic affect on front end performance and the amount of time it takes MODX to regenerate the cache.
[!getCache? &element=`twitterWidget` &elementClass=`modSnippet` &cacheExpires=`900` &cacheKey=`twitter` &cacheElementKey=`twitterWidget` ]]
In this case we are using cacheElementKey to cache our output globally, as twitterWidget is always returning the same thing. If we needed to support multiple variations of output, we simply use multiple cacheElementKeys like so:
[!getCache? &element=`twitterWidget` &handle=`jpdevries` &elementClass=`modSnippet` &cacheExpires=`900` &cacheKey=`twitter` &cacheElementKey=`twitterWidget-jpdevries` ]] [!getCache? &element=`twitterWidget` &handle=`modxpdx` &elementClass=`modSnippet` &cacheExpires=`900` &cacheKey=`twitter` &cacheElementKey=`twitterWidget-modxpdx` ]]
So now this cache both survives the resource cache, can be cleared from a custom menu item, can support multiple configurations, and is shared throughout the site. Rather than having to be loaded per resource we are now only processing these elements when needed. Make sure to view getCache’s the full properties list as there are even more configurations available for you to utilize on your next site build.
xFPC is a recently released yet thoroughly documented MODX Add-on that, among other things, adds the ability to easily retrieve sections of your content after the pages has loaded using AJAX. While getCache works on an element level, xFPC actually caches full pages. Maybe we have a section of a page that is heavy in markup, potentially desirable to the user, but not needed immediately as it’s not the primary content of the page. For example, let’s say we are working on an Archives table that lists hundreds of past items. Let’s say this table is being generated by an archives-table Chunk that’s already been written.
We’ll use xFPC to remove this Archive table from the initial page, but immediately fetch it using AJAX. To implement xFPC, create a new Resource that will output nothing more than our Archives Table. We should probably set the resource to not be Rich Text, Hidden from Menu and make sure it’s published of course. Paste your [[$archives-table]] Chunk in the content of the resource and save it. Let’s say the resource has an id of 300.
[[xFPCAjax? &resource=`300` ]]
statCache is a MODX Add-on that is powered by a clever plugin that removes the ability for your pages to be dynamic but also bypasses PHP completely.
The statcache Add-on is made up of a Plugin for MODX Revolution that writes out static representations of fully cacheable MODX Resources to a configurable location on the filesystem. You can then use your web server’s rewrite engine (or equivalent) to serve the static files first, if they exist. This has the advantage of bypassing MODX (and PHP) entirely, allowing you to serve potentially thousands of more requests per second. It has the disadvantage of not allowing any dynamic content to be served.
— StatCache Documentation
As if he hadn’t been instrumentally enough in defining the options you have available to cache your MODX website, Jason Coward recently released a simple script that will cache Resources marked as cacheable throughout your entire website, even multiple Contexts. It’s meant to be run outside of MODX (say hooked up to a CRON job). One tip, put it in a non-web accessible location on your server and make sure to set an absolute path to your MODX core. Then sit back, and watch your website cache itself.