Le htaccess est un fichier de configuration de votre serveur, et celui-ci  peut vous rendre énormément service pour les performances de votre site, sur l’expérience utilisateur et sur le référencement naturel. Mais c’est un peu le flou sur la manière de le configurer.

Voici donc un guide pour coder votre fichier htaccess :

Htacces, performances et temps de chargement
Htacces, performances et temps de chargement

Avant propos

Testez, testez et testez !

Chaque code donné ici permet d’optimiser le fichier htaccess pour accélérer votre site, le sécuriser et réduire la bande passante utilisée.

Mais en fonction de la configuration de votre serveur, les codes peuvent ne pas fonctionner : vous devez absolument tester et adapter chaque code en fonction de vos besoins !

Quelques définitions

Pour mieux comprendre cet article, voici quelques explications. N’hésitez pas à me contredire en commentaire si je me trompe.

  • Htaccess : c’est un fichier de configuration pour un serveur web apache. Si vous ne savez pas sur quel type de serveur vous êtes, demandez à votre hébergeur. La configuration qui est inscrite dedans s’applique au répertoire dans lequel il est placé, ainsi que dans tous ses sous-répertoires.
  • Compression Gzip : c’est un format de compression utilisé pour réduire la taille de vos fichiers, et ainsi accélérer votre site.
  • Serveur Apache : c’est le format de serveur http le plus répandu au monde, et que l’on retrouve dans la plupart des offres d’hébergement pros et grand public.
  • Système de cache : le cache d’un site internet ou d’un programme permet d’accéder à des données ou des pages déjà prêtes, sans avoir à les régénérer ou à les recalculer. Si vos pages sont en cache sur votre serveur, les visiteurs y accéderont beaucoup plus vite.
  • Entêtes et requêtes : il s’agit d’informations transmises entre votre ordinateur et le serveur. Ces informations servent aux deux en indiquant différentes informations : emplacement des fichiers, date de mise à jour, configuration, …
  • CHMOD : un chmod permet de modifier les droits d’un fichier en lecture, écriture et exécution, sous la forme de 3 chiffres (exemple : 777 ou 644). Chaque chiffre donne des droits différents en fonction de l’utilisateur : propriétaire, groupe et publique. C’est un point à étudier en détail pour sécuriser un site.

Compression

Compression Gzip via Deflate

Premier point à faire, activez la compression Gzip des fichiers en sortie de votre serveur.

Cela va accélérer le temps de chargement, et réduire la bande passante utilisée. Attention cependant, car cette compression n’est pas supportée par tous les navigateurs (notamment Netscape) et ne fonctionnera que sur des serveurs apaches 2.x.  Testez donc bien votre site sur plusieurs navigateurs après la mise en place de ce code.

# MOD_DEFLATE COMPRESSION
SetOutputFilter DEFLATE
AddOutputFilterByType DEFLATE text/html text/css text/plain text/xml application/x-javascript application/x-httpd-php
#Pour les navigateurs incompatibles
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html
#ne pas mettre en cache si ces fichiers le sont déjà
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip
#les proxies doivent donner le bon contenu
Header append Vary User-Agent env=!dont-vary

Compression Gzip via Mod_Gzip

Le code suivant remplace le précédent  mais fonctionne les serveurs apache 1.x qui ne peuvent gérer le mod_deflate (enfin, d’après ce que j’ai compris)…

RewriteEngine on
#Check to see if browser can accept gzip files. If so and we have it - serve it!
ReWriteCond %{HTTP:accept-encoding} gzip
RewriteCond %{HTTP_USER_AGENT} !Safari
#make sure there's no trailing .gz on the url
ReWriteCond %{REQUEST_FILENAME} !^.+\.gz$
#check to see if a .gz version of the file exists.
RewriteCond %{REQUEST_FILENAME}.gz -f
#All conditions met so add .gz to URL filename (invisibly)
RewriteRule ^(.+) $1.gz [QSA,L]
<IfModule mod_gzip.c>
mod_gzip_on Yes
mod_gzip_dechunk Yes
mod_gzip_keep_workfiles No
mod_gzip_can_negotiate Yes
mod_gzip_add_header_count Yes
mod_gzip_send_vary Yes
mod_gzip_command_version '/mod_gzip_status'
mod_gzip_min_http 1000
mod_gzip_minimum_file_size 300
mod_gzip_maximum_file_size 512000
mod_gzip_maximum_inmem_size 60000
mod_gzip_handle_methods GET POST
mod_gzip_temp_dir /tmp
mod_gzip_item_include file \.html$
mod_gzip_item_include file \.php$
mod_gzip_item_include file \.pl$
mod_gzip_item_include file \.rb$
mod_gzip_item_include file \.py$
mod_gzip_item_include file \.cgi$
mod_gzip_item_include file \.css$
mod_gzip_item_include file \.js$
mod_gzip_item_include mime ^application/javascript$
mod_gzip_item_include mime ^application/x-javascript$
mod_gzip_item_include mime ^text/.*
mod_gzip_item_include mime ^httpd/unix-directory$
mod_gzip_item_include handler ^cgi-script$
mod_gzip_item_include handler ^server-status$
mod_gzip_item_include handler ^server-info$
mod_gzip_item_include handler ^application/x-httpd-php
mod_gzip_item_exclude mime ^image/.*
</IfModule>

