Skip to content

Todo para WordPress, el desarrollo web — y mucho más

🛠 Cómo añadir cabeceras Expires en .htaccess: guía paso a paso

🛠 Cómo añadir cabeceras Expires en .htaccess: guía paso a paso

Usted ejecutó una prueba en GTmetrix y ahí aparece en rojo: «Add Expires Headers». Una imagen familiar. El sitio está en WordPress, el hosting en Apache, y la prueba de velocidad le exige configurar el caché del navegador mediante .htaccess.

El error no es crítico, pero sí molesto. Sin los encabezados Expires, el navegador recarga imágenes, CSS y scripts desde el servidor en cada visita. Una y otra vez. Incluso si nada ha cambiado. La velocidad cae, los usuarios esperan, Google baja las posiciones.

Usted puede solucionarlo en cinco minutos. Dos métodos: manualmente con código en.htaccess o con un plugin en dos clics. A continuación, ambos, con código listo para usar y configuraciones.

💡 Resumen rápido:

  • Comprenda cómo los encabezados Expires y Cache-Control gestionan el caché del navegador
  • Añada código listo para usar a.htaccess: copie, pegue, verifique
  • Instale el plugin AEH Speed Optimization en un minuto si no quiere tocar código
  • Configure períodos de caché óptimos para imágenes, CSS, JS y fuentes

Cómo funcionan los encabezados Expires

Cuando un visitante llega a un sitio, el navegador carga decenas de archivos: la página HTML, estilos CSS, JavaScript, fuentes, iconos, imágenes. Cada archivo es una solicitud HTTP independiente al servidor. Cuantas más solicitudes, mayor es el tiempo de carga.

El encabezado Expires le dice al navegador: «este archivo no cambia, guárdelo en caché y no lo vuelva a pedir hasta tal fecha». En visitas repetidas, el navegador toma los archivos del caché local en lugar de descargarlos nuevamente del servidor. Resultado: decenas de solicitudes menos y una carga rápida.

El equivalente moderno es el encabezado Cache-Control con la directiva max-age. Establece la duración del caché en segundos, no una fecha concreta, y hoy se considera el principal. Recomendamos configurar ambos encabezados simultáneamente: Expires para navegadores antiguos y proxies, Cache-Control para todo lo moderno. Ambos se escriben en el mismo bloque de.htaccess.

Error de cabeceras de expiración en informe GTmetrix

Método 1: código en.htaccess

El camino más directo es añadir las reglas de caché directamente al archivo de configuración de Apache. El archivo .htaccess se encuentra en la raíz del sitio (el mismo lugar donde está wp-config.php). Si no lo ve, active la visualización de archivos ocultos en su cliente FTP o en el gestor de archivos del hosting.

Antes de editar, descargue una copia del archivo a su computadora. Un error de sintaxis en.htaccess puede tumbar el sitio con un error 500; una copia de seguridad le permite volver atrás en un segundo.

Abra .htaccess en un editor y añada el siguiente bloque antes de # BEGIN WordPress:

1 # Browser caching: Expires and Cache-Control headers
2<IfModule mod_expires.c>
3 ExpiresActive On
4
5 # Images
6 ExpiresByType image/jpg "access plus 1 year"
7 ExpiresByType image/jpeg "access plus 1 year"
8 ExpiresByType image/gif "access plus 1 year"
9 ExpiresByType image/png "access plus 1 year"
10 ExpiresByType image/webp "access plus 1 year"
11 ExpiresByType image/avif "access plus 1 year"
12 ExpiresByType image/svg+xml "access plus 1 year"
13 ExpiresByType image/x-icon "access plus 1 year"
14
15 # CSS and JavaScript
16 ExpiresByType text/css "access plus 1 month"
17 ExpiresByType application/javascript "access plus 1 month"
18
19 # Fonts
20 ExpiresByType font/woff2 "access plus 1 year"
21 ExpiresByType font/woff "access plus 1 year"
22
23 # PDF and other documents
24 ExpiresByType application/pdf "access plus 1 month"
25
26 # Default
27 ExpiresDefault "access plus 2 days"
28</IfModule>
29
30 # Cache-Control headers for modern browsers
31<IfModule mod_headers.c>
32 &lt;FilesMatch &quot;\.(jpg|jpeg|png|gif|webp|avif|svg|ico|woff2|woff)$&quot;&gt;
33 Header set Cache-Control "max-age=31536000, public"
34 </FilesMatch>
35 &lt;FilesMatch &quot;\.(css|js)$&quot;&gt;
36 Header set Cache-Control "max-age=2592000, public"
37 </FilesMatch>
38</IfModule>

