These interests are the main reasons for many blog authors to switch to static site generators like Jekyll or Hugo. Performance and security is always a thing you should be aware of when hosting a website, but I am feeling comfortable with the WordPress right now and my guest authors like to write posts with the Gutenberg editor as well. After reading a post by Delicious Brains about their suggestion in caching WordPress by directly serving cached html files with Nginx before running PHP, I started to improve my setup by something similar with WP-Super-Cache.

listen 80;
listen [::]:80;

include /etc/nginx/inc.d/php.conf;
include /etc/nginx/inc.d/caching.conf;

index index.php index.html index.htm;

access_log off;

location = /favicon.ico {
  log_not_found off;
  access_log off;
}

location = /robots.txt {
  log_not_found off;
  access_log off;
  allow all;
}

# WP Super Cache rules.
set $cache_uri $request_uri;

# POST requests and urls with a query string should always go to PHP
if ($request_method = POST) {
  set $cache_uri 'null cache';
}

if ($query_string != "") {
  set $cache_uri 'null cache';
}

# Don't cache uris containing the following segments
if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|/feed/|index.php|wp-comments-popup.php|wp-links-opml.php|wp-locations.php|sitemap(_index)?.xml|[a-z0-9_-]+-sitemap([0-9]+)?.xml)") {
  set $cache_uri 'null cache';
}

# Don't use the cache for logged in users or recent commenters
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in") {
  set $cache_uri 'null cache';
}

# We only listen to https (index-https.html). For http use: index.html
set $cache_file "/wp-content/cache/supercache/$http_host$cache_uri/index-https.html";

# Use cached or actual file if they exists, otherwise pass request to WordPress
location / {
  # If we add index.php?$args its break WooCommerce like plugins # Ref: #330
  try_files $cache_file $uri $uri/ /index.php;
}

# uncomment to get cache file as header for debugging
# add_header X-Cache-File $cache_file;

https://wordpress.org/support/article/nginx/#wp-super-cache-rules

Benchmarks

With WP-Sucher-Cache only:

This is ApacheBench, Version 2.3 <$Revision: 1807734 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking www.zahnarzt-bracke.de (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests


Server Software:        nginx
Server Hostname:        www.zahnarzt-bracke.de
Server Port:            443
SSL/TLS Protocol:       TLSv1.2,ECDHE-RSA-AES128-GCM-SHA256,4096,128
TLS Server Name:        www.zahnarzt-bracke.de

Document Path:          /
Document Length:        23657 bytes

Concurrency Level:      100
Time taken for tests:   189.528 seconds
Complete requests:      10000
Failed requests:        0
Total transferred:      238650000 bytes
HTML transferred:       236570000 bytes
Requests per second:    52.76 [#/sec] (mean)
Time per request:       1895.276 [ms] (mean)
Time per request:       18.953 [ms] (mean, across all concurrent requests)
Transfer rate:          1229.67 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:      104 1024 317.8   1015    4142
Processing:   140  863 361.8    783    4208
Waiting:       38  729 319.8    663    2866
Total:        499 1887 447.0   1838    6282

Percentage of the requests served within a certain time (ms)
  50%   1838
  66%   1993
  75%   2102
  80%   2181
  90%   2425
  95%   2674
  98%   3026
  99%   3351
 100%   6282 (longest request)

With WP-Super-Cache and Nginx try_files combo:

This is ApacheBench, Version 2.3 <$Revision: 1807734 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking www.zahnarzt-bracke.de (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests


Server Software:        nginx
Server Hostname:        www.zahnarzt-bracke.de
Server Port:            443
SSL/TLS Protocol:       TLSv1.2,ECDHE-RSA-AES128-GCM-SHA256,4096,128
TLS Server Name:        www.zahnarzt-bracke.de

Document Path:          /
Document Length:        23657 bytes

Concurrency Level:      100
Time taken for tests:   119.667 seconds
Complete requests:      10000
Failed requests:        0
Total transferred:      238470000 bytes
HTML transferred:       236570000 bytes
Requests per second:    83.57 [#/sec] (mean)
Time per request:       1196.666 [ms] (mean)
Time per request:       11.967 [ms] (mean, across all concurrent requests)
Transfer rate:          1946.08 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:      110  860 383.1    808    6969
Processing:    62  332 185.2    288    2479
Waiting:       24  228 156.2    197    1827
Total:        269 1192 434.0   1128    7222

Percentage of the requests served within a certain time (ms)
  50%   1128
  66%   1257
  75%   1353
  80%   1425
  90%   1674
  95%   1965
  98%   2463
  99%   2811
 100%   7222 (longest request)

Conclusion

I am not quite sure if this helped anyway, but even the idea of serving already existing static html files directly with Nginx feels good …

Real static page

If you want to bring this idea even further, you should probably check out this little plugin: Simple-static