feat: EXT:staticfilecache serves cached pages without PHP again, as on TYPO3 10

Every page view goes through TYPO3 13 since the switch; staticfilecache
15.2 writes a gzip copy of each cacheable page, and the TYPO3 10 rewrite
rules in public/.htaccess let Apache deliver it directly (GET, no query
string, no backend login). Pages answer in about 2 ms instead of
0.5-4 s; static and dynamic output are identical for a sample of 22
sitemap URLs.

A flush of the pages cache group (travel data and snow report imports,
"clear frontend caches", deploys) removes the files; a page's own cache
lifetime still applies through the generated per-page .htaccess.

X-SFC-Tags is not passed on: with every record of a page as a tag it
reaches 100+ KB, more than Apache accepts from PHP-FPM, and it would
expose internal record ids. Debug headers stay off for the same reason.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
frommeandClaude Opus 5.5 committed 2026-10-24 19:05:21 +02:00
1 parent df3d823de4
commit 283f54c56c
4 files changed
+233 -1

No files matched your search

+105
View File
@@ -412,6 +412,111 @@ AddDefaultCharset utf-8
# NOTE: Add your additional local storages here
RewriteRule ^(?:fileadmin/|typo3conf/|typo3temp/|uploads/) - [L]
### Begin: StaticFileCache (preparation) ####
# Document root configuration
RewriteRule .* - [E=SFC_ROOT:%{DOCUMENT_ROOT}]
# Cleanup URI
RewriteCond %{REQUEST_URI} ^.*$
RewriteRule .* - [E=SFC_URI:/%{REQUEST_URI}]
RewriteCond %{REQUEST_URI} ^/.*$
RewriteRule .* - [E=SFC_URI:%{REQUEST_URI}]
RewriteCond %{REQUEST_URI} ^/?$
RewriteRule .* - [E=SFC_URI:/]
# Cleanup HOST
RewriteCond %{HTTP_HOST} ^([^:]+)(:[0-9]+)?$
RewriteRule .* - [E=SFC_HOST:%1]
# Get scheme
RewriteRule .* - [E=SFC_PROTOCOL:http]
RewriteCond %{SERVER_PORT} ^443$ [OR]
RewriteCond %{HTTP:X-Forwarded-Proto} https
RewriteRule .* - [E=SFC_PROTOCOL:https]
# Get port
RewriteRule .* - [E=SFC_PORT:80]
RewriteCond %{ENV:SFC_PROTOCOL} ^https$ [NC]
RewriteRule .* - [E=SFC_PORT:443]
RewriteCond %{SERVER_PORT} ^[0-9]+$
RewriteRule .* - [E=SFC_PORT:%{SERVER_PORT}]
RewriteCond %{HTTP:X-Forwarded-Port} ^[0-9]+$
RewriteRule .* - [E=SFC_PORT:%{HTTP:X-Forwarded-Port}]
# Full path for redirect
RewriteRule .* - [E=SFC_FULLPATH:typo3temp/assets/tx_staticfilecache/%{ENV:SFC_PROTOCOL}_%{ENV:SFC_HOST}_%{ENV:SFC_PORT}%{ENV:SFC_URI}/index]
# Extension (Order: br, gzip, default)
RewriteRule .* - [E=SFC_EXT:]
RewriteCond %{HTTP:Accept-Encoding} br [NC]
RewriteRule .* - [E=SFC_EXT:.br]
RewriteCond %{ENV:SFC_ROOT}/%{ENV:SFC_FULLPATH}%{ENV:SFC_EXT} !-f
RewriteRule .* - [E=SFC_EXT:]
RewriteCond %{ENV:SFC_EXT} ^$
RewriteCond %{HTTP:Accept-Encoding} gzip [NC]
RewriteRule .* - [E=SFC_EXT:.gz]
RewriteCond %{ENV:SFC_EXT} ^\.gz$
RewriteCond %{ENV:SFC_ROOT}/%{ENV:SFC_FULLPATH}%{ENV:SFC_EXT} !-f
RewriteRule .* - [E=SFC_EXT:]
# Write Extension to SFC_FULLPATH
RewriteRule .* - [E=SFC_FULLPATH:%{ENV:SFC_FULLPATH}%{ENV:SFC_EXT}]
### Begin: StaticFileCache (main) ####
# We only redirect URI's without query strings
RewriteCond %{QUERY_STRING} ^$
# It only makes sense to do the other checks if a static file actually exists.
RewriteCond %{ENV:SFC_ROOT}/%{ENV:SFC_FULLPATH} -f
# NO frontend or backend user is logged in. Logged in users may see different
# information than anonymous users. But the anonymous version is cached. So
# don't show the anonymous version to logged in users.
RewriteCond %{HTTP_COOKIE} !staticfilecache [NC]
# Avoid cached versions for workspace preview links of users that are not logged in
RewriteCond %{HTTP_COOKIE} !ADMCMD_prev [NC]
# We only redirect GET requests
RewriteCond %{REQUEST_METHOD} GET
# Rewrite the request to the static file.
RewriteRule .* %{ENV:SFC_ROOT}/%{ENV:SFC_FULLPATH} [L]
# Do not allow direct call the cache entries
RewriteCond %{ENV:SFC_URI} ^/typo3temp/assets/tx_staticfilecache/.*
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule .* - [F,L]
### Begin: StaticFileCache (options) ####
# Set proper content type and encoding for compressed html.
<FilesMatch "\.gz$">
SetEnv no-gzip 1
SetEnv no-brotli 1
<IfModule mod_headers.c>
Header set Content-Encoding gzip
</IfModule>
ForceType text/html
</FilesMatch>
<FilesMatch "\.br$">
SetEnv no-gzip 1
SetEnv no-brotli 1
<IfModule mod_headers.c>
Header set Content-Encoding br
</IfModule>
ForceType text/html
</FilesMatch>
# Avoid .br files being delivered with Content-Language: br headers
<IfModule mod_mime.c>
RemoveLanguage .br
</IfModule>
### End: StaticFileCache ###
# If the file/symlink/directory does not exist but is below /typo3/, redirect to the main TYPO3 entry point.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^typo3/(.*)$ %{ENV:CWD}index.php [QSA,L]