Menü schliessen
Created: December 8th 2011
Last updated: May 1st 2020
Categories: Common Web Development,  Joomla,  Typo3
Author: Marcus Fleuti

Optimizing web page response - compression - caching-gzip-deflate - header optimizations - MIME - htaccess - Typo3 - Joomla - Wordpress

Donation Section: Background
Monero Badge: QR-Code
Monero Badge: Logo Icon Donate with Monero Badge: Logo Text
82uymVXLkvVbB4c4JpTd1tYm1yj1cKPKR2wqmw3XF8YXKTmY7JrTriP4pVwp2EJYBnCFdXhLq4zfFA6ic7VAWCFX5wfQbCC

Commonly used .htaccess parameters for optimizing Compressions (gzip, deflate), header optimizations, defining font MIME types etc.

We've been experimenting with various parameters over a longer period and measured the performance of various pages with YSlow. Using these settings in the .htaccess file has given a major performance improvement on our websites:

Typo3 :: .htaccess settings

In order to have a fast and reliable Typo3 setup you should use these .htaccess settings and enable the [BE][compressionLevel] and [FE][compressionLevel] settings in the Install tool.

Note: If possible you should enable the lockSSL option in the Install Tool to force the user to user SSL in the backend: [BE][lockSSL] = 2

#Always forward any site request to your default domain to prohibit "duplicate content" issues for the search engines. 
#This is a SEO option. Please exchange "myDomain.tld" with your domain name and uncomment the next 3 lines.
#RewriteEngine On
#RewriteCond %{HTTP_HOST} !^www\.myDomain\.tld$ [NC]
#RewriteRule ^(.*)$ http://www.myDomain.tld/$1 [L,R=301]

### Begin: Compression via TYPO3 ###
<FilesMatch "\.js\.gzip$">
    AddType "text/javascript" .gzip
</FilesMatch>
<FilesMatch "\.css\.gzip$">
    AddType "text/css" .gzip
</FilesMatch>
AddEncoding gzip .gzip

# Basic security checks
# - Restrict access to deleted files in Recycler directories
# - Restrict access to TypoScript files in default templates directories
# - Restrict access to Private extension directories
RewriteRule ^fileadmin/(.*/)?_recycler_/ - [F]
RewriteRule ^fileadmin/templates/.*(\.txt|\.ts)$ - [F]
RewriteRule ^typo3conf/ext/[^/]+/Resources/Private/ - [F]

# Stop rewrite processing, if we are in the typo3/ directory.
RewriteRule ^(typo3/|t3lib/|fileadmin/|typo3conf/|typo3temp/|uploads/|favicon\.ico) - [L]

# If the file/symlink/directory does not exist => Redirect to index.php.
# For httpd.conf, you need to prefix each '%{REQUEST_FILENAME}' with '%{DOCUMENT_ROOT}'.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l

# Main URL rewriting.
RewriteRule .* index.php [L]

Joomla :: .htaccess settings

Most of these settings are recommended by the Joomla core development team.

Note: You should force the usage of SSL for the Administrator backend (System configuration -> Server -> Force SSL)

#Always forward any site request to your default domain to prohibit "duplicate content" issues for the search engines. 
#This is a SEO option. Please exchange "myDomain.tld" with your domain name and uncomment the next 3 lines.
RewriteEngine On

#RewriteCond %{HTTP_HOST} !^www\.myDomain\.tld$ [NC]
#RewriteRule ^(.*)$ http://www.myDomain.tld/$1 [L,R=301]

## Can be commented out if causes errors
Options +FollowSymLinks

## Begin - Joomla! core SEF Section.
#
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
#
# If the requested path and file is not /index.php and the request
# has not already been internally rewritten to the index.php script
RewriteCond %{REQUEST_URI} !^/index\.php
# and the request is for something within the component folder,
# or for the site root, or for an extensionless URL, or the
# requested URL ends with one of the listed extensions
RewriteCond %{REQUEST_URI} /component/|(/[^.]*|\.(php|html?|feed|pdf|vcf|raw))$ [NC]
# and the requested path and file doesn't directly match a physical file
RewriteCond %{REQUEST_FILENAME} !-f
# and the requested path and file doesn't directly match a physical folder
RewriteCond %{REQUEST_FILENAME} !-d
# internally rewrite the request to the index.php script
RewriteRule .* index.php [L]
#
## End - Joomla! core SEF Section.

