Blitz Logo Blitz

Intelligent static page caching for lightning-fast sites.

Reduces server response time by 10x for “instant” page loads.

Makes it possible to have your site served by a reverse proxy CDN.

Makes your site available even when performing updates and maintenance.

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.

Time to first byte

Blitz 3 is in public beta! Read the announcement or install it as follows:
composer require putyourlightson/craft-blitz:^3.0.0-beta.1

Although the performance gains depend on the individual site and server setup, the results above are not uncommon (on a 5 Mbps cable connection with 28ms of latency). Google recommends a server response time of 200ms or less.

Features #

Scalable
Cache invalidation is faster and lighter with fewer database needs. Blitz can also use Yii’s cache interface to tap into in-memory caches like Memcache and Redis. This makes Blitz a great fit for multi-node cloud platforms like Docker, Heroku and fortrabbit.

Extensible
Enjoy effortless full-page caching right at the edge with new reverse proxy purgers. Serve statically generated HTML pages from the Cloudflare CDN and let Blitz take care of invalidation. You can add your own purgers for services like Fastly, KeyCDN, and Akamai.

Predictable
Fine tune invalidation settings with expanded options for controlling when and how cached pages are handled. Set page specific options such as tags, cache durations and expiry dates. Use an API key and console commands to trigger actions on a schedule.

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

Paths

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.1.0 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…

  1. Turn Enable Caching” on.
  2. Add at least one row to Included URI Patterns” such as .* to cache the entire site.
  3. Save the settings and visit the site or warm the cache in the Blitz cache utility.

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 TTFB!

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

You can reduce the likelihood of visitors hitting un-cached pages by automatically keeping those caches warm. One way to do this is to create a cron job to refresh expired cache regularly and automatically.

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,

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 deleted. 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.

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 Warm Cache Automatically” is enabled and the warmCacheAutomaticallyForGlobals 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 (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 #

Added in Blitz 3.

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 #

Added in Blitz 3.

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.

Pattern Description
. Matches any character.
.* Matches any character 0 or more times.
.+ Matches any character 1 or more times.
\d Matches any digit.
\d{4} Matches any four digits.
\w Matches any word character.
\w+ Matches any word character 1 or more times.
entries Matches anything containing entries.
^entries Matches 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.

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 #

Added in Blitz 3.

The cache warmer to use for warming the cache. The default cache warmer is the Guzzle Warmer”. This warms the cache by sending GET requests to the cacheable pages on the site, therefore the site must be publicly accessible for this warmer to work.

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

Reverse Proxy Purger #

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, create a new page rule in the Page Rules” page of the domain in your account (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

Remote Deployment #

Added in Blitz 3.

A deployer allows you to deploy cached files to a remote location such as a Git repository. Selecting a deployer will tell Blitz to automatically deploy the appropriate pages once they have been warmed.

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

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 delete 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 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.

Concurrency #

Moved into the cache warmer in Blitz 3.

The max number of concurrent requests to use when warming the cache. The higher the number, the faster the cache will be warmed but the more server processing will be required. A number between 1 and 5 is recommended.

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.

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

Returns a script that injects the contents of the URI provided in place of the twig tag. 

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

Returns a script that injects the contents of a template in place of the twig tag. 

{{ 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. 

CSRF Controller Actions #

The controller action blitz/csrf/input can be used to fetch the 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.

$.get('/actions/blitz/csrf/token', function(data) {
    csrfToken = data;
};

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']) %}

cachingEnabled #

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

cacheElements #

Setting this option to false will disable caching the elements used on this page in the database (used for cache invalidation).

cacheElementQueries #

Setting this option to false will disable caching the element queries used on this page in the database (used for cache invalidation).

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.

Cron Jobs #

Create cron jobs using the following console commands to refresh expired or tagged cache on a scheduled basis. 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.

Note that the server rewrite code below was updated as of Blitz version 2.1.0.

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
#- Required as of version 2.1.0
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
#- Required as of version 2.1.0
RewriteCond %{QUERY_STRING} !token= [NC]
RewriteRule .* /cache/blitz/%{HTTP_HOST}/%{REQUEST_URI}/index.html [L]

#- Send would-be 404 requests to Craft

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 path
set $cache_path false;
if ($request_method = GET) {
    set $cache_path /cache/blitz/$host/$uri/$args/index.html;
}
#- Required as of version 2.1.0
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 path
set $cache_path false;
if ($request_method = GET) {
    set $cache_path /cache/blitz/$host/$uri/index.html;
}
#- Required as of version 2.1.0
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;
}

Debugging #

Cached HTML pages are timestamped with a comment at the end of the page. 

<!-- 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.

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 #

Added in Blitz 3.

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 storage 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 to add to the plugin’s default purger types.
'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 #

Added in Blitz 3.

Available deployer packages:

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 to add to the plugin’s default deployer types.
'deployerTypes' => [
    'putyourlightson\blitz\drivers\purgers\CloudflarePurger',
    '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;
     }
);

More #

Common Issues #

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

Ensure that the Caching Enabled setting is switched on 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).

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 at least 300 and memory_limit to at least 1024M. The Async Queue plugin can help prevent timeouts and memory issues by running jobs as background tasks and the Queue Manager plugin allows you to see what jobs are in the queue and manipulate them.

Support #

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