.htaccess
es un archivo de configuración de Apache, que nos permite establecer reglas en un directorio. De él puede depender una buena parte del rendimiento de nuestras páginas web.
En este artículo os voy a enseñar mis líneas de .htaccess básicas para cualquier página web.
Nota inicial
.htaccess
se evalúa cada solicitud, añadiendo carga al servidor. Por eso, siempre que sea posible, en producción modifica el archivo httpd.conf
directamente.
Desgraciadamente, esto no es posible para la inmensa mayoría de los mortales (entre los que me incluyo).
Finalmente indicar que buena parte de estas líneas de código vienen gracias a html5 Boilerplate. Creo que recopilarlos aquí y hacerlos accesibles a todos puede ser una buena idea.
Redirección del domino
Hay dos opciones: Que quieras redirigir el dominio con www a sin www (de www.midominio.com a midominio.com) o viceversa. Mantener ambos puede llevar problemas de SEO, o acceso a archivos.
De con www a sin www
RewriteEngine
para que ambos funcionen con la línea RewriteEngine On
si no está activado por defecto# Eliminar www.
<IfModule mod_rewrite.c>
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
</IfModule>
De sin www a con www
<IfModule mod_rewrite.c>
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>
Caché de archivos
La caché de archivos puede ser inmensamente beneficiosa para la velocidad de una web. Básicamente: Si un usuario visita cinco páginas de nuestra web, no tiene por qué descargar los mismos archivos estáticos (como imágenes, css y javascript) cinco veces. El navegador puede almacenar esos archivos en el sistema para obtenerlos mucho más rápidamente, pero para ello necesita instrucciones del servidor.
<IfModule mod_expires.c>
ExpiresActive on
# Por defecto 1 mes de caché
ExpiresDefault "access plus 1 month"
# los manifiestos appcache necesitan solicitarse cada vez, por firefox 3.6 (probablemente no necesario actualmente?
ExpiresByType text/cache-manifest "access plus 0 seconds"
# El HTML nunca debe de ser cacheado
ExpiresByType text/html "access plus 0 seconds"
# Los datos dinámicos tampoco (tal vez podría variar dependiendo de tu aplicación)
ExpiresByType text/xml "access plus 0 seconds"
ExpiresByType application/xml "access plus 0 seconds"
ExpiresByType application/json "access plus 0 seconds"
# Una hora para los feeds (cambiar dependiendo de la fecha de actualización de tu web)
ExpiresByType application/rss+xml "access plus 1 hour"
ExpiresByType application/atom+xml "access plus 1 hour"
# Favicon (Sólo una semana porque el nombre no cambia, luego podría haber cambios y mantenerse el cacheado)
ExpiresByType image/x-icon "access plus 1 week"
# Imágenes, vídeo, audio: 1 mes
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/png "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"
# Fuentes web: 1 mes
ExpiresByType application/x-font-ttf "access plus 1 month"
ExpiresByType font/opentype "access plus 1 month"
ExpiresByType application/x-font-woff "access plus 1 month"
ExpiresByType image/svg+xml "access plus 1 month"
ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
# CSS y JavaScript: 1 año. Ten en cuenta que si cambias los ficheros deberías usar una query string o un nombre de archivo diferente para evitar que los visitantes reciban archivos cacheados.
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
</IfModule>
# Eliminar E-Tag
# Estamos enviando periodos de caché muy amplios, así que no es necesario que el navegador compruebe mediante E-Tag si el fichero cambió
<IfModule mod_headers.c>
Header unset ETag
</IfModule>
FileETag None
Compresión GZIP
GZIP es la manera más rápida de reducir el tamaño del archivo enviado al navegador, mejorando el tiempo de carga. Con las siguientes líneas la activarás en tu web:
<IfModule mod_deflate.c>
# Force compression for mangled headers.
# http://developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping
<IfModule mod_setenvif.c>
<IfModule mod_headers.c>
SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding
RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
</IfModule>
</IfModule>
<IfModule mod_filter.c>
AddOutputFilterByType DEFLATE application/atom+xml \
application/javascript \
application/json \
application/rss+xml \
application/vnd.ms-fontobject \
application/x-font-ttf \
application/x-web-app-manifest+json \
application/xhtml+xml \
application/xml \
font/opentype \
image/svg+xml \
image/x-icon \
text/css \
text/html \
text/plain \
text/x-component \
text/xml
</IfModule>
</IfModule>
Codificación UTF-8
Si alguna vez habéis tenido problemas con caracteres extraños en vuestro servidor, puede ser por dos cosas: La base de datos o el propio servidor, si es por lo segundo, con las siguientes líneas debería de estar solucionado:
AddDefaultCharset utf-8
AddCharset utf-8 .atom .css .js .json .rss .vtt .xml
Forzar IE a no emularse
Puede que la conozcáis o no, pero hay una pequeña cabecera usada por IE llamada X-UA-Compatible
, que puede hacer que IE9 se comporte como si fuera IE7 (por ejemplo). Esto causa bastantes problemas, porque además de usar un navegador menos compilante con los estándares, crea inconsistencias entre versiones, para asegurarse de que IE10 actúa como IE10, IE9 como IE9, etc… y que IE6/7/8 usen Chrome Frame si está instalado:
# Eliminar www.
<IfModule mod_headers.c>
Header set X-UA-Compatible "IE=edge,chrome=1"
# Sólo queremos añadirlo para páginas HTML, el resto es un desperdicio de ancho de banda
<FilesMatch "\.(appcache|crx|css|eot|gif|htc|ico|jpe?g|js|m4a|m4v|manifest|mp4|oex|oga|ogg|ogv|otf|pdf|png|safariextz|svg|svgz|ttf|vcf|webapp|webm|webp|woff|xml|xpi)$">
Header unset X-UA-Compatible
</FilesMatch>
</IfModule>
¿Alguna línea de código más?
Soy todo oídos si tienes algo que aportar :)