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 intel­li­gent stat­ic page cach­ing for cre­at­ing light­ning-fast sites with Craft CMS. It sig­ni­fic­antly improves a site’s per­form­ance by redu­cing serv­er response time.

Time to first byte

Although the per­form­ance gains depend on the indi­vidu­al site and serv­er setup, the res­ults above are not uncom­mon (on a 5 Mbps cable con­nec­tion with 28ms of latency). Google recom­mends a serv­er response time of 200ms or less.

Fea­tures #

Scal­able
Cache inval­id­a­tion is faster and light­er with few­er data­base needs. Blitz can also use Yii’s cache inter­face to tap into in-memory caches like Mem­cache and Redis. This makes Blitz a great fit for multi-node cloud plat­forms like Dock­er, Her­oku and for­trab­bit.

Extens­ible
Enjoy effort­less full-page cach­ing right at the edge with new reverse proxy pur­gers. Serve stat­ic­ally genet­er­ate HTML pages from the Cloud­flare CDN and let Blitz take care of inval­id­a­tion. You can add your own pur­gers for ser­vices like Fastly, KeyCDN, and Akamai.

Pre­dict­able
Fine tune inval­id­a­tion set­tings with expan­ded options for con­trolling when and how cached pages are handled. Set page spe­cif­ic options such as tags, cache dur­a­tions and expiry dates. Use an API key and con­sole com­mands to trig­ger actions on a schedule.

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

Paths

License #

This plu­gin requires a com­mer­cial license pur­chas­able through the Craft Plu­gin Store. The license fee is $59 plus $29 per sub­sequent year for updates (option­al).

Require­ments #

This plu­gin requires Craft CMS 3.1.0 or later.

Basic Usage #

Get­ting Star­ted #

To install the plu­gin, search for Blitz” in the Craft Plu­gin Store, or install manu­ally using composer.

composer require putyourlightson/craft-blitz

Blitz will not make any changes to your site when first installed. To start cach­ing pages…

  1. Turn Enable Cach­ing” on.
  2. Add at least one row to Included URI Pat­terns” such as .* to cache the entire site.
  3. Save the set­tings and vis­it the site or warm the cache in the Blitz cache util­ity.

That’s it! You should notice an imme­di­ate dif­fer­ence once Blitz is cach­ing your pages. There are a few more option­al steps you can take to cut even more time off that TTFB!

If you are using Blitz File Stor­age” as the cache stor­age type, you can add Apache or Nginx serv­er rewrites to avoid PHP pro­cessing for even bet­ter performance.

You can reduce the like­li­hood of vis­it­ors hit­ting un-cached pages by auto­mat­ic­ally keep­ing those caches warm. One way to do this is to cre­ate a cron job to refresh expired cache reg­u­larly and automatically.

Craft’s {% cache %} tag doesn’t always play well with Blitz cache inval­id­a­tion. Since tem­plate cach­ing becomes redund­ant with full page cach­ing, it is best to remove {% cache %} tags from tem­plates Blitz caches, or simply dis­able tem­plate cach­ing from config/general.php:

'enableTemplateCaching' => false,

How It Works #

When a page is vis­ited that matches an included URI pat­tern, Blitz will serve a cached ver­sion of the page if it has one. Oth­er­wise, it will dis­play and cache the tem­plate out­put. Excluded URI pat­terns will over­ride any match­ing included URI patterns.

When an ele­ment is cre­ated, updated or deleted, any cached pages that used that ele­ment are deleted. If a reverse proxy pur­ger such a Cloud­flare is selec­ted, the pages are purged. If the Warm Cache Auto­mat­ic­ally” set­ting is enabled, a job is queued to warm the cleared cache.

Blitz is com­pat­ible with Craft’s Live Pre­view. It will detect when it is being used and not cache its out­put or dis­play cached content.

If a Glob­al is saved, Blitz will refresh the entire site cache if Warm Cache Auto­mat­ic­ally” is enabled and the warmCacheAutomaticallyForGlobals con­fig set­ting has not been set to false. This is because Glob­als are avail­able on every page of every site and can poten­tially affect every single cached page. Glob­als should be used spar­ingly and only in situ­ations where the glob­al value needs to be access­ible from mul­tiple pages. For any­thing else, con­sider using Entries or Cat­egor­ies rather than Globals.

Cache Util­ity #

The Blitz cache util­ity at Util­it­ies → Blitz Cache dis­plays the num­ber of cached URIs for each site (Blitz File Stor­age only). It also provides the fol­low­ing functionality.

Clear Cache #

Clear­ing the cache will delete all cached pages.

Flush Cache #

Flush­ing the cache will delete all records from the database.

Flush­ing the cache does not clear the cache, as it did in Blitz 1.

