Die perfekte .htaccess Datei für Contao

'Mathias Arzberger'
Mathias Arzberger

Die perfekte .htaccess Datei für Contao für eine gute Platzierung in den Google Suchergebnissen und eine schnelle Webseite.

Der richtige Performanceschub für deine Contao Webseite

Erhöhe die Performance und die Sicherheit deiner Contao Seite mit einfachen Anpassungen in der Konfigurationsdatei .htaccess.

Kompimieren und cachen

Browser-Cache ist ein Puffer-Speicher des Webbrowsers, in dem bereits abgerufene Ressourcen auf dem Rechner des Benutzers als Kopie aufbewahrt werden. Wird eine Ressource später erneut benötigt, ist sie aus dem Cache schneller abrufbar. Ab dem 2. Aufruf einer Webseite hat der Benutzer bereits einen Geschwindigkeitsvorteil. Der Browser Cache bezieht sich hierbei nicht nur auf Bilder, sondern auch auf die HTML-Seiten selbst, sowie dessen Schriftarten, CSS- und Javascript-Dateien. Dies bedeutet für den Server natürlich auch weniger Last und spart Ressourcen. Also los, alles cachen!

Empfehlung

<IfModule mod_rewrite.c>
    RewriteEngine On

    <IfModule mod_headers.c>
        # Assets in /assets and /bundles either contain a hash in their filename
        # or are called with a ?version suffix, therefore cache them for 1 year.
        RewriteRule ^(assets|bundles|files)/ - [ENV=CONTAO_ASSETS:true]
        Header set Cache-Control "max-age=31536000" env=CONTAO_ASSETS

        # Allow CORS on the Contao TinyMCE skin.
        RewriteRule ^assets/tinymce4/js/skins/contao/fonts/ - [ENV=CONTAO_TINYMCE_SKIN:true]
        Header set Access-Control-Allow-Origin "*" env=CONTAO_TINYMCE_SKIN
    </IfModule>

    # Determine the RewriteBase automatically and set it as environment variable.
    # If you are using Apache aliases to do mass virtual hosting or installed the
    # project in a subdirectory, the base path will be prepended to allow proper
    # resolution of the index.php file and to redirect to the correct URI. It will
    # work in environments without path prefix as well, providing a safe, one-size
    # fits all solution. But as you do not need it in this case, you can comment
    # the following 2 lines to eliminate the overhead.
    RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
    RewriteRule ^(.*) - [E=BASE:%1]

    # Sets the HTTP_AUTHORIZATION header removed by Apache
    RewriteCond %{HTTP:Authorization} .
    RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    # Redirect to URI without front controller to prevent duplicate content
    # (with and without `/index.php`). Only do this redirect on the initial
    # rewrite by Apache and not on subsequent cycles. Otherwise we would get an
    # endless redirect loop (request -> rewrite to front controller ->
    # redirect -> request -> ...).
    # So in case you get a "too many redirects" error or you always get redirected
    # to the start page because your Apache does not expose the REDIRECT_STATUS
    # environment variable, you have 2 choices:
    # - disable this feature by commenting the following 2 lines or
    # - use Apache >= 2.3.9 and replace all L flags by END flags and remove the
    #   following RewriteCond (best solution)
    RewriteCond %{ENV:REDIRECT_STATUS} ^$
    RewriteRule ^index\.php(?:/(.*)|$) %{ENV:BASE}/$1 [R=301,L]

    # If the requested filename exists, simply serve it.
    # We only want to let Apache serve files and not directories.
    RewriteCond %{REQUEST_FILENAME} -f
    RewriteRule ^ - [L]

    # Rewrite all other queries to the front controller.
    RewriteRule ^ %{ENV:BASE}/index.php [L]
</IfModule>

<IfModule !mod_rewrite.c>
    <IfModule mod_alias.c>
        # When mod_rewrite is not available, we instruct a temporary redirect of
        # the start page to the front controller explicitly so that the website
        # and the generated links can still be used.
        RedirectMatch 302 ^/$ /index.php/
        # RedirectTemp cannot be used instead
    </IfModule>
</IfModule>

Notwendige Anpassungen

[Update vom 23.03.2023]
Je nach Einstellungen des Hostingpaketes bzw. Servers kann es unter Umständen notwendig sein weitere Angaben in die .htaccess aufzunehmen.