Qué está ocurriendo aquí. El primer bloque <IfModule mod_expires.c> activa el módulo Expires y establece los períodos de almacenamiento para cada tipo de archivo. Un año para imágenes y fuentes, que casi nunca cambian. Un mes para CSS y JavaScript, que se actualizan periódicamente.

El segundo bloque <IfModule mod_headers.c> añade el moderno Cache-Control con los mismos períodos pero en segundos: 31536000 = un año, 2592000 = un mes.

Importante: los módulos mod_expires y mod_headers deben estar habilitados en el servidor. En la mayoría de los hostings Apache están activos por defecto: el soporte los habilita durante la configuración inicial. Si el caché no funciona después de guardar, escriba al soporte de hosting: «habilite mod_expires y mod_headers».

Después de pegar, guarde el archivo y súbalo de nuevo a la raíz del sitio. Abra el sitio en un navegador, vaya a DevTools (F12) → Network → actualice la página. Haga clic en cualquier archivo CSS o JS; en la pestaña Headers debería ver Expires y Cache-Control con valores distintos de cero.

Ejecute GTmetrix de nuevo; el error debería haber desaparecido.

Método 2: plugin AEH Speed Optimization

Si no quiere manipular.htaccess manualmente, existe un plugin. Antes se llamaba simplemente Add Expires Headers; hoy ha evolucionado a AEH Speed Optimization. Además de los encabezados de caché, puede realizar minificación de CSS, carga diferida de imágenes y compresión.

Página del plugin AEH Speed Optimization en el catálogo de WordPress

Pasos de instalación:

  • Plugins → Añadir nuevo, en la búsqueda escriba «AEH Speed Optimization»

  • Haga clic en Instalar ahora, luego en Activar

  • Vaya a Ajustes → AEH Speed Optimization

  • En la pestaña Cache Settings, marque los tipos de archivo y establezca los períodos de almacenamiento en días

Ajustes de caché en el plugin AEH Speed Optimization
  • Haga clic en Enviar

El plugin escribirá las reglas en.htaccess por sí mismo; usted no necesita escribir una sola línea de código. Para la mayoría de los sitios, la versión gratuita es suficiente. La versión Pro añade compresión Gzip, caché de recursos externos (fuentes de Google, scripts de CDN) y tipos de archivo personalizados.

Ejemplo de configuración de periodos de almacenamiento para grupos de archivos

🔗 AEH Speed Optimization en WordPress.org

Si ya tiene un plugin de caché como W3 Total Cache o WP Rocket, no necesita un plugin Expires independiente. Cualquier plugin de caché serio puede añadir encabezados Expires y Cache-Control a.htaccess automáticamente. Vaya a los ajustes de su plugin y verifique que la pestaña Browser Cache esté activa.

Qué tiempo de caché establecer

No hay una respuesta universal; el período depende de la frecuencia con que usted cambie un tipo de archivo específico.

Lista de tipos de archivo para configuración de caché en el plugin

Tipo de archivo

Período recomendado

Por qué

Imágenes (jpg, png, webp, avif, gif, svg)

1 año

Cambian raramente, pesan mucho, máximo beneficio del caché

Iconos y favicon

1 año

No cambian durante años

Fuentes (woff2, woff)