Warm Cache #

Warm­ing the cache will warm all of the pages by cre­at­ing a queue job to vis­it each of them.

Warm­ing the cache does not clear and flush the cache, as it did in Blitz 1.

Refresh Entire Cache #

Refresh­ing the cache will clear, flush, purge and warm all of the pages.

Refresh Expired Cache #

Refresh­ing expired cache will refresh all cached pages that have expired, or that con­tain Ele­ments that have expired (applies to Ele­ments with future post and expiry dates). Cache dur­a­tion and expiry dates can be spe­cified in the con­fig set­tings and the page spe­cif­ic options.

Refresh Tagged Cache #

Refresh­ing tagged cache will refresh all cached pages that were asso­ci­ated with the provided tags using the tags para­met­er in the page spe­cif­ic options.

Utility

Con­sole Com­mands #

Every cache util­ity func­tion above is also avail­able as a con­sole command.

./craft blitz/cache/clear

./craft blitz/cache/flush

./craft blitz/cache/warm

./craft blitz/cache/refresh

./craft blitz/cache/refresh-expired

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

Console commands

A con­sole com­mand also exists that gen­er­ates entry expiry dates and stores them to enable refresh­ing expired cache. This hap­pens auto­mat­ic­ally when entries are saved since Blitz ver­sion 2.0.0 but this com­mand allows sites that recently updated to gen­er­ate expiry dates for all of their entries. 

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

Refresh­ing Cache via URL #

Once you have cre­ated an API key in Set­tings → Advanced, you can trig­ger each of the cache util­it­ies through a URL. Those URLs are dis­played under the API key field after the set­ting has been saved.

API key

Set­tings #

Con­trol Pan­el Set­tings #

Cach­ing Enabled #

With this set­ting enabled, Blitz will begin cach­ing pages accord­ing to the included/​excluded URI pat­terns. Dis­able this set­ting to pre­vent Blitz from cach­ing any new pages.

Included/​Excluded URI Pat­terns #

The URI pat­terns to include or exclude when cach­ing. Blitz will only cache pages whose URI matches the URI pat­terns, giv­ing you fine-grain con­trol over what is cached.

URI pat­terns use PCRE reg­u­lar expres­sions (cheat sheet). Below are some com­mon use cases.

Pat­tern Descrip­tion
. Matches any character.
.* Matches any char­ac­ter 0 or more times.
.+ Matches any char­ac­ter 1 or more times.
\d Matches any digit.
\d{4} Matches any four digits.
\w Matches any word character.
\w+ Matches any word char­ac­ter 1 or more times.
entries Matches any­thing con­tain­ing entries.
^entries Matches any­thing begin­ning with entries.
^entries/entry$ Matches the exact URI entries/entry.

Settings General

Cache Stor­age #

The stor­age type to use for stor­ing cached pages. The default and recom­men­ded stor­age type for most sites is Blitz File Stor­age”. This stores cached pages as stat­ic HTML files in the spe­cified Folder Path” and is extremely per­form­ant, espe­cially when used with serv­er rewrites.

A Yii Cache Stor­age” type is also avail­able and will use whatever cache com­pon­ent Craft is set up to use. You can con­fig­ure Craft to use altern­at­ive cache stor­age (Mem­cache, Redis, etc.) by over­rid­ing the cache applic­a­tion com­pon­ent from config/app.php as explained in the Craft docs. This is the recom­men­ded stor­age type for multi-node cloud plat­forms like Dock­er, Her­oku and for­trab­bit.

You can extend Blitz to add your own cus­tom cache stor­age types.

Settings Storage

Reverse Proxy Pur­ger #

A pur­ger to use for clear­ing cache in a reverse proxy. This allows you to use a reverse proxy cache ser­vice and CDN such as Cloud­flare to deliv­er cached pages. Select­ing a pur­ger will tell Blitz to auto­mat­ic­ally purge the appro­pri­ate pages whenev­er they are updated.

You can extend Blitz to add your own cus­tom reverse proxy pur­gers.

Settings Purger

