Static Caching

Using the static file cache can bring your page load time down to <100ms, but you can not use escaping or anything that requires ExpressionEngine processing on each request.

It does this by caching the entire HTTP response just before it is sent to the browser.

This response is then built into a PHP template that includes all the code for setting HTTP headers and checking the expiry time.

When using Static caching if the speedy_query_cache_whitelist config value is changed you will need to clear your site cache to ensure new configuration is used.

When using Redis with static enabled if the speedy_query_cache_whitelist config value is changed or connection settings to the Redis server is changed you will need to clear your site cache to ensure new configuration is used. You will also need to delete the index_redis_default_site.php file in the root of your site, then click the prompt below in your control panel to re-generate the index file.

Installation

To enable the static file cache driver:

  • Create a new directory in your document root (where index.php is) named static.

  • Make sure speedy_static_enabled is not disabled in your config.php file.

  • Add the following code to the top of your .htaccess file (or create one if it does not exist).

  • Complete the installation in the Speedy control panel page.

At minimum, your config.php file should have the following for static caching to work:

$config['speedy_driver'] = 'static';

If you are using Redis as a static caching option, you must enable it in Redis driver settings page in the control panel, or add the following to your config.php file:

$config['speedy_redis_settings'] = [
'static' => 'yes',
];

Apache .htaccess rewrite rule:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/system [NC]
RewriteCond %{QUERY_STRING} !ACT|URL [NC]
RewriteCond %{REQUEST_METHOD} !=POST [NC]
RewriteCond $1 !\.(css|js|gif|jpe?g|png) [NC]
RewriteCond %{DOCUMENT_ROOT}/static/default_site/static%{REQUEST_URI}/index\.php -f
RewriteRule ^ /static/default_site/static%{REQUEST_URI}/index\.php [L,QSA]
</IfModule>

If using Nginx:

if ($request_method !~* GET) {
set $request_var nonget;
}
if ($args ~* (ACT|URI)) {
set $uri_var acturl;
}
if (-e $document_root/static/default_site/static/$request_uri$request_var$uri_var/index.php) {
rewrite ^(.*) /static/default_site/static/$request_uri/index.php last;
}

Once static caching is enabled and configured, simply add the following tag to the pages you want to be cached. This tag can be anywhere in your template, and does not need a closing tag pair.

{exp:speedy:static}

{exp:speedy:static} accepts the following parameters:

  • ttl The number of seconds before this cache item with expire. If left blank the default TTL (1 hour) will be used. Use ttl="0" to cache this item until the cache it broken. (Default: "")

  • tags A pipe-separated list of tags to apply to this item. Tags can be used in the cache breaking settings. (Default: "")

  • url_override Override the url used as part of the key for non-global items. (Default: "")

  • url_prefix Add a prefix to the key. Useful for multi-lingual sites, e.g. url_prefix="{publisher:current_language_code}" (Default: "")

    • If using Publisher, and you are not displaying the default language segment in the URL, you may need a conditional similar to url_prefix="{if publisher:current_language_id != publisher:default_language_id}{publisher:current_language_code}{/if}"

Advanced Customization

If you want to customise the path to the static file directory, you can set the speedy_static_path option in your config.php. If you do this, you must update your .htaccess file.

If you are using the MSM module, or have a different site short name for whatever reason you must update your .htaccess file.

Replace STATIC_PATH and SITE_NAME in the following template:

Apache .htaccess rewrite rule:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/system [NC]
RewriteCond %{QUERY_STRING} !ACT|URL [NC]
RewriteCond %{REQUEST_METHOD} !=POST [NC]
RewriteCond $1 !\.(css|js|gif|jpe?g|png) [NC]
RewriteCond %{DOCUMENT_ROOT}/STATIC_PATH/SITE_NAME/static%{REQUEST_URI}/index\.php -f
RewriteRule ^ /STATIC_PATH/SITE_NAME/static%{REQUEST_URI}/index\.php [L,QSA]
</IfModule>

If using Nginx:

if ($request_method !~* GET) {
set $request_var nonget;
}
if ($args ~* (ACT|URI)) {
set $uri_var acturl;
}
if (-e $document_root/STATIC_PATH/SITE_NAME/static/$request_uri$request_var$uri_var/index.php) {
rewrite ^(.*) /STATIC_PATH/SITE_NAME/static/$request_uri/index.php last;
}

Nginx example coming soon.

Query String Caching

Query string caching will only work when using the static driver if the requested page is cached without the query string. For example, if the url /products/shirt?size=small is requested by the user and cached, it will not display the cached contents to any user until /products/shirt is also cached.

Note this is not the case when using the Redis cache driver with static enabled.

If the speedy_query_cache_whitelist config value is defined and contains an array of values, query string caching will be enabled. Speedy will only cache unique pages that contain query strings keys defined in speedy_query_cache_whitelist.

Redis as Static driver

If you are using Redis with static caching, your .htaccess re-write rules will look a little different. The index_redis_default_site.php file will be auto-generated by Speedy during the setup process. If this file does not exist you will be prompted in Speedy's control panel page to generate the file (see screenshot above).

RewriteCond %{REQUEST_URI} !^/admin.php [NC]
RewriteCond %{QUERY_STRING} !ACT|URL [NC]
RewriteCond %{REQUEST_METHOD} !=POST [NC]
RewriteCond %{REQUEST_URI} !^/~ [NC]
RewriteCond $1 !\.(css|js|gif|jpe?g|png) [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}/index_redis_default_site\.php -f
RewriteRule ^(.*)$ index_redis_default_site\.php?%{REQUEST_URI} [L,QSA]

CSRF tokens

When static caching is enabled, the CSRF tokens in forms will be invalid. Each user gets a CSRF token, thus if every user gets the same cached page forms will not submit due to an invalid token. Speedy will update the CSRF token field in any form that is generated by ExpressionEngine. If you are building your own forms, make sure your csrf_token field matches the following format.

<input type="hidden" name="csrf_token" value="[token value]">

A csrf_token field updated by Speedy is wrapped in HTML comments. If you do not see the following comments around your csrf_token fields in cached output, then Speedy did not update the value for the current user.

<!-- CSRF_TOKEN_UPDATED --><input type="hidden" name="csrf_token" value="[token value]"><!-- /CSRF_TOKEN_UPDATED -->