1 año

Se conectan una vez y no se actualizan

Estilos CSS

1 mes

Se editan de vez en cuando; al rediseñar, limpie el caché

JavaScript

1 mes

Misma lógica que para CSS

PDF y documentos

1 mes

Se descargan raramente pero pueden actualizarse

Regla general: cuanto más estable es el archivo, más largo es el período. Para imágenes, un año es el estándar. Para CSS y JS, un mes es un compromiso razonable entre velocidad y frescura.

Si está desarrollando activamente el sitio y los estilos cambian cada semana, establezca CSS a una semana, no a un mes. Cuando termine las ediciones, vuelva a un mes.

⁉️🤔 Preguntas frecuentes

Añadí código a.htaccess pero GTmetrix aún muestra el error. ¿Por qué?

La razón más común es que los módulos mod_expires o mod_headers no están habilitados en el servidor. Escriba al soporte de hosting solicitando activar ambos módulos. Segunda razón: insertó el código después de # BEGIN WordPress, no antes. WordPress sobrescribe todo lo que aparece después de su marcador. Tercera, un plugin de caché (W3 Total Cache, WP Rocket) ya gestiona.htaccess y sobrescribió sus reglas con las suyas propias. En ese caso, configure Browser Cache dentro del propio plugin, no manualmente.

¿Cuál es la diferencia entre Expires y Cache-Control?

Expires establece una fecha y hora concretas («válido hasta el 15 de junio de 2027»). Cache-Control con la directiva max-age establece la duración en segundos desde el momento de la solicitud («válido por 31536000 segundos»). Cache-Control es más flexible y tiene prioridad: si ambos están configurados, el navegador sigue Cache-Control. Recomendamos escribir ambos para máxima compatibilidad con clientes antiguos y nuevos.

El sitio está en Nginx,.htaccess no funciona. ¿Qué hacer?

El archivo .htaccess es configuración de Apache. Nginx lo ignora. En Nginx, las reglas de caché se añaden a la sección server del archivo de configuración del sitio con la directiva expires. Si tiene Nginx (hostings como Kinsta, Cloudways), use el plugin AEH Speed Optimization: funciona en cualquier servidor web porque gestiona los encabezados a través de PHP, no mediante la configuración del servidor.

¿Necesito configurar Expires si ya estoy usando un CDN?

Sí. Un CDN (Cloudflare, BunnyCDN) almacena contenido en caché en sus servidores en todo el mundo, pero el caché del navegador es una capa independiente. Unos encabezados Expires y Cache-Control correctamente configurados reducen las solicitudes incluso al CDN: el navegador no va a la red en absoluto por un archivo si su copia local aún está fresca. Dos capas de caché, CDN + navegador, trabajan juntas, no se reemplazan mutuamente.

¿El plugin AEH Speed Optimization entra en conflicto con mi plugin de caché?

Puede ocurrir si ambos intentan escribir reglas en.htaccess. Antes de instalar AEH Speed Optimization, desactive Browser Cache en su plugin de caché principal o, por el contrario, conserve un solo plugin que gestione tanto el caché de páginas como el caché del navegador. WP Rocket y W3 Total Cache pueden hacer todo de serie; no necesita un plugin Expires independiente con ellos.

¿Conviene configurar Expires manualmente o basta con un plugin?

Si trabaja con soltura con FTP y no le teme a un editor de código, la configuración manual mediante.htaccess le da control total y no añade un plugin extra al administrador. El código anterior: copie, pegue y el asunto queda resuelto.

Para todos los demás, el plugin AEH Speed Optimization resuelve la tarea sin riesgo de un error tipográfico en la configuración. Además, proporciona minificación y carga diferida, que también aceleran el sitio.

Lo principal es no dejar el error de GTmetrix tal como está. Cinco minutos para configurar los encabezados Expires proporcionan un aumento de velocidad notable, y la velocidad es tanto experiencia de usuario como posicionamiento en buscadores.