Cloud­flare does not cache HTML by default. To enable stat­ic page cach­ing, cre­ate 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 pat­tern such as domain.com/* and add a Cache Level” set­ting with a value of Cache Everything”. Click Save and Deploy” and then vis­it your site. With dev tools open you should see a cache response (HIT, MISS, etc.) in the CF-Cache-Status header.

Cloudflare Page Rule

Clear Cache Auto­mat­ic­ally #

Wheth­er the cache should auto­mat­ic­ally be cleared after ele­ments are updated. With this set­ting dis­abled, Blitz will mark affected page caches as expired without actu­ally delete them. In order to delete them, the Refresh Expired Cache” util­ity or con­sole com­mand should be used. Dis­abling this set­ting may make sense if your site gets heavy traffic and clear­ing cache should be lim­ited to spe­cif­ic times or intervals.

Warm Cache Auto­mat­ic­ally #

Wheth­er the cache should auto­mat­ic­ally be warmed after clear­ing. With this set­ting enabled, Blitz will cre­ate a queue job to auto­mat­ic­ally vis­it pages whose cache has been cleared in the back­ground. Dis­abling this set­ting may make sense if your site is very large and has many related elements.

Con­cur­rency #

The max num­ber of con­cur­rent requests to use when warm­ing the cache. The high­er the num­ber, the faster the cache will be warmed but the more serv­er pro­cessing will be required. A num­ber between 1 and 5 is recommended.

Query String Cach­ing #

URLs with query strings will be cached accord­ing to the selec­ted option in the Query String Cach­ing” set­ting as follows:

Do not cache URLs with query strings #

URLs with query strings (any­thing fol­low­ing a ? in a URL) will not be cached. Use this if query para­met­ers dynam­ic­ally affect a page’s out­put and should there­fore nev­er 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 sep­ar­ately. Use when query para­met­ers affect a page’s out­put in a determ­in­ist­ic way and can there­fore 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 out­put. Use when query para­met­ers do not affect a page’s out­put and can there­fore 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 char­ac­ters). The indi­vidu­al URLs are dis­played below the field after a value has been saved.

Settings Advanced

Con­fig Set­tings #

Blitz comes with a con­fig file for a multi-envir­on­ment way to set the plu­gin set­tings, as well as more advanced plu­gin con­fig­ur­a­tion set­tings. To use it, copy the config.php to your project’s main config dir­ect­ory as blitz.php and uncom­ment any set­tings you wish to change. All of the avail­able set­tings are lis­ted and doc­u­mented in the con­fig file.

Advanced Usage #

Dynam­ic Con­tent #

When a page is cached, the cached ver­sion of that page will be served up on all sub­sequent requests. You should there­fore avoid cach­ing pages whose entire con­tent changes per indi­vidu­al request. The easi­est way to do this is to add excluded URI pat­terns for such pages. 

Blitz offers a work­around for inject­ing dynam­ic con­tent into a cached page using a Javas­cript XHR (AJAX) request. The fol­low­ing tem­plate tags are avail­able for doing so.

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

Returns a script that injects the con­tents of the URI provided 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 cre­ate a page con­tain­ing dynam­ic con­tent 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 Con­trol­ler Actions #

The con­trol­ler action blitz/csrf/input can be used to fetch the input field dynam­ic­ally using AJAX, for example. The blitz/csrf/param and blitz/csrf/token con­trol­ler actions are also avail­able for fetch­ing the CSRF param and a token respectively.

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

Page Spe­cif­ic Options #

It is pos­sible to set page spe­cif­ic cach­ing options in your twig tem­plates by passing an object into the craft.blitz.options() func­tion. All para­met­ers are optional.

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

An altern­at­ive nota­tion is to use meth­od chain­ing on the mod­el that the craft.blitz.options() func­tion returns.

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

cachingEnabled #

Set­ting this option to false will dis­able cach­ing of this page.

cacheElements #

Set­ting this option to false will dis­able cach­ing the ele­ments used on this page in the data­base (used for cache invalidation).

cacheElementQueries #

Set­ting this option to false will dis­able cach­ing the ele­ment quer­ies used on this page in the data­base (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 sup­por­ted value types. Dur­a­tion inter­vals are a con­veni­ent way to set dur­a­tions. Com­mon examples include:

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

expiryDate #

A Dat­e­Time object that will define when the cache should expire. The Refresh Expired Cache” util­ity or con­sole com­mand must be used to inval­id­ate expired cache. 

tags #

One or more tags (array or string sep­ar­ated by com­mas) that will be asso­ci­ated with this page. Tags should not con­tain spaces. The Refresh Tagged Cache” util­ity or con­sole com­mand can be used to inval­id­ate tagged cache.

Cron Jobs #

Cre­ate cron jobs using the fol­low­ing con­sole com­mands to refresh expired or tagged cache on a sched­uled basis. If entries are gen­er­ally pos­ted or expire on the hour then a good sched­ule might be every hour at 5 minutes past the hour. Change /usr/bin/php to the PHP path (if different).

Enter­ing which php in the con­sole 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

Serv­er Rewrites #

For improved per­form­ance when using the Blitz File Stor­age” type, adding a serv­er rewrite will avoid the request from ever being pro­cessed by Craft once it has been cached. This leads to extremely per­form­ant load­ing of cached pages.

Note that the serv­er rewrite code below was updated as of Blitz ver­sion 2.1.0.

Apache #

In Apache this is achieved with mod_rewrite by adding a rewrite rule to the vir­tu­al host .conf file (this art­icle 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 des­ig­nated in the plu­gin set­tings (if different).

If the Query String Cach­ing” set­ting is set to Do not cache URLs with query strings or Cache URLs with query strings as unique pages then use the fol­low­ing 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 Cach­ing” set­ting is set to Cache URLs with query strings as the same page then the /%{QUERY_STRING} seg­ment 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 loc­a­tion hand­ler to the con­fig­ur­a­tion file. 

Change cache/blitz to the cache folder path des­ig­nated in the plu­gin set­tings (if different).

If the Query String Cach­ing” set­ting is set to Do not cache URLs with query strings or Cache URLs with query strings as unique pages then use the fol­low­ing code.

#- Blitz cache rewrite
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;
}
location / {
    try_files $cache_path;
}

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

If the Query String Cach­ing” set­ting is set to Cache URLs with query strings as the same page then the /$args seg­ment should be removed.

#- Blitz cache rewrite
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;
}
location / {
    try_files $cache_path;
}

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

Debug­ging #

Cached HTML pages are timestamped with a com­ment at the end of the page. 

<!-- Cached by Blitz on 2018-06-27T10:05:00+02:00 -->

If the HTML was served by the plu­gin rather than with a serv­er rewrite then an addi­tion­al com­ment is added.

<!-- Served by Blitz -->

Note that if your HTML is mini­fied then all com­ments will be removed from the markup, includ­ing the com­ments above.

If the sendPoweredByHeader con­fig set­ting is not set to false then an X-Powered-By: Blitz head­er will be sent.

Extend­ing Blitz #

Cache Stor­age Types #

In addi­tion to the provided cache stor­age types, you can write your own by extend­ing the BaseCacheStorage abstract class. See the imple­ment­a­tion 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 stor­age type to Blitz, you can cre­ate a stand-alone com­poser pack­age for it. Install the pack­age with composer require and then add the class to the cacheStorageTypes con­fig set­ting 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 stor­age type as a mod­ule or plu­gin, then register it by listen­ing 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;
     }
);

Reverse Proxy Pur­gers #

In addi­tion to the provided reverse proxy pur­gers, you can write your own by extend­ing the BaseCachePurger abstract class. See the imple­ment­a­tion of the putyourlightson\blitz\drivers\purgers\CloudflarePurger class.

<?php
namespace vendor\package;

use putyourlightson\blitz\drivers\storage\BaseCachePurger;

class MyCachePurger extends BaseCachePurger
{
    // Override base methods
}

To add your cache pur­ger to Blitz, you can cre­ate a stand-alone com­poser pack­age for it. Install the pack­age with composer require and then add the class to the cachePurgerTypes con­fig set­ting 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',
],

Avail­able cache pur­ger packages:

If you prefer to write your cache pur­ger as a mod­ule or plu­gin, then register it by listen­ing 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;
     }
);

More #

Com­mon Issues #

The site is not being cached when I vis­it it.”

Ensure that the Cach­ing Enabled set­ting is switched on and that the page you are vis­it­ing matches an Included URI Pat­tern (and not an Excluded URI Pat­tern). Blitz will not cache pages that dis­play the debug tool­bar so check that you are not logged in as an admin with the debug tool­bar enabled on the front-end. Blitz will also not cache pages that con­tain asset trans­form gen­er­a­tion URLs in them as doing so can lead to cached pages that per­form poorly (see this issue).

The site is not being cached when using con­sole commands.”

Ensure that the site’s Base URL does not use the @web ali­as and is not determ­ined by a web request. A con­sole request doesn’t come in through a URL so there will be noth­ing to detect. It is best to provide an abso­lute URL or use an ali­as, con­fig set­ting or envir­on­ment vari­able that ref­er­ences an abso­lute URL whenev­er pos­sible. Ensure also that your site is switched on and is pub­licly accessible.

The refresh cache queue job is stalling.”

This is likely due to PHP tim­ing out or run­ning out of memory and is a com­mon issue in Craft. For large sites we recom­mend increas­ing max_execution_time to at least 300 and memory_limit to at least 1024M. The Async Queue plu­gin can help pre­vent timeouts and memory issues by run­ning jobs as back­ground tasks and the Queue Man­ager plu­gin allows you to see what jobs are in the queue and manip­u­late them.

Sup­port #

Sup­port is provided through Git­Hub issues and by email at [email protected]​putyourlightson.​net.

Cred­its #

Blitz is act­ively developed and main­tained by PutY­our­Light­sOn, yet it has had a tre­mend­ous amount of sup­port from the Craft CMS com­munity. A few people worth men­tion­ing for their valu­able input are: Oliv­er Stark; Andrew Welch; Ben Parizek.