Zusätzliche Einträge in der .htaccess bei ALL-INKL.COM - Neue Medien Münnich

<IfModule mod_expires.c>
  ExpiresActive on
  ExpiresDefault                                      "access plus 1 month"

  # Web Open Font Format (WOFF) 1.0
  ExpiresByType application/font-woff                 "access plus 1 month"
  ExpiresByType application/x-font-woff               "access plus 1 month"
  ExpiresByType font/woff                             "access plus 1 month"

  # Web Open Font Format (WOFF) 2.0
  ExpiresByType application/font-woff2                "access plus 1 month"

  ExpiresByType image/svg+xml                         "access plus 1 month"
  ExpiresByType image/webp                            "access plus 1 month"

  # Other
  ExpiresByType text/x-cross-domain-policy            "access plus 1 week"
</IfModule>

<IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE application/font-woff2
  AddOutputFilterByType DEFLATE application/x-font-woff
  AddOutputFilterByType DEFLATE application/x-web-app-manifest+json font/woff
  AddOutputFilterByType DEFLATE font/woff
  AddOutputFilterByType DEFLATE font/opentype
  AddOutputFilterByType DEFLATE image/svg+xml
  AddOutputFilterByType DEFLATE image/x-icon

  # Exception: Images
  SetEnvIfNoCase REQUEST_URI \.(?:gif|jpg|jpeg|png|svg|webp)$ no-gzip dont-vary

  # Drop problematic browsers
  BrowserMatch ^Mozilla/4 gzip-only-text/html
  BrowserMatch ^Mozilla/4\.0[678] no-gzip
  BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html

  # Make sure proxies don't deliver the wrong content
  Header append Vary User-Agent env=!dont-vary
</IfModule>

Zusätzliche Einträge in der .htaccess bei der webgo GmbH

# Add correct content-type
AddType application/x-font-woff .woff
AddType application/font-woff2  .woff2
AddType image/svg+xml .svg

ExpiresActive on

ExpiresByType application/x-font-woff "access plus 1 year"
ExpiresByType application/font-woff2  "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"

Zusätzliche Einträge in der .htaccess bei IONOS

# gzip-Komprimierung aktivieren
<IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE text/plain
  AddOutputFilterByType DEFLATE text/html
  AddOutputFilterByType DEFLATE text/xml
  AddOutputFilterByType DEFLATE text/shtml
  AddOutputFilterByType DEFLATE text/css
  AddOutputFilterByType DEFLATE text/javascript
  AddOutputFilterByType DEFLATE application/xml
  AddOutputFilterByType DEFLATE application/xhtml+xml
  AddOutputFilterByType DEFLATE application/rss+xml
  AddOutputFilterByType DEFLATE application/javascript
  AddOutputFilterByType DEFLATE application/x-javascript
</IfModule>

Zusätzliche Einträge in der .htaccess bei alfahosting

# Mögliche Einträge bei alfahosting
# gzip-Komprimierung aktivieren
<IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE text/html text/plain text/css application/json
  AddOutputFilterByType DEFLATE application/javascript
  AddOutputFilterByType DEFLATE text/xml application/xml text/x-component
  AddOutputFilterByType DEFLATE application/xhtml+xml application/rss+xml application/atom+xml
  # Compress compressible fonts and svg
  # only uncomment if you dont have compression turned on already. Otherwise it will cause all other filestypes not to get compressed
  AddOutputFilterByType DEFLATE image/x-icon image/svg+xml application/vnd.ms-fontobject application/x-font-ttf font/opentype
</IfModule>

<IfModule mod_expires.c>
  ExpiresActive On
  ExpiresByType image/jpg "access plus 1 year"
  ExpiresByType image/jpeg "access plus 1 year"
  ExpiresByType image/gif "access plus 1 year"
  ExpiresByType image/png "access plus 1 year"
  ExpiresByType text/css "access plus 1 year"
  ExpiresByType text/html "access plus 1 year"
  ExpiresByType application/pdf "access plus 1 year"
  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"
  ExpiresByType application/x-shockwave-flash "access plus 1 year"
  ExpiresByType image/x-icon "access plus 1 year"
  # Add a far future Expires header for fonts
  ExpiresByType application/vnd.ms-fontobject "access plus 1 year"
  ExpiresByType application/x-font-ttf "access plus 1 year"
  ExpiresByType application/x-font-opentype "access plus 1 year"
  ExpiresByType application/x-font-woff "access plus 1 year"
  ExpiresByType image/svg+xml "access plus 1 year"
  ExpiresDefault "access plus 1 month"
