WARNING: This is an ALPHA release and not feature complete yet.
Flexible caching framework for WPGraphQL v0.9.0 or later
composer require valu/wp-graphql-cache
Or you can clone it from Github to your plugins using the stable branch
cd wp-content/plugins
git clone --branch stable https://github.com/valu-digital/wp-graphql-cache.git
If you want to just start caching all your queries for a given period of time
you can just add this to your theme's functions.php
or to a mu-plugin:
use WPGraphQL\Extensions\Cache\CacheManager;
CacheManager::register_graphql_query_cache([
'query_name' => '*',
'expire' => 120, // sec
]);
or you can target specific queries
use WPGraphQL\Extensions\Cache\CacheManager;
CacheManager::register_graphql_query_cache([
'query_name' => 'MySlowQuery',
'expire' => 120,
]);
Lets say you have a big query fetching various things where most of them are
reasonably fast but one of the is too slow. You can target that individual
root field with register_graphql_field_cache()
.
use WPGraphQL\Extensions\Cache\CacheManager;
CacheManager::register_graphql_field_cache([
'query_name' => 'MyBigQuery',
'field_name' => 'menuItems',
'expire' => 120, // sec
]);
This will start caching the menuItems
root field on a GraphQL query named
MyBigQuery
for 120 seconds.
You can clear all GraphQL caches with CacheManager::clear()
but if you want
to be more specific with cache clearing you must pass in a zone
property to
register_graphql_query_cache
and register_graphql_field_cache
and you can
clear that zone with CacheManager::clear_zone($zone)
.
The zone
is a caching zone the cache will be stored to. Zones are needed
because the cached responses are written to multiple cache keys because graphql
variables and the current user can change between calls to the same query
The zone can be cleared with CacheManager::clear_zone()
/**
* Register cache to a 'menus' zone
*/
CacheManager::register_graphql_field_cache([
'zone' => 'menus', // 👈
'query_name' => 'MyBigQuery',
'field_name' => 'menuItems',
'expire' => 120, // sec
]);
/**
* Clear the zone 'menus' when the menus are updated
*/
add_action('wp_update_nav_menu', function () {
CacheManager::clear_zone('menus');
});
You can also share the same zone between multiple caches.
The zones can be cleared using the WP CLI too
$ wp graphql-cache clear # clear all zones
$ wp graphql-cache clear --zone=menus
WPGraphQL Cache comes with very simple build query performance tool which
adds a x-graphql-duration
header to the /graphql
responses. It contains
the duration of the actual GraphQL response resolving in milliseconds.
When no caches are hit this is the theoretical maximun this plugin can take
of from the response times. Everything else is spend in setting up WP and
WPGraphQL itself before the GraphQL resolver execution.
If you want to go beyond that you can enable GET requests with Persisted Queries in the WPGraphQL Lock plugin and cache the whole response in your edge server (nginx, varnish, CDN etc.). This will be the absolute best performing cache because the PHP interpreter is not invoked at all on cache hit.
There are couple storage backends availables which can be configured using
the graphql_cache_backend
filter.
use WPGraphQL\Extensions\Cache\Backend\FileSystem;
add_filter('graphql_cache_backend', function () {
return new FileSystem( [
'base_directory' => '/custom/path',
'directory_permissions' => '0770',
'file_permissions' => '0660',
] );
});
This is the default backend which writes the cache to
/tmp/wp-graphql-cache
. It not super fast but it can perform reasonably when
backed by a RAM disk.
This is cache storage backend which writes WordPress transients.
This is a flexible cache storage backend as the true storage can be configured at a platform level via the use of the object cache. By default if no object cache is defined WordPress will store transients as options in the database.
For example a single server environment might use a APC object cache where as a HA environment might have a Memcached or Redis backend.
TODO
A custom backend can be also returned as long as it extends from
\WPGraphQL\Extensions\Cache\Backend\AbstractBackend
.