Blitz Logo Blitz

Intelligent static page caching for lightning-fast sites.

Blitz makes your site fly and feel light-weight and instantaneous to navigate.

Your site remains available even when performing updates and maintenance.

Your entire site can be served statically from a CDN such as Cloudflare or Netlify Edge.

Blitz provides intelligent static page caching for creating lightning-fast sites with Craft CMS. It significantly improves a site’s performance by reducing server response time.

Server response time

Performance gains depend on the individual server setup, however the results above are not uncommon. Google recommends a server response time of 200ms or less.

Read the Blitz 3 announcement here.

Features #

Speed
Blitz makes your site fly. By serving cached pages, load times are reduced to the absolute minimum, making your site feel light-weight and instantaneous to navigate.

Guess what? This site is powered by Blitz, so you can experience first-hand exactly how fast it really is :)

Stability
Because your site’s pages are statically cached, the site remains available even when performing Craft updates and maintenance.

Cost Saving
Your web server no longer has to spin up PHP and render templates on each request. Statically cached pages can be served from a reverse proxy CDN such as Cloudflare or from a static host such as Netlify, meaning that you can deliver high performance sites using much more inexpensive servers.

Predictability
Cache invalidation happens automatically in the background as content is edited, making for a seamless author experience. The plugin is a breeze to set up, very configurable and thoroughly tested.

Extensibility
Blitz comes with built in cache storage, cache warmers, reverse proxy purgers and deployers. Bring your own drivers for full control and customisation.

We love a good visualisation to help explain a concept, so below is a high-level overview of how Blitz works in its various configurations.

Visualisation

License #

This plugin requires a commercial license purchasable through the Craft Plugin Store. The license fee is $99 plus $49 per subsequent year for updates (optional).

Requirements #

This plugin requires Craft CMS 3.2.1 or later.

Basic Usage #

Getting Started #

To install the plugin, search for Blitz” in the Craft Plugin Store, or install manually using composer.

composer require putyourlightson/craft-blitz

Blitz will not make any changes to your site when first installed. To start caching pages, follow the 3 steps on the welcome screen.

  1. Enable caching.
  2. Add at least one included URI pattern, for example .* to cache the entire site.
  3. Save the settings and your site pages will automatically be cached when visited. If you like, you can warm the entire cache using the Blitz Cache Utility.

Welcome screen

That’s it! You should notice an immediate difference once Blitz is caching your pages. There are a few more optional steps you can take to cut even more time off that time-to-first-byte!

If you are using Blitz File Storage” as the cache storage type (recommended), you can add Apache or Nginx server rewrites to avoid PHP processing for even better performance.

You can reduce the likelihood of visitors hitting pages with expired entries (or entries with future post dates) by creating a cron job to refresh expired cache automatically on a scheduled interval.

Craft’s {% cache %} tag doesn’t always play well with Blitz cache invalidation. Since template caching becomes redundant with full page caching, it is best to remove {% cache %} tags from templates Blitz caches, or simply disable template caching from config/general.php:

'enableTemplateCaching' => false,

If anything does not work as expected then take a look at the common issues.

How It Works #

When a page is visited that matches an included URI pattern, Blitz will serve a cached version of the page if it has one. Otherwise, it will display and cache the template output. Excluded URI patterns will override any matching included URI patterns.

When an element is created, updated or deleted, any cached pages that used that element are cleared. If a reverse proxy purger such a Cloudflare is selected, the pages are purged. If the Warm Cache Automatically” setting is enabled, a job is queued to warm the cleared cache. If a remote deployer is selected then the warmed pages will be deployed to the remote location.

Blitz is compatible with Craft’s Live Preview. It will detect when it is being used and not cache its output or display cached content.

If a Global is saved, Blitz will refresh the entire site cache if Clear Cache Automatically” is enabled and the refreshCacheAutomaticallyForGlobals config setting has not been set to false. This is because Globals are available on every page of every site and can potentially affect every single cached page. Globals should be used sparingly and only in situations where the global value needs to be accessible from multiple pages. For anything else, consider using Entries or Categories rather than Globals.

Cache Utility #

The Blitz cache utility at Utilities → Blitz Cache displays the number of cached URIs for each site (for Blitz File Storage only). It also provides the following functionality.

Clear Cache #

Clearing the cache will delete all cached pages.

Flush Cache #

Flushing the cache will delete all records from the database.

Purge Cache #

Purging the cache will delete all cached pages in the reverse proxy.

Warm Cache #

Warming the cache will create a queue job to warm all of the pages by visiting each of them.

