Page Cache
Evolve comes with full response caching for pages. This can greatly improve the performance of your website by serving static HTML files instead of booting up Laravel for every request.
How it works
Usualy when a request comes in, your webserver (Apache/Nginx) redirects everything to public/index.php which starts PHP and spins up a new Laravel instance. Starting a new PHP process, booting Laravel, making database calls and doing other logic in your application sometimes takes a lot of time.
The Evolve Page Cache will do this only one time for each route and then save the full response body to a static HTML or JSON file on your webserver.
For example: When you visit the route /en/contact, the page cache will create a new file in public/page-cache/en/contact/index.html. Same goes for AJAX calls which result in index.json files inside the page-cache directory.
Now we can serve the content directly from our page-cache directory without even having to start PHP or Laravel.
WARNING
Be aware of the fact that you can only cache pages with static content! Every user will get the exact same cached file.
INFO
Good to know: Only GET requests with a successful response code (HTTP 2xx) will be cached.
Setup
Enabling the page cache
Enable the page cache on the Evolve Settings Page or just set APP_PAGE_CACHE=true. Outgoing responses will now be cached to disk and ready to be served for the next request.
Serving cached content
To be able to serve the static files correctly from our page-cache directory we'll have to tell Apache about it. Place this config just before the FrontController handling:
# Serve Cached Page If Available...
RewriteCond %{REQUEST_URI} ^/?$
RewriteCond %{DOCUMENT_ROOT}/page-cache/index.html -f
RewriteRule .? page-cache/index.html [L]
RewriteCond %{DOCUMENT_ROOT}/page-cache%{REQUEST_URI}/index.html -f
RewriteRule . page-cache%{REQUEST_URI}/index.html [L]
RewriteCond %{DOCUMENT_ROOT}/page-cache%{REQUEST_URI}/index.json -f
RewriteRule . page-cache%{REQUEST_URI}/index.json [L]Workaround for CSRF Tokens
Because CSRF tokens are session based, we cannot use the token in the <meta> tag anymore for making POST requests. We need to fetch it with Javascript in the frontend.
Replace the CSRF token part in the theme's src/app.ts with this:
// Add Laravel CSRF token to axios defaults
export const csrfReady = Http.get('/api/csrf-token').then(response => {
Http.defaults.headers.common['X-CSRF-TOKEN'] = response.data
Http.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'
})Now, when doing POST requests, be sure to wait for the csrfReady promise to be fulfilled.
import { csrfToken } from '@app/app'
csrfToken.then(() => {
// Ready to do POST requests
// Http.post(...)
})Controlling which pages get cached
Exclude routes
You can exclude somes routes from the page cache by adding the path to the page-cache.ignore array. Asterisks (*) may be used as wildcard values.
'page-cache' => [
'ignore' => [
'/de/fahrzeuge',
'/de/shop/*',
]
]Routeables
With Evolve, your pages are usually served via a model which implements the Routeable interface. You can specify which models should get cached by returning true/false from the isPageCachable public method.
public function isPageCachable(): bool
{
$allowPageCache = /* some custom logic */ ;
return $allowPageCache;
}Clearing cached pages
Most models in Evolve are already set up to clear the related routes when changes are made. But sometimes you still need to clear the cached content by yourself. There's a few ways to do it:
Evolve Admin UI
You can clear all cached content simply by clicking the cache clear button in the footer. Navigate to the caches page to forget specific pages.
Artisan command
# Flush all cached content
php artisan evolve:clear-page-cache
# Clear a specific page
php artisan evolve:clear-page-cache de/some-pageProgrammatically
use Racerfish\Evolve\Services\PageCache;
// Flush all cached content
PageCache::make()->flush();
// Clear a specific page
PageCache::make()->forget('de/some-page');
// Clear many pages
PageCache::make()->forget([
'de/some-page',
'de/another-page',
'de/full-paths/*',
]);Pre-Caching pages
Artisan command
You can pre-cache all Evolve routes with the evolve:rebuild-page-cache Artisan command.
php artisan evolve:rebuild-page-cacheProgrammatically
If you wish to do the pre-caching in code, you can do it by making a GET request with a HTTP client to a specific route. Make sure to make two calls: One requesting text/html, and another requesting application/json.
// Cache HTML version
Http::accept('text/html')->get('/en/contact');
// Cache JSON/API version
Http::accept('application/json')->get('/en/contact');Evolve will return a X-Evolve-Page-Cache header with a value of either cached or none, depending on if the page was cached or not.
$response = Http::accept('text/html')->get('/en/contact');
if ($response->header('X-Evolve-Page-Cache') === 'cached') {
echo 'Page successfully cached to disk';
}