Testez la compression de votre site

En plus des outils connus de Firefox comme Yslow et Firebug, voici deux petits sites pour tester votre compression :

Cache et headers

Expire headers

Le Expire header est un atout de taille. Il permet d’indiquer que certains types de fichiers peuvent rester en cache dans le navigateur du visiteur pendant une durée déterminée, sans que le navigateur n’ait besoin de faire des requêtes pour vérifier la validité du cache. Vous allez donc diminuer drastiquement le nombre de requêtes de votre site.

# BEGIN Expire headers
<IfModule mod_expires.c>
 ExpiresActive On
 ExpiresDefault "access plus 7200 seconds"
 ExpiresByType image/jpg "access plus 2592000 seconds"
 ExpiresByType image/jpeg "access plus 2592000 seconds"
 ExpiresByType image/png "access plus 2592000 seconds"
 ExpiresByType image/gif "access plus 2592000 seconds"
 AddType image/x-icon .ico
 ExpiresByType image/ico "access plus 2592000 seconds"
 ExpiresByType image/icon "access plus 2592000 seconds"
 ExpiresByType image/x-icon "access plus 2592000 seconds"
 ExpiresByType text/css "access plus 2592000 seconds"
 ExpiresByType text/javascript "access plus 2592000 seconds"
 ExpiresByType text/html "access plus 7200 seconds"
 ExpiresByType application/xhtml+xml "access plus 7200 seconds"
 ExpiresByType application/javascript A2592000
 ExpiresByType application/x-javascript "access plus 2592000 seconds"
 ExpiresByType application/x-shockwave-flash "access plus 2592000 seconds"
</IfModule>
# END Expire headers

Inutile de vous acharner si vos outils indiquent que les expire headers ne sont pas appliqués sur tous les fichiers. Si comme moi vous utilisez le système publicitaire d’Adsense, vous ne pourrez rien y faire…

Cache-control

Le cache control est un complément de l’expire headers, en fonction du serveur que vous avez ou du navigateur utilisé par vos visiteurs. Là aussi, on va déterminer une durée de cache par type de fichier :

# BEGIN Cache-Control Headers
<IfModule mod_headers.c>
 <FilesMatch "\.(ico|jpe?g|png|gif|swf|css|gz)$">
 Header set Cache-Control "max-age=2592000, public"
 </FilesMatch>
 <FilesMatch "\.(js)$">
 Header set Cache-Control "max-age=2592000, private"
 </FilesMatch>
<filesMatch "\.(html|htm)$">
Header set Cache-Control "max-age=7200, public"
</filesMatch>
# Disable caching for scripts and other dynamic files
<FilesMatch "\.(pl|php|cgi|spl|scgi|fcgi)$">
Header unset Cache-Control
</FilesMatch>
</IfModule>
# END Cache-Control Headers

Les fichiers dynamiques ne sont pas, ou très peu mis en cache (html, php, cgi, …), tandis que le reste est mis en cache pour une longue durée.

La différence entre une cache-control public et private réside dans les proxys. Le paramètre public indique que la mise en cache est pour tout le monde, tandis que private indique que les proxys n’ont pas l’autorisation de mettre en cache.

Le Etag

Ce code permet de désactiver les etags, et donc de réduire encore le nombre de requêtes et votre bande passante utilisée.

Un etag permet de différencier deux versions d’un document ou d’un fichier. Cet Etag est transmis entre votre ordinateur et le serveur lors des requêtes HTTP. Son but est de vérifier si le document a été modifié. Si le fichier est identique, le navigateur utilisera son cache. Mais lors de chaque requête, les informations etags vont être transmises inutilement, surtout si vous avez déjà configuré comme indiqué le reste de votre fichier htaccess.

