Server Cache Helper by WPHercules

We have been working on a small plugin that we think is going to make a huge difference for our clients and I hope it will also help others that are using server cache solutions to speed up their WordPress websites.

TL;DR

It is called WPH Server Cache Helper and it detects automatically the pages that should skip cache on your WordPress and notify the server so those pages are excluded on your server cache solution.

With this plugin installed you won’t need to manually exclude pages any more.

Server Cache vs Plugin Cache

If you do not know about how cache works, this post explain it better than I could. I recommend to read that before to read this post.

There are two main ways to cache a page or post in WordPress. The standard and simple way is to use a plugin. The plugin will create the static version of your page and it will check if the content is cached or not before to show it, avoiding the load of the page and saving your server resources.

But this system still needs to load the plugin to work, so it is still loading part of the WordPress with each visit. There is another way to do this, and it is called “Server Cache”. The principle is the same, create a static version of the page and show it instead of loading. The difference is that with server cache, you do not load the WordPress or any PHP at all, so you save more resources and it load faster.

If you know how the cache works and if you have been following the latest news of the “website performance world“, you may have noticed that server cache is the best solution chosen by the top WordPress hostings for deliver the best performance for your WordPress website.

Cache plugins still have some advantages to the server cache solutions. Some cache plugins provide extra optimizations and other features that can improve the performance of your website. But most of those features can be replaced by other non-cache plugins, and with some of them, you can have those options activated and tell the plugin to use your server cache at the same time (with some extra configurations like this one from wp-rocket).

The problem

But there is one feature that is not easy to replace and it has been a big issue for us when we are providing server page cache to our clients.

The biggest feature that is not easy to do with server cache is the the exclusions of pages and content from cache.

When working with server cache, the server configuration is the one that needs to take care of the exclusions. All of the providers will exclude by default the most common pages, like login, wp-admin folder, e-commerce carts, checkouts and some others, but to have your custom page to be excluded is not that easy.

Most of the providers will use different solutions to deal with this problem. Some providers will force you to install a plugin that connect with their cache systems to setup the exclusions (Runcloud Hub or Spinupwp), others require you to contact their support team to exclude any pages (Kinsta, WPEngine and others), and some of them will provide instructions on how you can manually edit the configuration files on the server (Runcloud and Gridpane) to exclude your custom URLs.

In a perfect world, this should be enough. All WordPress sites should have the same exclusion pages and every cache system will work with those.

But in real life, every website is different and some clients will change the most common urls, like the cart or the my account page. For example, you can decide that the cart url is better named your_cart or that checkout could be on the url payment instead, or maybe you are not using WooCommerce and you use EDD for your online shop.

You may think this problem is not that common, and that is true on most English websites, but when you consider that the rest of the world that does not speak English do not use the words cart or *checkout*, then you can see why this is more frequent.

And we need to remember that non English WordPress are more than 50% of the WordPress installations in the world, so it is not a small market after all.

So for all those WordPress sites that are not in English (or for any English one that want to customise their urls), setting up a server cache is a little nightmare and it means to talk with the hosting support team for any change we want to make to those urls. And this is of course considering that the user will know that there is a problem changing the urls and that they should notify the provider. Most WordPress users won´t even realise that they need to do anything at all.

Why this is not a a problem for WP Cache plugins?

So the client change the urls, why this is not a problem for them when they use Cache Plugins?

The main reason is that the client has the power to exclude pages within the plugin configuration. No need to call or contact any support team, so it is a much easier and quick solution for them, but there is more.

There is another reason this is not a big deal with (some) cache plugins. And it is because to a constant named DONOTCACHEPAGE.

When you have a page or a post that needs to be excluded from cache, you can pass that constant within your code to indicate that to the WordPress cache plugins. Those constants are set-up by all the well constructed plugins and also most of the Cache plugins will check for them and skip cache automatically when they are set (some examples from wp-rocket and cache enabler plugins).

In our example, the cart and the checkout pages from WooCommerce include this constant since version 1.4.2, so if you change your cart url on your WooCommerce settings, you won’t need to do anything else, as the cache plugins (the good ones at least) will see the constant and skip the cache there, with no interaction or updates required from the users.

Our solution