Deploy to Remote #

Deploying to remote will create a queue job to deploy all cached files to the remote location. If you want to ensure that every cacheable page is deployed then you should warm the cache first.

Refresh Cache #

Refreshing the cache will clear, flush, purge, warm and deploy all of the pages.

Refresh Expired Cache #

Refreshing expired cache will refresh all cached pages that have expired, or that contain elements that have expired (applies to elements with future post and expiry dates). Cache duration and expiry dates can be specified in the config settings and the page specific options.

Refresh Cached URLs #

Refreshing cached URLs will refresh all cached pages with the provided URLs.

Refresh Tagged Cache #

Refreshing tagged cache will refresh all cached pages that were associated with the provided tags using the tags parameter in the page specific options.

Utility

Console Commands #

Every cache utility function above is also available as a console command.

./craft blitz/cache/clear

./craft blitz/cache/flush

./craft blitz/cache/purge

./craft blitz/cache/warm

./craft blitz/cache/deploy

./craft blitz/cache/refresh

./craft blitz/cache/refresh-expired

./craft blitz/cache/refresh-urls http://domain.com/page

./craft blitz/cache/refresh-tagged tag1,tag2,tag3

Console commands

A console command also exists that generates entry expiry dates and stores them to enable refreshing expired cache. This happens automatically when entries are saved but this command allows sites to manually generate expiry dates for all of their entries. 

./craft blitz/cache/generate-expiry-dates

Refreshing Cache via URL #

Once you have created an API key in Settings → Advanced, you can trigger each of the cache utilities through a URL. Those URLs are displayed under the API key field after the setting has been saved.

API key

Settings #

Control Panel Settings #

Caching Enabled #

With this setting enabled, Blitz will begin caching pages according to the included/​excluded URI patterns. Disable this setting to prevent Blitz from caching any new pages.

Included/​Excluded URI Patterns #

The URI patterns to include or exclude when caching. Blitz will only cache pages whose URI matches the URI patterns, giving you fine-grain control over what is cached.

URI patterns use PCRE regular expressions (cheat sheet). Below are some common use cases.

PatternDescription
A blank field matches the homepage.
.Matches any character.
.*Matches any character 0 or more times.
.+Matches any character 1 or more times.
\dMatches any digit.
\d{4}Matches any four digits.
\wMatches any word character.
\w+Matches any word character 1 or more times.
entriesMatches anything containing entries.
^entriesMatches anything beginning with entries.
^entries/entry$Matches the exact URI entries/entry.

Settings General

Cache Storage #

The storage type to use for storing cached pages. The default and recommended storage type for most sites is Blitz File Storage”. This stores cached pages as static HTML files in the specified Folder Path” and is extremely performant, especially when used with server rewrites.

With the Create Gzip Files” setting enabled, Blitz will compress cached files using gzip and write them to index.html.gz files for improved performance (requires extra code in server rewrites). Note that this will only impact direct requests to your web server so if using Cloudflare or another CDN, this won’t make much of a difference.

A Yii Cache Storage” type is also available and will use whatever cache component Craft is set up to use. You can configure Craft to use alternative cache storage (Memcache, Redis, etc.) by overriding the cache application component from config/app.php as explained in the Craft docs. This is the recommended storage type for multi-node cloud platforms like Docker, Heroku and fortrabbit.

You can extend Blitz to add your own custom cache storage types.

Settings Storage

Cache Warming #

To warm, or not to warm, that is the question:
Whether tis nobler in the mind to suffer
The organic warming of a cold cache,
Or to take arms against a sea of CMS requests,
And by preemptive cache warming, end them.

The cache warmer to use for warming the cache. The default cache warmer is the Guzzle Warmer”. This warms the cache by sending HTTP requests to the cacheable pages on the site as if an anonymous visitor was requesting them, therefore the site must be publicly accessible for this warmer to work.

A Local Warmer” is also available for situations in which the site is not publicly accessible. This warms the cache by mocking requests and having Craft handle them without making any external requests. While it can be used within closed intranets and works very efficiently, it is not as reflective of real-world web requests and should therefore be used with caution.

You can extend Blitz to add your own custom cache warmers.

Reverse Proxy Purging #

A purger to use for clearing cache in a reverse proxy. This allows you to use a reverse proxy cache service and CDN such as Cloudflare to deliver cached pages. Selecting a purger will tell Blitz to automatically purge the appropriate pages whenever they are updated.

You can extend Blitz to add your own custom reverse proxy purgers.

Settings Purger

