Page Caching
WordPress, being built with PHP and using a database, comes with some inherent overhead. Requesting data from the database takes time, plugin code adds a bit more time, and so does your theme. Before you know it, a site can be taking 5-10 seconds before it can even return a response (this is the plain HTML code), not to mention all the CSS, JS, images and fonts your page might need AFTER the browser gets the initial HTML from the page. In addition to that, if you can't afford quality hosting, your server might be overloaded from sharing resources with 200-300 other sites, and the overhead from all the PHP and database queries gets even worse!
Clearing the Cache
WebP Variant
- The server gets a request for https://my-awesome-site.com/my-awesomer-image.jpg
- It checks to see if the visitor is using a browser that supports WebP (most do) AND if there is a WebP version of my-awesomer-image.jpg.
- If #2, bam, it's delivered, no URLs changed, no HTML broken, hurrah!
We have some other WebP delivery options in the EWWW Image Optimizer, but they all have one fatal flaw: they change the HTML structure of your page to deliver WebP images.
So this is my second favorite WebP delivery option, and it's a great one! When SWIS caches your pages, it can build 2 copies (or variants): one for WebP browsers, and one for the poor saps on old browsers. These variants are completely identical in structure. The only difference is the image URLs themselves.
When someone visits your site, SWIS does a quick check for WebP support, and delivers the appropriate variant to the visitor. Double hurrah!
Cache Preload
Most sites aren't static, they change from time to time. And so the cache gets cleared, and now your visitors are getting slow page loads because the cache needs to be rebuilt. Never fear, just let cache preloading take care of that, and say goodbye to slow first page loads!
But how does it work?!?! Alright, I'll tell you, ease up already! First, it checks for site maps in known locations (sitemap_index.xml, sitemap.xml, and wp-sitemap.xml). If your sitemap is somewhere else, just holler and we'll add it to the list. But those covers all the common SEO plugins and stock WP behavior.
If SWIS absolutely can't find a sitemap, it'll grab the 1,000 most recently published posts/pages/content. From there, it uses "async" requests in the background to fetch each one of the URLs that have been found. By default, it pauses for 5 seconds in between requests, but you can change that with the swis_cache_preload_delay filter if you like. If a page is cached already, SWIS is clever enough to skip ahead and go to the next URL, so there's no double-dipping (gross, who does that!).
More Options?
Oh, you betcha! The Page Cache has even more options available via Overrides.
Server-based Cache Delivery
Page Caching in SWIS is already about as fast as it can possibly be. But there can still be a small amount of overhead from running PHP. To bypass PHP entirely, you can implement rewrite rules with your server that will deliver the cached pages without running any PHP code.
But before we get to that, there are a few caveats. First, modern PHP is so fast, you may not see any difference. In my own tests the difference with/without PHP was a mere 2ms, but every site is different, so you can try it out and see for yourself.
Second, when your server is delivering the cached files, there is no cache expiration, since no PHP runs and SWIS can't check the expiration time against the cached page. There's a way around that, but we'll get to that in a minute.
Apache/LiteSpeed
Add the following at the top of your .htaccess file. The main thing is to make sure it is before the # BEGIN WordPress section. If you're using the WebP Variant option, be sure to uncomment that section, and you can also adjust the query string and cookie exclusions too.
If you have installed WordPress in a sub-directory, or are using a custom folder for the SWIS cache, you'll want to update the path in the last couple lines.
# BEGIN SWIS Cache
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^ - [E=SWIS_SCHEME:http-]
RewriteCond %{HTTPS} on [OR]
RewriteCond %{SERVER_PORT} ^443$ [OR]
RewriteCond %{HTTP:X-Forwarded-Proto} https [OR]
RewriteCond %{HTTP:X-Forwarded-Scheme} https
RewriteRule ^ - [E=SWIS_SCHEME:https-]
# Use this for the WebP Variant setting.
# RewriteRule ^ - [E=SWIS_WEBP]
# RewriteCond %{HTTP_ACCEPT} image/webp
# RewriteRule ^ - [E=SWIS_WEBP:-webp]
RewriteCond %{REQUEST_METHOD} GET
# Use the second line if you want to allow any query strings.
RewriteCond %{QUERY_STRING} =""
# RewriteCond %{QUERY_STRING} !^(?!(fbclid|ref|mc_(cid|eid)|utm_(source|medium|campaign|term|content|expid)|gclid|fb_(action_ids|action_types|source)|age-verified|usqp|cn-reloaded|_ga|_ke)).+$
RewriteCond %{HTTP_COOKIE} !(wp-postpass|wordpress_logged_in|comment_author|edd_cart_messages|edd_items_in_cart|edd_saved_cart|sc_checkout_id|sc_customer_id|sc_order_id|woocommerce_items_in_cart|wp_woocommerce_session)
RewriteCond "%{DOCUMENT_ROOT}/wp-content/swis/cache/html/%{HTTP_HOST}%{REQUEST_URI}%{ENV:SWIS_SCHEME}index.html" -f
RewriteRule ^ "/wp-content/swis/cache/html/%{HTTP_HOST}%{REQUEST_URI}%{ENV:SWIS_SCHEME}index.html" [L]
</IfModule>
# END SWIS Cache
Nginx
Add the following to your Nginx configuration, and uncomment the WebP Variant portion if needed. You may also customize the cookie/query-string exclusions as well. Note that the query string exclusions are those which are allowed to have a cached response.
Lastly, make sure the cache directory matches your setup, in case you have WordPress installed in a sub-directory or anything like that.
# cache directory
set $swis_cache_dir '/wp-content/swis/cache/html/';
# default cache keys
set $swis_cache_key_scheme 'http-';
set $swis_cache_key_webp '';
# scheme cache key
if ( $scheme = https ) {
set $swis_cache_key_scheme 'https-';
}
if ( $server_port = 443 ) {
set $swis_cache_key_scheme 'https-';
}
if ( $http_x_forwarded_proto = https ) {
set $swis_cache_key_scheme 'https-';
}
if ( $http_x_forwarded_scheme = https ) {
set $swis_cache_key_scheme 'https-';
}
# webp cache key
# if ( $http_accept ~ image/webp ) {
# set $swis_cache_key_webp '-webp';
# }
# get cache file
set $swis_cache_file_dir ${swis_cache_dir}${http_host}${request_uri};
set $swis_cache_file_name ${swis_cache_key_scheme}index${swis_cache_key_webp}.html;
set $swis_cache_file ${swis_cache_file_dir}${swis_cache_file_name};
location / {
error_page 405 = @fallback;
recursive_error_pages on;
# check request method
if ( $request_method != GET ) {
return 405;
}
# check excluded query strings
if ( $query_string ~ ^(?!(fbclid|ref|mc_(cid|eid)|utm_(source|medium|campaign|term|content|expid)|gclid|fb_(action_ids|action_types|source)|age-verified|usqp|cn-reloaded|_ga|_ke)).+$ ) {
return 405;
}
# check excluded cookies
if ( $http_cookie ~ (wp-postpass|wordpress_logged_in|comment_author|edd_cart_messages|edd_items_in_cart|edd_saved_cart|sc_checkout_id|sc_customer_id|sc_order_id|woocommerce_items_in_cart|wp_woocommerce_session) ) {
return 405;
}
# deliver cache file if it exists
try_files $swis_cache_file @fallback;
}
location @fallback {
try_files $uri $uri/ /index.php?$args;
}
Purge Cache with Cron
If you want to cleanup cache files automatically, or are using server-based rewrites, you can remove expired files with this command. Be sure to update the path and the time (in minutes):
/usr/bin/find /home/user/public_html/wp-content/swis/cache/html/ -type f -iname '*.html' -amin +1440 -print0 2>/dev/null | /usr/bin/xargs -0 rm -f
Also note that you might need to adjust the paths for find and xargs. I have a habit of using absolute paths in my cron jobs, and these might not match your system.