At WPHercules, 50% of our clients speak “non-english” languages (mostly Spanish to be fair), so we have been working hard to find a solution to this problem. We want to offer out clients the best performance using Server Cache, but without the issues for them and the overhead to our support system that this set up generates.

After working on it for a while, we have created a really simple plugin that, when installed on your WordPress site, will convert the constant DONOTCACHEPAGE into a different set of rules that will tell your server to skip the cache, the same way the cache plugins automatically do.

So with this plugin installed, it will check the pages before to load them, and if the constant is set, it will tell the server to bypass the cache and load the page completely.

We are providing this plugin to all our clients but we are also providing it for free to anyone that wants to use it.

So you can find the code on this Github repository and you can get the latest version on a zip file from this direct link.

Server level configuration required

Before you go and install it, make sure you understand how it works and how to set it up.

This plugin will only work with a custom configuration on our server. The server needs to know that if the header is there, then that page should not be cached.

Please read the instructions before to activate the plugin.

If you are using a provider like Runcloud , you may need to customise the cache configuration to make this work.

How it works?

The process is simple. Before to load a page on WordPress, we check if that post or page has this constant. If it has been defined then we create a “secret/special” header that will tell the server to bypass and more important, to not store the cache on this particular page.

We use the header wph-no-cache, so you can setup your server to bypass cache. We have also added special configuration for the most known providers.

The header is set on WordPress when we detect the constant and it is checked by the server and that makes it skip the cache storage.

We also set other headers like Cache-Control and Expires, and we also setup a cookie, but we explain below why this was not enough.

Why do not you use queries, cookies, urls or other tools already predefined by the providers?

All providers already have their own set of exclusion rules, and the most common ones include urls, cookies and queries, but this was not working for us, this is why:

We starting using cookies, as this is the easy way to tell the server cache to bypass a page and all providers are already using a cookie to bypass cache (the login cookie for example). But the cookies alone are not a solution and they do not work as expected.

When you are setting up the cookie at the PHP level, it is too late to tell the server not to store the cache. So the cookie is set, but the cache is stored as well at the same time.
That means the if the user removes the cookie, or worse, if any other user visit the same URL after it has been stored, then that new user will be shown the stored cache version of the page. And we cannot even put the cookie then, because the PHP of WordPress (and our plugin) does not even run.

We could also use queries to prevent cache, as again most providers will exclude pages with queries, and that could work, but for doing this we will need to redirect all request to a new url with that especial no-cache query. This will duplicate the number or requests on the server for those pages, and that of course will have an impact on the server performance, which is the whole opposite of what we are trying to achieve here, so we decided not to do this and keep looking.

The url exclusion, as explained above, means that you need to edit the exclusion rules manually with any change on them, so not really a solution to the problem.

Then there are other headers which are meant to be used to prevent cache: Cache-control headers, Expires and Pragma.

  • Pragma is ignored by nginx, which is the most common server now. We are setting it on our plugin, just in case, but we never expected it to work.
  • Expires and Cache-Control will help with the browser cache, and therefore we also setup them on our plugin. But again, it is common for Nginx server cache to ignore those two headers, so this won’t work with most cache solutions based on Nginx servers .

So we needed something different and we decided to use that secret header that together with a small configuration on your server, it will work nicely.

Future

For now we wanted to launch it so other people can benefit from that as soon as possible.
We plan to add more providers (we will contact them to see if they are interested) first, so it requires less configuration from the users to work.

Then we might add some performance features, but we want to keep it simple and easy to use.
We have some ideas already written down on the Readme. Please open an issue with any feature request you may have.

Please leave any comments on the github or contact us using our Twitter or contact form.

References and inspiration

We got some inspiration and get some code from the following sources (this is also on the Readme of the plugin here).

We have used some code from the plugin https://wordpress.org/plugins/slim-maintenance-mode/ by Johannes @wpdocde
and also from https://wordpress.org/plugins/fresh-forms-for-gravity/ by Samuel Aguilera @samuelaguilera

Thank you specially to the Gridpane support team for helping me during my tests and for giving me the last hint to crack this.

Other links and texts to read that I have used (some are more interesting than others):

Thank you very much all for your help. We hope you find the plugin useful.