</IfModule>

# Fonts
# Add correct content-type for fonts and svg
<IfModule mod_mime.c>
  AddType application/vnd.ms-fontobject .eot 
  AddType application/x-font-ttf .ttf
  AddType application/x-font-opentype .otf
  AddType application/x-font-woff .woff
  AddType image/svg+xml .svg
</IfModule>

Alte .htaccess Version

<IfModule mod_expires.c>
  ExpiresActive on
  ExpiresDefault                                      "access plus 1 month"

  # CSS
  ExpiresByType text/css                              "access plus 1 year"

  # Data interchange
  ExpiresByType application/atom+xml                  "access plus 1 hour"
  ExpiresByType application/rdf+xml                   "access plus 1 hour"
  ExpiresByType application/rss+xml                   "access plus 1 hour"

  ExpiresByType application/json                      "access plus 0 seconds"
  ExpiresByType application/ld+json                   "access plus 0 seconds"
  ExpiresByType application/schema+json               "access plus 0 seconds"
  ExpiresByType application/vnd.geo+json              "access plus 0 seconds"
  ExpiresByType application/xml                       "access plus 0 seconds"
  ExpiresByType text/xml                              "access plus 0 seconds"

  # Favicon (cannot be renamed!) and cursor images
  ExpiresByType image/vnd.microsoft.icon              "access plus 1 week"
  ExpiresByType image/x-icon                          "access plus 1 week"

  # HTML - Behält die Website eine Stunde im Cache, neues wird erst nach Ablauf einer Stunde
  # angezeigt. Wenn nicht gewuenscht, bei 3600 eine Null eintragen
  ExpiresByType text/html                             "access plus 3600 seconds"

  # JavaScript
  ExpiresByType application/javascript                "access plus 1 year"
  ExpiresByType application/x-javascript              "access plus 1 year"
  ExpiresByType text/javascript                       "access plus 1 year"

  # Manifest files
  ExpiresByType application/manifest+json             "access plus 1 week"
  ExpiresByType application/x-web-app-manifest+json   "access plus 0 seconds"
  ExpiresByType text/cache-manifest                   "access plus 0 seconds"

  # Media files
  ExpiresByType audio/ogg                             "access plus 1 month"
  ExpiresByType image/bmp                             "access plus 1 month"
  ExpiresByType image/gif                             "access plus 1 month"
  ExpiresByType image/jpeg                            "access plus 1 month"
  ExpiresByType image/png                             "access plus 1 month"
  ExpiresByType image/svg+xml                         "access plus 1 month"
  ExpiresByType image/webp                            "access plus 1 month"
  ExpiresByType video/mp4                             "access plus 1 month"
  ExpiresByType video/ogg                             "access plus 1 month"
  ExpiresByType video/webm                            "access plus 1 month"

  # Web fonts
  
  # Embedded OpenType (EOT)
  ExpiresByType application/vnd.ms-fontobject         "access plus 1 month"
  ExpiresByType font/eot                              "access plus 1 month"

  # OpenType
  ExpiresByType font/opentype                         "access plus 1 month"

  # TrueType
  ExpiresByType application/x-font-ttf                "access plus 1 month"

  # Web Open Font Format (WOFF) 1.0
  ExpiresByType application/font-woff                 "access plus 1 month"
  ExpiresByType application/x-font-woff               "access plus 1 month"
  ExpiresByType font/woff                             "access plus 1 month"

  # Web Open Font Format (WOFF) 2.0
  ExpiresByType application/font-woff2                "access plus 1 month"

  # Other
  ExpiresByType text/x-cross-domain-policy            "access plus 1 week"
</IfModule>