Cloudflare does not cache HTML by default. To enable static page caching, first set Browser Cache TTL” to Respect Existing Headers” in the Caching” page of the domain in your account. Then create a new page rule in the Page Rules” page (you get 3 page rules with a free plan). Enter a URL pattern such as domain.com/* and add a Cache Level” setting with a value of Cache Everything”. Click Save and Deploy” and then visit your site. With dev tools open you should see a cache response (HIT, MISS, etc.) in the CF-Cache-Status header.

Cloudflare Page Rule

The Dr. Flare Chrome extension provides a helpful visual representation of if and how your site is being cached by Cloudflare.

Dr. Flare Chrome extension

Remote Deployment #

A deployer allows you to deploy cached files to a remote location such as a Git repository. This allows you to use a static host to deliver all (or part of) your site’s pages. Selecting a deployer will tell Blitz to automatically deploy the appropriate pages once they have been warmed.

Read the article Deploying a Craft site to Netlify with Blitz 3 for instructions on how to set up Craft CMS to automatically deploy to Netlify Edge.

You can extend Blitz to add your own custom remote deployers.

Advanced Settings #

Clear Cache Automatically #

Whether the cache should automatically be cleared after elements are updated. With this setting disabled, Blitz will mark affected page caches as expired without actually deleting them. In order to delete them, the Refresh Expired Cache” utility or console command should be used. Disabling this setting may make sense if your site gets heavy traffic and clearing the cache should be limited to specific times or intervals.

Warm Cache Automatically #

Whether the cache should automatically be warmed after clearing. With this setting enabled, Blitz will create a queue job to automatically visit pages whose cache has been cleared in the background. Disabling this setting may make sense if your site is very large and has many related elements.

Query String Caching #

URLs with query strings will be cached according to the selected option in the Query String Caching” setting as follows:

Do not cache URLs with query strings #

URLs with query strings (anything following a ? in a URL) will not be cached. Use this if query parameters dynamically affect a page’s output and should therefore never be cached.

Cache URLs with query strings as unique pages #

URLs with query strings will be cached as unique pages, so domain.com/about, domain.com/about?utm_source=twitter and domain.com/about?utm_source=facebook will be cached separately. Use when query parameters affect a page’s output in a deterministic way and can therefore be cached as unique pages.

Cache URLs with query strings as the same page #

URLs with query strings will be cached as the same page, so domain.com/about, domain.com/about?utm_source=twitter and domain.com/about?utm_source=facebook will all be cached with the same output. Use when query parameters do not affect a page’s output and can therefore be cached as the same page.

API Key #

An API key that can be used to clear, flush, warm, or refresh cache through a URL (min. 16 characters). The individual URLs are displayed below the field after a value has been saved.

Settings Advanced

Config Settings #

Blitz comes with a config file for a multi-environment way to set the plugin settings, as well as more advanced plugin configuration settings. To use it, copy the config.php to your project’s main config directory as blitz.php and uncomment any settings you wish to change. All of the available settings are listed and documented in the config file.

Advanced Usage #

Dynamic Content #

When a page is cached, the cached version of that page will be served up on all subsequent requests. You should therefore avoid caching pages whose entire content changes per individual request. The easiest way to do this is to add excluded URI patterns for such pages. 

Blitz offers a workaround for injecting dynamic content into a cached page using a JavaScript XHR (AJAX) request. The following template tags are available for doing so.

A limitation of injecting the result of an AJAX request into HTML is that any script tags will not be executed. This may have adverse effects on injected content that includes and requires JavaScript code to be run.

{{ craft.blitz.getUri('/page/name', params) }} #

Returns a script that injects the contents of the URI provided in place of the twig tag, optionally passing parameters to the query string. 

{# Basic usage #}
{{ craft.blitz.getUri('/page/name') }}

{# Using the tag with parameters #}
{{ craft.blitz.getUri('/page/name', { 
    param1: 'value1', 
    param2: 'value2' 
}) }}

{# Using the tag to request a controller action #}
{{ craft.blitz.getUri('/actions/snaptcha/field/get-field') }}

{# Accessing the parameters in the requested template #}
Param1: {{ craft.app.request.getParam('param1') }}
Param2: {{ craft.app.request.getParam('param2') }}

{{ craft.blitz.getTemplate('template/name', params) }} #

Returns a script that injects the contents of a template in place of the twig tag, optionally passing parameters to the template. 

{# Basic usage #}
{{ craft.blitz.getTemplate('/template/name') }}

{# Using the tag with parameters #}
{{ craft.blitz.getTemplate('/template/name', { param1: 'value1', param2: 'value2' }) }}

{# The parameters will be available in the requested template #}
Param1: {{ param1 }}
Param2: {{ param2 }}

{{ craft.blitz.csrfInput() }} #

Returns a script that injects a CSRF input field in place of the twig tag. 

Below is an example of how you might use the tags to create a page containing dynamic content and a form page that can be cached by Blitz.

Your cart: {{ craft.blitz.getUri('/ajax/cart-items') }}

<form method="post">
   {{ craft.blitz.csrfInput() }}
   ...
 
 </form>

{{ craft.blitz.csrfParam() }} #

Returns a script that injects the CSRF param in place of the twig tag. 

{{ craft.blitz.csrfToken() }} #

Returns a script that injects a CSRF token in place of the twig tag. 

JavaScript Events #

Whenever you use one of the tags above, the following JavaScript events become available for more fine-grained control.

// The `beforeBlitzInjectAll` event is triggered before any dynamic content is fetched
document.addEventListener('beforeBlitzInjectAll', function (event) {
    // The event can be cancelled with the following line
    event.preventDefault();
});

// The `beforeBlitzInject` event is triggered before each dynamic content tag is fetched
document.addEventListener('beforeBlitzInject', function (event) {
    // The event can be cancelled with the following line
    event.preventDefault();
});

// The `afterBlitzInject` event is triggered after each dynamic content tag is injected
document.addEventListener('afterBlitzInject', function (event) { });

// The `afterBlitzInjectAll` event is triggered after all dynamic content tag is injected
document.addEventListener('afterBlitzInjectAll', function (event) { });

CSRF Controller Actions #

The controller action blitz/csrf/input can be used to fetch an input field dynamically using AJAX, for example. The blitz/csrf/param and blitz/csrf/token controller actions are also available for fetching the CSRF param and a token respectively.

// Gets a CSRF input field
fetch('/actions/blitz/csrf/input')
    .then(result => { return result.text(); })
    .then(result => { console.log(result); });
    // Returns <input type="hidden" name="CRAFT_CSRF_TOKEN" value="t-xHRdO6WOsd4tYG1qvLIF4E_9SHlMs912YbvkjESTmhwa">
    
// Gets the CSRF param
fetch('/actions/blitz/csrf/param')
    .then(result => { return result.text(); })
    .then(result => { console.log(result); });
    // Returns CRAFT_CSRF_TOKEN
    
// Gets a CSRF token
fetch('/actions/blitz/csrf/token')
    .then(result => { return result.text(); })
    .then(result => { console.log(result); });
    // Returns t-xHRdO6WOsd4tYG1qvLIF4E_9SHlMs912YbvkjESTmhwa

Page Specific Options #

It is possible to set page specific caching options in your twig templates by passing an object into the craft.blitz.options() function. All parameters are optional.

{% do craft.blitz.options({
    cachingEnabled: true,
    cacheElements: true,
    cacheElementQueries: true,
    cacheDuration: 'P1D',
    expiryDate: entry.eventDate,
    tags: ['home', 'listing']
}) %}

An alternative notation is to use method chaining on the model that the craft.blitz.options function returns.

{% do craft.blitz.options.cacheDuration('P1D').tags(['home', 'listing']) %}

Because Blitz caches elements and element queries in the same order that twig templates are parsed, you can change the options at various places in your templates.

{# Disable page options #}
{% do craft.blitz.options.cacheElements(false).cacheElementQueries(false) %}

{# Output global navigation #}
{% for entry in craft.entries.section('navigation').all() %}
    <a href="{{ entry.url }}">{{ entry.title }}</a>
{% endfor %}

{# Re-enable page options #}
{% do craft.blitz.options.cacheElements(true).cacheElementQueries(true) %}

cachingEnabled #

Setting this option to false will disable caching of the page.

cacheElements #

Setting this option to false will disable caching the elements used on this page in the database. This is used for cache invalidation of pages when elements used on those pages are updated or deleted.

cacheElementQueries #

Setting this option to false will disable caching the element queries used on this page in the database. This is used for cache invalidation of pages when new elements are added that should appear on those pages.

cacheDuration #

The amount of time after which the cache should expire. If set to 0 then the cache will not get an expiry date. See ConfigHelper::durationInSeconds() for a list of supported value types. Duration intervals are a convenient way to set durations. Common examples include:

  • PT1H (1 hour)
  • P1D (1 day)
  • P1W (1 week)
  • P1M (1 month)

expiryDate #

A DateTime object that will define when the cache should expire. The Refresh Expired Cache” utility or console command must be used to invalidate expired cache. 

tags #

One or more tags (array or string separated by commas) that will be associated with this page. Tags should not contain spaces. The Refresh Tagged Cache” utility or console command can be used to invalidate tagged cache.

Source Tags #

You can tag pages using source tags in the format sourceIdAttribute:sourceId or sourceIdAttribute:* as a wildcard. 

{# Tags the page with section ID 3. Any time an entry in that section is
   created, updated or deleted, the cached page will be refreshed. #}
     
{% do craft.blitz.options.tags('sectionId:3') %}

Then, any time an element in that source is created, updated or deleted, appropriately tagged pages will be cleared. This is especially useful if you have set the cacheElements or cacheElementQueries config settings to false, or if you have a unique scenario in which cached pages should be refreshed (such as very large or complex sites, see this related issue).

Blitz supports the following element source ID attributes:

  • sectionId (entries)
  • groupId (categories)
  • groupId (tags)
  • typeId (Commerce products)
  • campaignTypeId (Campaign campaigns)
  • mailingListTypeId (Campaign mailing lists)

You can add your own source ID attributes using the sourceIdAttributes config setting.

Cron Jobs #

Create cron jobs using the following console commands to refresh expired or tagged cache on a scheduled interval. If entries are generally posted or expire on the hour then a good schedule might be every hour at 5 minutes past the hour. Change /usr/bin/php to the PHP path (if different).

Entering which php in the console will give you the full path to PHP in most environments.

// Refresh expired cache every hour at 5 minutes past the hour.
5 * * * * /usr/bin/php /path/to/craft blitz/cache/refresh-expired

// Refresh cache tagged with the tags “home” and “listing” every day at 6am.
0 6 * * * /usr/bin/php /path/to/craft blitz/cache/refresh-tagged home,listing

Server Rewrites #

For improved performance when using the Blitz File Storage” type, adding a server rewrite will avoid the request from ever being processed by Craft once it has been cached. This leads to extremely performant loading of cached pages.

Apache #

In Apache this is achieved with mod_rewrite by adding a rewrite rule to the virtual host .conf file (this article explains how), or the root .htaccess file if you must, just before the rewrites provided by Craft. 

Change cache/blitz to the cache folder path designated in the plugin settings (if different).

If the Query String Caching” setting is set to Do not cache URLs with query strings or Cache URLs with query strings as unique pages then use the following code.

#- Blitz cache rewrite
RewriteCond %{DOCUMENT_ROOT}/cache/blitz/%{HTTP_HOST}/%{REQUEST_URI}/%{QUERY_STRING}/index.html -s
RewriteCond %{REQUEST_METHOD} GET
RewriteCond %{QUERY_STRING} !token= [NC]
RewriteRule .* /cache/blitz/%{HTTP_HOST}/%{REQUEST_URI}/%{QUERY_STRING}/index.html [L]

#- Send would-be 404 requests to Craft

If the Query String Caching” setting is set to Cache URLs with query strings as the same page then the /%{QUERY_STRING} segment should be removed.

#- Blitz cache rewrite
RewriteCond %{DOCUMENT_ROOT}/cache/blitz/%{HTTP_HOST}/%{REQUEST_URI}/index.html -s
RewriteCond %{REQUEST_METHOD} GET
RewriteCond %{QUERY_STRING} !token= [NC]
RewriteRule .* /cache/blitz/%{HTTP_HOST}/%{REQUEST_URI}/index.html [L]

#- Send would-be 404 requests to Craft

If you are using the Blitz File Storage” and have the Create Gzip Files” setting enabled then adding the following before the Blitz cache rewrite will serve gzip files if they exist.

#- Blitz cache rewrite for gzip files
RewriteCond %{DOCUMENT_ROOT}/cache/blitz/%{HTTP_HOST}/%{REQUEST_URI}/%{QUERY_STRING}/index.html.gz -s
RewriteCond %{HTTP:Accept-encoding} gzip
RewriteCond %{REQUEST_METHOD} GET
RewriteCond %{QUERY_STRING} !token= [NC]
RewriteRule .* /cache/blitz/%{HTTP_HOST}/%{REQUEST_URI}/%{QUERY_STRING}/index.html.gz [L]

#- AddEncoding allows you to have certain browsers uncompress information on the fly.
AddEncoding gzip .gz

#- Serve correct content types, and prevent mod_deflate double gzip.
RewriteRule \.html\.gz$ - [T=text/html,E=no-gzip:1]

#- Blitz cache rewrite

Nginx #

In Nginx this is achieved by adding a location handler to the configuration file. 

Change cache/blitz to the cache folder path designated in the plugin settings (if different).

If the Query String Caching” setting is set to Do not cache URLs with query strings or Cache URLs with query strings as unique pages then use the following code.

#- Blitz cache rewrite
set $cache_path false;
if ($request_method = GET) {
    set $cache_path /cache/blitz/$host/$uri/$args/index.html;
}
if ($args ~ "token=") {
    set $cache_path false;
}

#- Send would-be 404 requests to the cache path or Craft
location / {
    try_files $cache_path $uri $uri/ /index.php?$query_string;
}

If the Query String Caching” setting is set to Cache URLs with query strings as the same page then the /$args segment should be removed.

#- Blitz cache rewrite
set $cache_path false;
if ($request_method = GET) {
    set $cache_path /cache/blitz/$host/$uri/index.html;
}
if ($args ~ "token=") {
    set $cache_path false;
}

#- Send would-be 404 requests to the cache path or Craft
location / {
    try_files $cache_path $uri $uri/ /index.php?$query_string;
}

If you are using the Blitz File Storage” and have the Create Gzip Files” setting enabled then adding the following before the Blitz cache rewrite will serve gzip files if they exist.

#- Enable serving of static gzip files as per: http://nginx.org/en/docs/http/ngx_http_gzip_static_module.html
gzip_static on;

#- Blitz cache rewrite

Debugging #

Cached HTML pages are timestamped with a comment at the end of the page, unless the outputComments config setting is set to false.

<!-- Cached by Blitz on 2019-06-15T21:00:00+02:00 -->

If the HTML was served by the plugin rather than with a server rewrite then an additional comment is added.

<!-- Served by Blitz on 2019-06-15T21:00:00+02:00 -->

Note that if your HTML is minified then all comments will be removed from the markup, including the comments above.

If the HTML was served by the plugin and the sendPoweredByHeader config setting is not set to false then an X-Powered-By: Blitz header will be sent.

Logs are written to storage/logs/blitz.log. A debug config setting exists that can be enabled to help troubleshoot why pages are not being cached. 

return [
    'debug' => true,
];

If pages are not being cached as expected then take a look at the common issues.

Extending Blitz #

Cache Storage Types #

In addition to the provided cache storage types, you can write your own by extending the BaseCacheStorage abstract class. See the implementation of the putyourlightson\blitz\drivers\storage\FileStorage class.

<?php
namespace vendor\package;

use putyourlightson\blitz\drivers\storage\BaseCacheStorage;

class MyCacheStorage extends BaseCacheStorage
{
    // Override base methods
}

To add your cache storage type to Blitz, you can create a stand-alone composer package for it. Install the package with composer require and then add the class to the cacheStorageTypes config setting in config/blitz.php.

// The storage type classes to add to the plugin’s default storage types.
'cacheStorageTypes' => [
    'vendor\package\MyCacheStorage'
],

If you prefer to write your cache storage type as a module or plugin, then register it by listening for the EVENT_REGISTER_STORAGE_TYPES event and adding the class to the $event->types array.

use craft\events\RegisterComponentTypesEvent;
use putyourlightson\blitz\helpers\CacheStorageHelper;
use vendor\package\drivers\storage\MyCacheStorage;
use yii\base\Event;

Event::on(CacheStorageHelper::class, 
     CacheStorageHelper::EVENT_REGISTER_STORAGE_TYPES,
     function(RegisterComponentTypesEvent $event) {
         $event->types[] = MyCacheStorage::class;
     }
);

Cache Warmers #

In addition to the provided cache warmer, you can write your own by extending the BaseCacheWarmer abstract class. See the implementation of the putyourlightson\blitz\drivers\warmers\GuzzleWarmer class.

<?php
namespace vendor\package;

use putyourlightson\blitz\drivers\warmers\BaseCacheWarmer;

class MyCacheWarmer extends BaseCacheWarmer
{
    // Override base methods
}

To add your cache warmer to Blitz, you can create a stand-alone composer package for it. Install the package with composer require and then add the class to the cacheWarmerTypes config setting in config/blitz.php.

// The warmer type classes to add to the plugin’s default warmer types.
'cacheWarmerTypes' => [
    'vendor\package\MyCacheWarmer'
],

If you prefer to write your cache warmer as a module or plugin, then register it by listening for the EVENT_REGISTER_WARMER_TYPES event and adding the class to the $event->types array.

use craft\events\RegisterComponentTypesEvent;
use putyourlightson\blitz\helpers\CacheWarmerHelper;
use vendor\package\drivers\warmers\MyCacheWarmer;
use yii\base\Event;

Event::on(CacheWarmerHelper::class, 
     CacheWarmerHelper::EVENT_REGISTER_WARMER_TYPES,
     function(RegisterComponentTypesEvent $event) {
         $event->types[] = MyCacheWarmer::class;
     }
);

Reverse Proxy Purgers #

Available cache purger packages:

In addition to the provided reverse proxy purger, you can write your own by extending the BaseCachePurger abstract class. See the implementation of the putyourlightson\blitz\drivers\purgers\CloudflarePurger class.

<?php
namespace vendor\package;

use putyourlightson\blitz\drivers\purgers\BaseCachePurger;

class MyCachePurger extends BaseCachePurger
{
    // Override base methods
}

To add your cache purger to Blitz, you can create a stand-alone composer package for it. Install the package with composer require and then add the class to the cachePurgerTypes config setting in config/blitz.php.

// The purger type classes that should be available.
'cachePurgerTypes' => [
    'putyourlightson\blitz\drivers\purgers\CloudflarePurger',
    'vendor\package\MyCachePurger',
],

If you prefer to write your cache purger as a module or plugin, then register it by listening for the EVENT_REGISTER_PURGER_TYPES event and adding the class to the $event->types array.

use craft\events\RegisterComponentTypesEvent;
use putyourlightson\blitz\helpers\CachePurgerHelper;
use vendor\package\drivers\purgers\MyCachePurger;
use yii\base\Event;

Event::on(CachePurgerHelper::class, 
     CachePurgerHelper::EVENT_REGISTER_PURGER_TYPES,
     function(RegisterComponentTypesEvent $event) {
         $event->types[] = MyCachePurger::class;
     }
);

Remote Deployers #

Available deployer packages:

  • Shell Deployer (by PutYourLightsOn) 
  • Netlify Deployer (by PutYourLightsOn) 

    While the Netlify Deployer provides a quick and easy setup, the Git Deployer is the recommended way of deploying full websites to Netlify sites. 

In addition to the provided Git Deployer, you can write your own by extending the BaseDeployer abstract class. See the implementation of the putyourlightson\blitz\drivers\deployers\GitDeployer class.

<?php
namespace vendor\package;

use putyourlightson\blitz\drivers\deployers\BaseDeployer;

class MyDeployer extends BaseDeployer
{
    // Override base methods
}

To add your deployer to Blitz, you can create a stand-alone composer package for it. Install the package with composer require and then add the class to the deployerTypes config setting in config/blitz.php.

// The deployer type classes that should be available.
'deployerTypes' => [
    'vendor\package\MyDeployer',
],

If you prefer to write your deployer as a module or plugin, then register it by listening for the EVENT_REGISTER_DEPLOYER_TYPES event and adding the class to the $event->types array.

use craft\events\RegisterComponentTypesEvent;
use putyourlightson\blitz\helpers\DeployerHelper;
use vendor\package\drivers\deployers\MyDeployer;
use yii\base\Event;

Event::on(DeployerHelper::class, 
     DeployerHelper::EVENT_REGISTER_DEPLOYER_TYPES,
     function(RegisterComponentTypesEvent $event) {
         $event->types[] = MyDeployer::class;
     }
);

Integrations #

You can add integration with Blitz to your own custom or third-party plugin/​module. This is especially useful if elements are being created/​updated in bulk.

The following code enables batchMode before processing a feed, which forces Blitz to wait until the refresh method is manually called until refreshing the cache. In other words, only a single refresh cache job will be created even if 500 elements are updated.

// Before processing the feed
Blitz::$plugin->refreshCache->batchMode = true;

// Process the feed

// After processing the feed
Blitz::$plugin->refreshCache->refresh();

Alternatively, you can create an integration for a third-party plugin by implementing the IntegrationInterface class. See the implementation of the putyourlightson\blitz\drivers\integrations\FeedMeIntegration class.

<?php
namespace vendor\package;

use putyourlightson\blitz\Blitz;
use putyourlightson\blitz\drivers\integrations\IntegrationInterface;
use yii\base\Event;

class MyIntegration implements IntegrationInterface
{
    public static function getRequiredPlugins(): array
    {
        return [
            ['handle' => 'my-plugin-handle', 'version' => '2.0.0']
        ];
    }

    public static function registerEvents()
    {
        Event::on(MyPlugin::class, MyPlugin::EVENT_BEFORE_PROCESS_FEED,
            function() {
                Blitz::$plugin->refreshCache->batchMode = true;
            }
        );
        Event::on(MyPlugin::class, MyPlugin::EVENT_AFTER_PROCESS_FEED,
            function() {
                Blitz::$plugin->refreshCache->refresh();
            }
        );
    }
}

To add your integration to Blitz, you can create a stand-alone composer package for it. Install the package with composer require and then add the class to the integrations config setting in config/blitz.php.

// The integrations to initialise.
'integrations' => [
    'vendor\package\MyIntegration',
],

If you prefer to write your integration as a module or plugin, then register it by listening for the EVENT_REGISTER_INTEGRATIONS event and adding the class to the $event->types array.

use craft\events\RegisterComponentTypesEvent;
use putyourlightson\blitz\helpers\IntegrationHelper;
use vendor\package\drivers\integrations\MyIntegration;
use yii\base\Event;

Event::on(IntegrationHelper::class, 
     IntegrationHelper::EVENT_REGISTER_INTEGRATIONS,
     function(RegisterComponentTypesEvent $event) {
         $event->types[] = MyIntegration::class;
     }
);

More #

Common Issues #

The site is not being cached when I visit it” #

Ensure that the Caching Enabled setting is enabled and that the page you are visiting matches an Included URI Pattern (and not an Excluded URI Pattern). Blitz will not cache pages that display the debug toolbar so check that you are not logged in as an admin with the debug toolbar enabled on the front-end. Blitz will also not cache pages that contain asset transform generation URLs, as doing so can lead to cached pages that perform poorly (see this issue). To work around this, you can set enable the generateTransformsBeforePageLoad config setting.

The site is not being cached when using console commands” #

Ensure that the site’s Base URL does not use the @web alias and is not determined by a web request. A console request doesn’t come in through a URL so there will be nothing to detect. It is best to provide an absolute URL or use an alias, config setting or environment variable that references an absolute URL whenever possible. Ensure also that your site is switched on and is publicly accessible.

The refresh cache queue job is stalling” #

This is likely due to PHP timing out or running out of memory and is a common issue in Craft. For large sites we recommend increasing max_execution_time to 300 and memory_limit to 1024M.

The refresh cache queue jobs run for long periods of time and sometimes pile up” #

For very large sites, sites that don’t use eager-loading of elements in the templates, or sites that contain many relationships between elements, Blitz may need to check against thousands of element queries each time a refresh cache queue job is run. If this is negatively impacting the content editing experience then it may be worthwhile setting the cacheElementQueries config setting to false (followed by refreshing the cache). With this setting disabled, Blitz will be unable to automatically refresh cached pages when new entries are added (updating and deleting entries will still trigger a refresh).

To work around this, you can add source tags to pages that should be refreshed whenever an element in a section, category group, or another supported element source is created, updated or deleted.

{# Tags the page with section ID 3 #}
{% do craft.blitz.options.tags(['sectionId:3']) %}

{% for entry in craft.entries.sectionId(3).all() %}
    ...
{% endfor %}


The entire cache is cleared and warmed when only one entry is updated” #

This is likely due to that entry being referenced in the site’s navigation, footer, or other globally used element. If the entry is updated, then every cached page (in this case the entire site) must be cleared to ensure that the changes to that entry are reflected. This is avoidable in one of several ways.

  1. Hard-code the entry’s title and URL instead of dynamically referencing it.
  2. Use a dedicated navigation plugin such as Navigation by Verbb. 
  3. Disable the Clear Cache Automatically setting and create a cron job to refresh expired cache on a scheduled interval. If you want to keep the cache clearing behaviour but avoid rewarming the entire cache, disable the Warm Cache Automatically setting and allow the cache to be generated organically (when visitors browse your site), or create a cron job to warm the cache on a scheduled interval.
  4. Disable cacheElements and cacheElementQueries using page specific options before outputting the navigation or footer, for example:
{# Disable page options #}
{% do craft.blitz.options.cacheElements(false).cacheElementQueries(false) %}

{# Output global navigation #}
{% for entry in craft.entries.section('navigation').all() %}
    <a href="{{ entry.url }}">{{ entry.title }}</a>
{% endfor %}

{# Re-enable page options #}
{% do craft.blitz.options.cacheElements(true).cacheElementQueries(true) %}

The consequence of this is that the cached page will not be cleared when elements in the global navigation are updated (unless they are used elsewhere on the page).

Support #

Support is provided through GitHub issues and by email at [email protected]​putyourlightson.​net.