WordPress :: .htacess settings

Most of these settings are recommended by the WordPress core development team.

Note: You should force SSL for the WordPress backend by setting the following parameter within /wp-config.php:

define('FORCE_SSL_ADMIN', true);

 

#Always forward any site request to your default domain to prohibit "duplicate content" issues for the search engines. 
#This is a SEO option. Please exchange "myDomain.tld" with your domain name and uncomment the next 3 lines.
#RewriteEngine On
#RewriteCond %{HTTP_HOST} !^www\.myDomain\.tld$ [NC]
#RewriteRule ^(.*)$ http://www.myDomain.tld/$1 [L,R=301]

#Settings for supporting WordPress Permalinks
RewriteRule ^index\.php$ – [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

#Securing WordPress
#Protect the wp-config.php file
<files wp-config.php>
order allow,deny
deny from all
</files>

Common :: .htacess settings

The common settings can and should be attached to one of the above described settings for an individual CMS

#Always forward any site request to your default domain to prohibit "duplicate content" issues for the search engines. 
#This is a SEO option. Please exchange "myDomain.tld" with your domain name and uncomment the next 3 lines.
#RewriteEngine On
#RewriteCond %{HTTP_HOST} !^www\.myDomain\.tld$ [NC]
#RewriteRule ^(.*)$ http://www.myDomain.tld/$1 [L,R=301]

## Begin - Rewrite rules to block out some common exploits.
# If you experience problems on your site block out the operations listed below
# This attempts to block the most common type of exploit `attempts` to Joomla!
#
# Block out any script trying to base64_encode data within the URL.
RewriteCond %{QUERY_STRING} base64_encode[^(]*\([^)]*\) [OR]
# Block out any script that includes a <script> tag in URL.
RewriteCond %{QUERY_STRING} (<|%3C)([^s]*s)+cript.*(>|%3E) [NC,OR]
# Block out any script trying to set a PHP GLOBALS variable via URL.
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
# Block out any script trying to modify a _REQUEST variable via URL.
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
# Return 403 Forbidden header and show the content of the root homepage
RewriteRule .* index.php [F]
## End - Rewrite rules to block out some common exploits.

##
# Uncomment following line if your webserver's URL
# is not directly related to physical file paths.
# Update Your Joomla! Directory (just / for root).
##
# RewriteBase /

#Protect the .htaccess file itself
<files ~ "^.*\.([Hh][Tt][Aa])">
order allow,deny 
deny from all 
satisfy all 
</files>

#No directory listing
Options -Indexes
#If you like to turn Indexes on (+Indexes) you could also turn on fancy indexing (show icons, file sizes, modification date etc.)
#IndexOptions +FancyIndexing

#webfont MIME encoding. Google Chrome likes that.
AddType application/vnd.ms-fontobject .eot
AddType font/ttf .ttf
AddType font/otf .otf
AddType application/x-font-woff .woff

# Set Expires Headers
<ifModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault "access plus 1 month"

    # cache.appcache needs re-requests in FF 3.6
    ExpiresByType text/cache-manifest "access plus 0 seconds"

    # Your document html
    ExpiresByType text/html "access plus 1 hour"

    # Data
    ExpiresByType text/xml "access plus 0 seconds"
    ExpiresByType application/xml "access plus 0 seconds"
    ExpiresByType application/json "access plus 0 seconds"

    # RSS feed
    ExpiresByType application/rss+xml "access plus 1 hour"

    # Favicon (cannot be renamed)
    ExpiresByType image/x-icon "access plus 1 month"

    # Media: images, video, audio
    ExpiresByType image/gif "access plus 1 month"
    ExpiresByType image/png "access plus 1 month"
    ExpiresByType image/jpg "access plus 1 month"
    ExpiresByType image/jpeg "access plus 1 month"
    ExpiresByType video/ogg "access plus 1 month"
    ExpiresByType audio/ogg "access plus 1 month"
    ExpiresByType video/mp4 "access plus 1 month"
    ExpiresByType video/webm "access plus 1 month"

    # HTC files  (css3pie)
    ExpiresByType text/x-component "access plus 1 month"

    # Webfonts
    ExpiresByType font/truetype "access plus 1 year"
    ExpiresByType font/opentype "access plus 1 year"
    ExpiresByType application/x-font-woff   "access plus 1 year"
    ExpiresByType image/svg+xml "access plus 1 year"
    ExpiresByType application/vnd.ms-fontobject "access plus 1 year"

    # CSS and JavaScript
    ExpiresByType text/css "access plus 1 year"
    ExpiresByType application/javascript "access plus 1 year"
    ExpiresByType text/javascript "access plus 1 year"
</ifModule>

<ifModule mod_headers.c>
    #Set default cache control header to 1 WEEK
    Header unset Cache-Control
    Header set Cache-Control "max-age=604800, public, must-revalidate"

    # Force no caching for dynamic files like PHP scripts since it causes troubles with lots of content management systems like Typo3 or Joomla.
    <FilesMatch ".(php|cgi|pl|htm|html)$">
        <ifModule mod_expires.c>
            ExpiresDefault A0
        </ifModule>
        Header unset Cache-Control
        Header set Cache-Control "no-store, no-cache, must-revalidate, max-age=0, pre-check=0, post-check=0"
    </FilesMatch>

    # 1 WEEK
    <FilesMatch ".(css|js|xml)$">
        Header unset Cache-Control
        Header set Cache-Control "max-age=604800, public, must-revalidate"
    </FilesMatch>

    # 1 MONTH
    <FilesMatch ".(avi|mov|ppt|doc|docx|xls|xlsx|ppt|pptx|mp3|wmv|wav|ico|pdf|flv|jpg|jpeg|png|gif|swf|txt)$">
        ### By disabling "Last-Modified" globally and ETag and setting an expiration to now+xx days these filetypes
        ### will not be revalidated again once they're downloaded. This means that there won't be even any re-request by the browser on these files
        ### until the originally set expiration date is set. This represents a large optimization potential because it minimizes server requests dramatically
        ### but it might lead to confusion at the development stage. Thus for development you should disable all caching using the options below.
        ### Nevertheless if you use the browsers' reload or clear cache functions you can force loading the data from server.
        Header unset Cache-Control
        Header set Cache-Control "max-age=2592000, public"
        #Since we're not revalidating here no ETag is required
        FileETag None
        Header unset ETag
    </FilesMatch>

    #This is what Google wants
    <FilesMatch "\.(js|css|xml|gz)$">
        Header append Vary: Accept-Encoding
    </FilesMatch>

    Header unset Last-Modified
    Header unset Pragma

    ### disable caching for development/debugging purposes
    #Header unset Cache-Control
    #Header set Cache-Control: "no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0"
    #Header unset ETag
    #Header set Pragma "no-cache"
    #Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
</ifModule>

# Deflate Compression by FileType
<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/plain
    AddOutputFilterByType DEFLATE text/html
    AddOutputFilterByType DEFLATE text/xml
    AddOutputFilterByType DEFLATE text/css
    AddOutputFilterByType DEFLATE application/xml
    AddOutputFilterByType DEFLATE application/xhtml+xml
    AddOutputFilterByType DEFLATE application/rss+xml
    AddOutputFilterByType DEFLATE application/javascript
    AddOutputFilterByType DEFLATE application/x-javascript
    AddOutputFilterByType DEFLATE x-font/otf x-font/ttf x-font/eot
</IfModule>

# gzip Compression if availiable
<IfModule mod_gzip.c>
    mod_gzip_on                     Yes
    mod_gzip_dechunk                Yes
    mod_gzip_keep_workfiles         No
    mod_gzip_minimum_file_size      300
    mod_gzip_maximum_file_size      1000000
    mod_gzip_maximum_inmem_size     1000000
    mod_gzip_item_include file      \.(html?|txt|css|js|php|pl|xml)$
    mod_gzip_item_include handler   ^cgi-script$
    mod_gzip_item_include mime      ^text/.*
    mod_gzip_item_include mime      ^application/javascript.*
    mod_gzip_item_include mime      ^application/x-javascript.*
    # Exclude old browsers and images since IE has trouble with this
    mod_gzip_item_exclude reqheader "User-Agent: .*Mozilla/4..*["
    mod_gzip_item_exclude mime      ^image/.*
    mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</IfModule>

Hint :: SSL Redirect

A special case would be SSL redirect. Instead of using SSL extensions in your CMS you could forward the user to an SSL page using a .htaccess entry like this:

RewriteCond %{SERVER_PORT} 80 
RewriteRule ^(.*)$ https://www.myDomain.tld/$1 [L,R=301]