<IfModule mod_deflate.c>
  # Insert filters / compress text, html, javascript, css, xml:
  AddOutputFilterByType DEFLATE text/plain
  AddOutputFilterByType DEFLATE text/html
  AddOutputFilterByType DEFLATE text/xml
  AddOutputFilterByType DEFLATE text/css
  AddOutputFilterByType DEFLATE text/vtt 
  AddOutputFilterByType DEFLATE text/x-component
  AddOutputFilterByType DEFLATE application/xml
  AddOutputFilterByType DEFLATE application/xhtml+xml
  AddOutputFilterByType DEFLATE application/rss+xml
  AddOutputFilterByType DEFLATE application/js
  AddOutputFilterByType DEFLATE application/javascript
  AddOutputFilterByType DEFLATE application/x-javascript
  AddOutputFilterByType DEFLATE application/x-httpd-php
  AddOutputFilterByType DEFLATE application/x-httpd-fastphp
  AddOutputFilterByType DEFLATE application/atom+xml 
  AddOutputFilterByType DEFLATE application/json
  AddOutputFilterByType DEFLATE application/ld+json 
  AddOutputFilterByType DEFLATE application/vnd.ms-fontobject 
  AddOutputFilterByType DEFLATE application/x-font-ttf
  AddOutputFilterByType DEFLATE application/font-woff2
  AddOutputFilterByType DEFLATE application/x-font-woff
  AddOutputFilterByType DEFLATE application/x-web-app-manifest+json font/woff
  AddOutputFilterByType DEFLATE font/woff 
  AddOutputFilterByType DEFLATE font/opentype
  AddOutputFilterByType DEFLATE image/svg+xml
  AddOutputFilterByType DEFLATE image/x-icon 
  AddOutputFilterByType DEFLATE image/webp 
	
  # Exception: Images
  SetEnvIfNoCase REQUEST_URI \.(?:gif|jpg|jpeg|png|svg|webp)$ no-gzip dont-vary
	
  # Drop problematic browsers
  BrowserMatch ^Mozilla/4 gzip-only-text/html
  BrowserMatch ^Mozilla/4\.0[678] no-gzip
  BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html
	
  # Make sure proxies don't deliver the wrong content
  Header append Vary User-Agent env=!dont-vary
</IfModule>

#Alternative caching using Apache's "mod_headers", if it's installed.
#Caching of common files - ENABLED
<IfModule mod_headers.c>
  <FilesMatch "\.(ico|pdf|flv|swf|js|css|gif|png|jpg|jpeg|txt|webp)$">
    Header set Cache-Control "max-age=2628000, public"
  </FilesMatch>
</IfModule>

<IfModule mod_headers.c>
  <FilesMatch "\.(js|css|xml|gz)$">
    Header append Vary Accept-Encoding
  </FilesMatch>
</IfModule>

# Set Keep Alive Header
<IfModule mod_headers.c>
    Header set Connection keep-alive
</IfModule>

# If your server don't support ETags deactivate with "None" (and remove header)
<IfModule mod_expires.c> 
  <IfModule mod_headers.c> 
    Header unset ETag 
  </IfModule> 
  FileETag None 
</IfModule>

<IfModule mod_headers.c>
  <FilesMatch ".(js|css|xml|gz|html|woff|woff2|ttf)$">
    Header append Vary: Accept-Encoding
  </FilesMatch>
</IfModule>

Fazit

Die .htaccess Datei ist ein wichtiges Werkzeug für Performance und Sicherheit deiner Contao Webseite und sollte regelmäßig an aktuelle Bedürfnisse angepasst werden. Solltest du weitere Empfehlungen für eine Optimierung der .htaccess Datei haben, nehmen wir diese gern auf.

Changelog

  • 13.03.2023 gzip-Komprimierung bei IONOS aktivieren
  • 19.12.2022 Bei einigen Hostern müssen trotzdem einzelne Content-Typen hinzugefügt werden und der Expires Header gesetzt werden.
  • 24.02.2020 mod_deflate webp; hinzugefügt; exception webp; hinzugefügt; mod_headers webp hinzugefügt
  • 26.03.2020 Formatierung angepasst
  • 27.03.2020 Änderung in Zeile 209: Header set Cache-Control "max-age=2592000, public" geändert zu Header set Cache-Control "max-age=2628000, public"
  • 10.06.2020 Komplett neue Version der .htaccess Datei

 

Zurück