De plus, sur les serveurs apache, l’identifiant est basé sur la date de dernière modification. Mais si le site est géré par un cluster de plusieurs serveurs, on aura parfois un identifiant différent alors que le fichier n’a jamais été modifié, le tout à cause du etag… (voir sources plus bas)

# KILL THEM ETAGS
Header unset ETag
FileETag none

Et voilà, vous êtes débarrassé une bonne fois pour toute de ces fameux etags.

Sécurité

Protection du fichier htAccess

Nous allons maintenant sécuriser l’accès au fichier htaccess via ce code:

# protect the htaccess file
<files .htaccess>
order allow,deny
deny from all
</files>

Profitez-en pour faire un CHMOD 644 de votre fichier htaccess pour le sécuriser au maximum (vous donnerez ainsi les droits en écriture uniquement à l’admin serveur).

Protection de la lecture des répertoires

Pour éviter que vos visiteurs ne puisse consulter les répertoires qui ne contiennent pas de fichier index, utilisez ce code :

# protection de la lecture des répertoires
 Options -Indexes

Le code Htaccess complet

Et donc le rendu final est :

# MOD_DEFLATE COMPRESSION
SetOutputFilter DEFLATE
AddOutputFilterByType DEFLATE text/html text/css text/plain text/xml application/x-javascript application/x-httpd-php
#Pour les navigateurs incompatibles
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html
#ne pas mettre en cache si ces fichiers le sont déjà
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip
#les proxies doivent donner le bon contenu
Header append Vary User-Agent env=!dont-vary

# BEGIN Expire headers
<IfModule mod_expires.c>
 ExpiresActive On
 ExpiresDefault "access plus 7200 seconds"
 ExpiresByType image/jpg "access plus 2592000 seconds"
 ExpiresByType image/jpeg "access plus 2592000 seconds"
 ExpiresByType image/png "access plus 2592000 seconds"
 ExpiresByType image/gif "access plus 2592000 seconds"
 AddType image/x-icon .ico
 ExpiresByType image/ico "access plus 2592000 seconds"
 ExpiresByType image/icon "access plus 2592000 seconds"
 ExpiresByType image/x-icon "access plus 2592000 seconds"
 ExpiresByType text/css "access plus 2592000 seconds"
 ExpiresByType text/javascript "access plus 2592000 seconds"
 ExpiresByType text/html "access plus 7200 seconds"
 ExpiresByType application/xhtml+xml "access plus 7200 seconds"
 ExpiresByType application/javascript A259200
 ExpiresByType application/x-javascript "access plus 2592000 seconds"
 ExpiresByType application/x-shockwave-flash "access plus 2592000 seconds"
</IfModule>
# END Expire headers

# BEGIN Cache-Control Headers
<IfModule mod_headers.c>
 <FilesMatch "\\.(ico|jpe?g|png|gif|swf|gz|ttf)$">
 Header set Cache-Control "max-age=2592000, public"
 </FilesMatch>
 <FilesMatch "\\.(css)$">
 Header set Cache-Control "max-age=2592000, public"
 </FilesMatch>
 <FilesMatch "\\.(js)$">
 Header set Cache-Control "max-age=2592000, private"
 </FilesMatch>
<filesMatch "\\.(html|htm)$">
Header set Cache-Control "max-age=7200, public"
</filesMatch>
# Disable caching for scripts and other dynamic files
<FilesMatch "\.(pl|php|cgi|spl|scgi|fcgi)$">
Header unset Cache-Control
</FilesMatch>
</IfModule>
# END Cache-Control Headers

# KILL THEM ETAGS
Header unset ETag
FileETag none

# protect wpconfig.php
<files wp-config.php>
order allow,deny
deny from all
</files>

# protect the htaccess file
<files .htaccess>
order allow,deny
deny from all
</files>

# protection de la lecture des répertoires
Options -Indexes

En ce qui concerne mes sources, je ne les ai pas toutes retrouvées… Mon htaccess a évolué au fur et à mesure des mois, et chaque bout de code a été pris à droite à gauche. Dès que je les retrouve toutes, je vous fais signe.

Et si mon htaccess contient des erreurs ou s’il peut être amélioré, dites-le moi (car ce n’est pas vraiment mon domaine d’expertise…).

Article mis à jour le 29 Juin 2010 :
  • Ajout des expires headers pour les favicons
  • Grosse amélioration de Mod_Deflate Compression (merci à RenardDuDezert)
  • Ajout de la protection de la lecture des répertoires (merci à Geal)