🚀 Kirby 3.9 is here! Learn more
Skip to content

Staticache

return [
  'cache' => [
    'pages' => [
      'active' => true,
      'type'   => 'static'
    ]
  ]
];

Staticache gives you the performance of a static site generator for your regular Kirby installations.

Introduction

Static site performance on demand!

This plugin will give you the performance of a static site generator for your regular Kirby installations. Without a huge setup or complex deployment steps, you can run your Kirby site on any server – cheap shared hosting, VPS, you name it – and enable the static cache to get incredible speed on demand.

With custom ignore rules, you can even mix static and dynamic content. Keep some pages static while others are still served live by Kirby.

The static cache will automatically be flushed whenever content gets updated in the Panel. It's truly the best of both worlds.

Rough benchmark comparison for our Starterkit home page:

Without page cache: ~70 ms
With page cache: ~30 ms
With static cache: ~10 ms

Limitations

This plugin is still an experiment. The first results are very promising but it needs to be tested on more servers.

A statically cached page will prevent any Kirby logic from executing. This means that Kirby can no longer differentiate between visitors and logged-in users. Every request will be served directly by your web server, even if the response would differ based on the cookies or other request headers.

If your site has any logic in controllers, page models, templates, snippets or plugins that results in different page responses depending on the request, this logic will naturally not be compatible with Staticache.

If only specific pages are affected by this, you can add them to the cache ignore list (see below) and use Staticache for the rest of your site. Otherwise, using Kirby's default page cache will be the better option overall because Kirby will automatically detect which responses can be cached and which caches can be used for the current request.

Setup

Cache configuration

Basic setup:

Staticache is a cache driver that can be activated for the pages cache:

site/config/config.php
return [
  'cache' => [
    'pages' => [
      'active' => true,
      'type'   => 'static'
    ]
  ]
];

Ignore rules:

If you want to keep some of your pages dynamic, you can configure ignore rules like for the native pages cache: https://getkirby.com/docs/guide/cache#caching-pages

site/config/config.php
return [
  'cache' => [
    'pages' => [
      'active' => true,
      'type'   => 'static',
      'ignore' => function ($page) {
        return $page->template()->name() === 'blog';
      }
    ]
  ]
];

All pages that are not ignored will automatically be cached on their first visit. Kirby will automatically purge the cache when changes are made in the Panel.

Please note that already cached pages are unaffected by changes to the ignore option. Your web server will pick up the already created files and will not check if the page is cacheable. If you see cached results from ignored pages, please manually clear your cache directory.

Custom cache comment:

Staticache adds an HTML comment like <!-- static YYYY-MM-DDT01:02:03+00:00 --> to the end of every cached HTML file by default. You can override or disable this comment in the cache configuration:

site/config/config.php
return [
  'cache' => [
    'pages' => [
      'active' => true,
      'type'   => 'static',

      // disabled comment
      'comment' => '',

      // OR string value (only for HTML)
      'comment' => '<!-- your custom comment -->',

      // OR a custom closure
      'comment' => fn ($contentType) => $contentType === 'html' ? '<!-- comment -->' : ''
    ]
  ]
];

Custom root:

The rendered HTML files are stored in the site/cache/example.com/pages/ folder just like with the native pages cache. The difference is that all paths within this folder match the URL structure of your site. The separate directories for each root URL ensure that links and references in your rendered HTML keep working even in a multi-domain setup.

If you are using a custom web server setup, you can override the cache root like so:

site/config/config.php
return [
  'cache' => [
    'pages' => [
      'active' => true,
      'type'   => 'static',
      'root'   => '/path/to/your/cache/root',
      'prefix' => null
    ]
  ]
];

If your site is only served on a single domain, you can disable the root URL prefix like so while keeping the general storage location in the site/cache directory:

site/config/config.php
return [
  'cache' => [
    'pages' => [
      'active' => true,
      'type'   => 'static',
      'prefix' => 'pages'
    ]
  ]
];

If you use a custom root and/or prefix, please modify the following server configuration examples accordingly.

Web server integration

This plugin will automatically generate and store the cache files, however you need to configure your web server to pick the files up and prefer them over a dynamic result from PHP.

The configuration depends on your used web server:

Apache:

Add the following lines to your Kirby .htaccess file, directly after the RewriteBase rule.

RewriteCond %{DOCUMENT_ROOT}/site/cache/%{SERVER_NAME}/pages/%{REQUEST_URI}/index.html -f [NC]
RewriteRule ^(.*) %{DOCUMENT_ROOT}/site/cache/%{SERVER_NAME}/pages/%{REQUEST_URI}/index.html [L]

RewriteCond %{DOCUMENT_ROOT}/site/cache/%{SERVER_NAME}/pages/%{REQUEST_URI} -f [NC]
RewriteRule ^(.*) %{DOCUMENT_ROOT}/site/cache/%{SERVER_NAME}/pages/%{REQUEST_URI} [L]

Caddy:

A simple Caddy config for Staticache may look like this:

example.com

root * /path/to/your/site

file_server
php_fastcgi unix//var/run/php-fpm.sock {
  try_files {path} site/cache/{host}/pages/{path}/index.html site/cache/{host}/pages/{path} index.php
}

nginx:

Standard PHP nginx config will have this location block for all requests:

location / {
  try_files $uri $uri/ /index.php?$query_string;
}

Change it to add /site/cache/$server_addr/pages/$uri/index.html before the last /index.php fallback:

location / {
  try_files $uri $uri/ /site/cache/$server_addr/pages/$uri/index.html /site/cache/$server_addr/pages/$uri /index.php?$query_string;
}

PHP loader:

If you don't have access to the server configuration, you can load the static caches from your Kirby index.php. Compared to Kirby's built-in page cache, this avoids having to load Kirby on every request, but all requests are still passed to PHP. This makes this approach slower than the direct integration into the web server but still much faster than the built-in page cache.

To load the static cache files from PHP, please place the following code snippet right at the top (!) of your index.php file (directly after the opening <?php tag):

index.php
(function /* staticache */ () {
  $root = __DIR__ . '/site/cache';

  // check if a cache for this domain exists
  $root .= '/' . $_SERVER['SERVER_NAME'] . '/pages';
  if (is_dir($root) !== true) {
    return;
  }

  // determine the exact file to use
  $path = $root . '/' . ltrim($_SERVER['REQUEST_URI'] ?? '', '/');
  if (is_file($path . '/index.html') === true) {
    // a HTML representation exists in the cache
    $path = $path . '/index.html';
  } elseif (is_file($path) !== true) {
    // neither a HTML representation nor a custom
    // representation exists in the cache
    return;
  }

  die(file_get_contents($path));
})();

Header support

Staticache stores only the response bodies by default. The HTTP status code as well as headers set by your pages are not preserved in this mode. This ensures compatibility with all web servers.

If your web server supports reading headers from the static files, you can enable header support with the headers option:

site/config/config.php
return [
  'cache' => [
    'pages' => [
      'active'  => true,
      'type'    => 'static',
      'headers' => true
    ]
  ]
];

You need to adapt your web server configuration accordingly:

Apache:

Header support in Apache requires mod_asis. Please ensure that your Apache installation has this module installed and enabled.

Afterwards add the following block to your .htaccess file to make Apache use mod_asis for cached files:

<Directory "/var/www/your-site/site/cache">
  SetHandler send-as-is
</Directory>

PHP loader:

Replace the last line of the loader function with this code:

index.php
// split the file into headers (before two line breaks) and body
  $file    = file_get_contents($path);
  $divide  = mb_strpos($file, "\n\n");
  $headers = mb_substr($file, 0, $divide);
  $body    = mb_substr($file, $divide + 2);

  foreach (explode("\n", $headers) as $header) {
    if (mb_substr($header, 0, 7) === 'Status:') {
      http_response_code((int)trim(mb_substr($header, 8)));
    } else {
      header($header);
    }
  }

  die($body);

Related plugins

return [
    'afbora.kirby-minify-html' => [
        'enabled' => true,
        'options' => [...]
    ]
];

Minify HTML

by Ahmet Bora

Enable minify HTML output for Kirby 3.
// kirby core
$page = page($somePageId);
// faster
$page = boost($somePageId);
// fastest
$page = boost($somePageDirUri);

Boost

by Bruno Meilick

Boost the speed of Kirby by having content files of pages cached, with automatic unique ID, fast lookup and Tiny-URL.
$page->file('ukulele.pdf')->fingerprint();

Fingerprint

by Bruno Meilick

File method and css/js helpers to add hashes to assets and files
$key  = crc32($page->url());
$data = lapse($key, function () {
    return [1, 2, 3];
});

Lapse

by Bruno Meilick

Cache any data until the set expiration time

MySQL Cache Driver

by Bruno Meilick

MySQL based Cache-Driver

PHP Cache Driver

by Bruno Meilick

PHP based Cache-Driver

Redis Cache Driver

by Bruno Meilick

Redis based Cache-Driver

SQLite Cache Driver

by Bruno Meilick

SQLite based Cache-Driver
site()->stopwatch()->start('myevent');
// some code to profile
site()->stopwatch()->stop('myevent');

echo site()->stopwatch()->duration('myevent');

Stopwatch

by Bruno Meilick

Profile your Kirby 3 CMS code with precision in milliseconds (or seconds).
<?= js('assets/js/main.js') ?>

<!-- will become -->
<script src="/assets/js/main.9ad649fd.js"></script>

Hashed Assets

by Johann Schopplich

File name hashes support for css() and js() helpers. Without rewrite rules!

AWS CloudFront invalidations

by Liftric GmbH

Kirby plugin which triggers AWS CloudFront invalidations automatically.
return [
    'lukaskleinschmidt.resolve.cache' => true
];

Resolve

by Lukas Kleinschmidt

Speed up Kirby's page routing.

Clear Cache

by oweb studio

Clean temporary files and folders such as cache, media, .lock and .logins on your website.

PWA (Progressive Web App)

by oweb studio

Turns your Kirby website into a PWA: progressive web app.
return [
  'schnti.cachebuster.active' => true
];

Cachebuster

by Timo Schneider

Add modification timestamps to your css and js files, as long as they are embedded with the css() and js() helpers.

Clear Cloudflare Cache

by Markus Denhoff

Automatically purge Cloudflare cached URLs

Other plugins by Kirby Team