Performance-Optimierung (GZIP, Caching, Expires Header etc.) mit Hilfe der .htaccess
In diesem Beitrag findet ihr eine Vorlage für die .htaccess-Datei, mit der die Performance einer Website verbessert werden kann.
Kurze Ladezeiten sind ein wichtiges Qualitätsmerkmal für Websites und werden von Google & Co. als Bewertungskriterium herangezogen. Eine Möglichkeit um die Geschwindigkeit der eigenen Seite zu erhöhen führt über die .htaccess-Datei. Hier können Ablaufdaten für verschiedene Dateitypen oder die Kompression mittels GZIP/Brotli eingerichtet werden. In diesem Beitrag archivieren wir eine Standard-Vorlage für die .htaccess.
Kompression, Caching & Performance-Optimierung in der .htaccess
Die folgende Methode funktioniert nur für Apache-Webserver, da Nginx-Server die Regeln in einer anderen Syntax und in einer anderen Datei erwarten. Bevor ihr Änderungen vornehmt, solltet ihr zunächst ein Backup der .htaccess-Datei erstellen! Anschließend könnt ihr den folgenden Code einfügen.
Zuerst werden die Medientypen (MIME-Type) definiert, die der Webserver für moderne Dateiformate (Schriften, Bilder, Videos, Audio, Manifeste) verwenden soll, damit Browser diese Dateien korrekt interpretieren und darstellen können. Danach wird festgelegt, welche Dateien komprimiert werden sollen. Standardmäßig wird dafür Gzip als Kompressions-Methode verwendet. Falls verfügbar, wird die modernere und effektivere Brotli-Methode benutzt. Anschließend werden für jeden Dateityp die Vorhaltezeiten für das Browser-Caching definiert. Für Dateien, die sich typischerweise häufig ändern (HTML, JSON etc.), sind kurze Zeiträume definiert. Für eher statische Assets (Bilder, Videos, Audio etc.) gelten dagegen lange Vorhaltezeiten.
# ----------------------------------------------------------------------
# Compression and Caching
# ----------------------------------------------------------------------
<IfModule mod_mime.c>
# --- Manifest ---
AddType application/manifest+json .webmanifest
# --- Fonts ---
AddType font/woff2 .woff2
AddType font/woff .woff
# --- Images ---
AddType image/svg+xml .svg .svgz
AddType image/webp .webp
AddType image/avif .avif
AddType image/x-icon .ico
# --- Video ---
AddType video/mp4 .mp4
AddType video/ogg .ogv
AddType video/webm .webm
# --- Audio ---
AddType audio/mpeg .mp3
AddType audio/ogg .ogg
AddType audio/webm .weba
</IfModule>
<IfModule mod_deflate.c>
# Exclude already-compressed files from further compression
<IfModule mod_setenvif.c>
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|webp|avif|ico|svgz|zip|gz|gzip|bz2|br|rar|7z|mp4|mp3|webm|ogv|ogg|weba|woff|woff2|pdf)$ no-gzip
</IfModule>
# Compress text-based MIME types
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/json
AddOutputFilterByType DEFLATE application/ld+json
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/atom+xml
AddOutputFilterByType DEFLATE application/manifest+json
AddOutputFilterByType DEFLATE image/svg+xml
</IfModule>
<IfModule mod_brotli.c>
# Compress text-based content with Brotli (better compression than gzip)
AddOutputFilterByType BROTLI_COMPRESS text/html
AddOutputFilterByType BROTLI_COMPRESS text/plain
AddOutputFilterByType BROTLI_COMPRESS text/xml
AddOutputFilterByType BROTLI_COMPRESS text/css
AddOutputFilterByType BROTLI_COMPRESS text/javascript
AddOutputFilterByType BROTLI_COMPRESS application/javascript
AddOutputFilterByType BROTLI_COMPRESS application/x-javascript
AddOutputFilterByType BROTLI_COMPRESS application/json
AddOutputFilterByType BROTLI_COMPRESS application/ld+json
AddOutputFilterByType BROTLI_COMPRESS application/xml
AddOutputFilterByType BROTLI_COMPRESS application/xhtml+xml
AddOutputFilterByType BROTLI_COMPRESS application/rss+xml
AddOutputFilterByType BROTLI_COMPRESS application/atom+xml
AddOutputFilterByType BROTLI_COMPRESS application/manifest+json
AddOutputFilterByType BROTLI_COMPRESS image/svg+xml
</IfModule>
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 0 seconds"
# -- HTML/XML (short cache) ---
ExpiresByType text/html "access plus 60 seconds"
ExpiresByType application/xhtml+xml "access plus 60 seconds"
# --- Manifest (moderate cache) ---
ExpiresByType application/manifest+json "access plus 1 day"
# --- Data/Feeds (short cache) ---
ExpiresByType application/json "access plus 5 minutes"
ExpiresByType application/ld+json "access plus 5 minutes"
ExpiresByType application/xml "access plus 5 minutes"
ExpiresByType text/xml "access plus 5 minutes"
ExpiresByType application/rss+xml "access plus 5 minutes"
ExpiresByType application/atom+xml "access plus 5 minutes"
# --- CSS/JS (long cache) ---
ExpiresByType text/css "access plus 1 year"
ExpiresByType text/javascript "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType application/x-javascript "access plus 1 year"
# --- Fonts (long cache) ---
ExpiresByType font/woff "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
# --- Images (long cache) ---
ExpiresByType image/avif "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/x-icon "access plus 1 year"
# --- Video (long cache) ---
ExpiresByType video/mp4 "access plus 1 year"
ExpiresByType video/ogg "access plus 1 year"
ExpiresByType video/webm "access plus 1 year"
# -- Audio: long cache ---
ExpiresByType audio/mpeg "access plus 1 year"
ExpiresByType audio/ogg "access plus 1 year"
ExpiresByType audio/webm "access plus 1 year"
# --- Other (long cache) ---
ExpiresByType application/pdf "access plus 1 year"
</IfModule>
<IfModule mod_headers.c>
# Remove ETag (rely on Cache-Control instead for better CDN compatibility)
Header unset ETag
FileETag None
# Set Vary header for content negotiation
Header set Vary "Accept-Encoding"
# Security headers
Header always set X-Content-Type-Options "nosniff"
# Remove WordPress headers from static assets
<FilesMatch "\.(css|js|jpg|jpeg|png|gif|webp|avif|svg|svgz|ico|woff|woff2|mp4|mp3|ogg|ogv|webm|weba|pdf|json|xml|webmanifest)$">
Header unset Pragma
Header unset Set-Cookie
</FilesMatch>
# -- HTML/XML (short cache) ---
<FilesMatch "\.(html|htm|xhtml)$">
Header set Cache-Control "public, max-age=60, stale-while-revalidate=86400"
</FilesMatch>
# --- Manifest (moderate cache) ---
<FilesMatch "\.webmanifest$">
Header set Cache-Control "public, max-age=86400"
</FilesMatch>
# --- Data/Feeds (short cache) ---
<FilesMatch "\.(json|xml)$">
Header set Cache-Control "public, max-age=300, stale-if-error=3600"
</FilesMatch>
# --- CSS/JS (long cache) ---
<FilesMatch "\.(css|js)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
# --- Fonts (long cache) ---
<FilesMatch "\.(woff|woff2)$">
Header set Cache-Control "public, max-age=31536000, immutable"
Header set Access-Control-Allow-Origin "*"
</FilesMatch>
# --- Images (long cache) ---
<FilesMatch "\.(jpg|jpeg|png|gif|webp|avif|svg|svgz|ico)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
# --- Video (long cache) ---
<FilesMatch "\.(mp4|webm|ogv)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
# -- Audio: long cache ---
<FilesMatch "\.(mp3|ogg|weba)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
# --- Other (long cache) ---
<FilesMatch "\.pdf$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
</IfModule>
Hallo Jonas,
wie sieht es bzgl. der Performance aus? Sollte man hierbei nicht nur das übernehmen was man auch wirklich auf der Webseite / Shop / Blog verwendet? Schliesslich müsste der Webserver diese auch komplett bei jedem Aufruf verarbeiten und entsprechende Module aktivieren, die eventuell nicht vorhanden sind.
Ich versuche gerade bei den Umleitungen, Cache und auch beim Quellcode immer nur so wenig wie möglich und so viel wie nötig zu verwenden. Gerade was die ganzen Schriftarten angeht, wenn man entsprechende nicht verwendet spart man sich hier auch eine Menge an unnötigen Text und schafft mehr „Übersicht“.
Hallo Danny, du hast vollkommen recht. Dieser Beitrag fasst einige mögliche Optimierungen zum schnellen Copy+Paste zusammen. Hier je nach Bedarf anzupassen macht durchaus Sinn.