Cómo hacer que tu web cargue rápido, sin pagar un centavo
Hay dos tipos de sitios web: los que cargan antes de que sueltes el dedo del mouse, y los que te dan tiempo de ir a la cocina, prepararte un café y volver a ver si ya apareció el menú.
Si tu sitio es del segundo tipo, tranquilo. Casi todo lo que hace lento a un sitio es reparable,
gratis, y sin contratar a un gurú que cobra por hora lo que tú cobras por día. Vamos a ver tres
cosas: qué técnicas mueven de verdad la aguja, qué directivas meter en el .htaccess
(con el código listo para copiar), y cómo optimizar imágenes sin pagar ningún servicio.
Conejillo de indias: Little Italy Kitchen, restaurante italiano en LoDo, Denver. Horno de leña, pasta a mano, y una web con fotos de lasaña de 6 megabytes cada una.
Por qué importa la velocidad (y por qué no es magia)
Primero, bajemos las expectativas a un nivel sano. La velocidad es un factor de ranking, confirmado públicamente desde 2010, pero es un factor menor. Nadie llega al primer puesto solo por cargar rápido, así como nadie gana un concurso de cocina solo porque llegó temprano.
La forma correcta de pensarlo: cuando tu página y la de tu competidor están casi empatadas en todo lo demás, ser materialmente más rápido puede ser el empujón. Y además — esto es lo que de verdad importa — las páginas rápidas dan mejor experiencia y aumentan las conversiones.
Traducido a español de restaurante: si alguien busca dónde cenar desde el celular, parado en una esquina con hambre y 12% de batería, tu sitio tiene aproximadamente un segundo para mostrar algo útil antes de que esa persona se vaya al competidor.
Los tres números que Google mira: Core Web Vitals
| Métrica | Qué mide | Meta ("bueno") |
|---|---|---|
| LCP Largest Contentful Paint |
Cuánto tarda en aparecer el bloque de contenido principal | ≤ 2,5 segundos |
| INP Interaction to Next Paint |
Cuánto tarda la página en responder cuando el usuario hace clic o toca algo | ≤ 200 milisegundos |
| CLS Cumulative Layout Shift |
Cuánto se mueve el contenido mientras carga (lo que te hace pulsar el botón equivocado) | ≤ 0,1 |
Un detalle técnico que vale oro: las tres métricas se miden en el percentil 75 de tus usuarios reales. No basta con que te cargue rápido a ti, en tu laptop, con fibra óptica. Tiene que cargarle rápido al 75% de quienes te visitan, incluido el turista con señal 3G intermitente.
Primero mide, después toca
Regla de oro: no optimices a ciegas. Antes de tocar código:
- PageSpeed Insights: te da datos de campo (usuarios reales, del conjunto CrUX) y datos de laboratorio, más sugerencias concretas.
- Lighthouse: integrado en Chrome DevTools. Puedes pulsar cada fila del informe para ver exactamente qué recurso causa el problema.
- GTmetrix: su pestaña "Structure" tiene una auditoría de LCP que te dice qué elemento específico frena la carga. Y el "waterfall", que muestra en qué orden carga todo.
- WebPageTest y Pingdom: más opciones de laboratorio.
- Search Console: informe de Core Web Vitals con datos reales de tu sitio.
Las técnicas que realmente aceleran un sitio
El hosting: donde casi todos pierden la batalla
En un hosting compartido, tu sitio pelea por recursos con otros sitios del mismo servidor. Y a veces esos vecinos corren scripts pesados a toda hora. Es cocinar en una cocina comunitaria donde alguien siempre está usando las cuatro hornillas.
Si GTmetrix te dice que todos tus elementos están optimizados pero el servidor sigue lento, el problema es el hosting y ninguna directiva te va a salvar. El salto a un VPS suele ser el cambio que más se nota.
Menos scripts de terceros
Cada vez que agregas Analytics, un pixel, un chat en vivo, un widget de reseñas, un mapa embebido y un botón de reservas, tu página tiene que hablar con un servidor remoto distinto cada vez que carga.
Uno solo no hace daño. Pero como advierte The Art of SEO: si tienes tres o más programas de analítica o seguimiento, probablemente tienes demasiados. Little Italy Kitchen no necesita cuatro herramientas de mapas de calor para saber que la gente pulsa "Ver el menú".
Código limpio: minificar CSS y JavaScript
Minificar es quitarle al código los espacios, saltos de línea y comentarios que sirven para que un humano lo lea pero que la máquina no necesita. Y hay un beneficio menos obvio: cuando validas tu HTML y CSS, reduces las veces que el navegador tiene que adivinar qué querías renderizar, lo que reduce el tiempo de render.
Caché, CDN y base de datos
Cachear es guardar una versión ya "cocinada" de tus páginas para no reconstruirlas cada vez. Si usas un CMS, revisa que su caché esté activada — en algunas plataformas hay que encenderla explícitamente — y revisa el impacto de cada extensión instalada, porque muchas son las culpables de la lentitud.
Un truco viejo pero efectivo si tienes una portada computacionalmente pesada: generas un snapshot
estático con wget, lo guardas como index.html, y programas un cron que lo
repita para mantenerlo fresco.
wget --output-document=index.html http://www.littleitalykitchen.com/index.php
Sobre el CDN: copia tu contenido a servidores repartidos por el mundo. Little Italy Kitchen está en Denver, pero recibe turistas que investigan restaurantes antes de viajar, desde Tokio o Madrid. Y hay planes gratuitos que incluyen CDN, compresión Brotli, minificación y certificado SSL: para un sitio pequeño-mediano sobra.
Y la base de datos: si lleva años funcionando, los registros se fragmentan y el rendimiento baja. Desfragmentarla puede acelerarla notablemente.
El archivo .htaccess: el interruptor pequeño que hace mucho
El .htaccess permite cambiar la configuración de Apache directorio por directorio.
Controla el directorio donde está y todos sus subdirectorios, y normalmente vive en la raíz.
Cuatro advertencias que te ahorran un infarto
- Haz una copia de respaldo antes de modificarlo.
- Un carácter mal puede tumbar tu sitio. Literalmente puede dejarlo fuera de línea hasta que corrijas el error.
- Guárdalo con saltos de línea UNIX. Si tu editor usa formato Windows, salen errores raros.
- Es un archivo oculto. Activa "ver archivos ocultos" en tu FTP y asegúrate de que no existe uno ya, para no sobrescribirlo.
Y una nota: cada directiva va envuelta en un <IfModule>. Así, si tu hosting no
tiene ese módulo activado, el servidor ignora el bloque en lugar de reventar con un error 500.
Compresión gzip (la más rentable de todas)
Comprime el contenido antes de enviarlo al navegador. En texto plano, HTML, CSS y JavaScript el ahorro puede ser del 60% al 80%.
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml
AddOutputFilterByType DEFLATE text/css text/javascript
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/json
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE font/ttf font/otf font/eot
# Navegadores antiguos con bugs conocidos
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
<IfModule mod_headers.c>
Header append Vary User-Agent
</IfModule>
</IfModule>
Importante: fíjate que NO comprimimos JPG, PNG, WebP, MP4 ni ZIP. Esos ya vienen
comprimidos; volver a comprimirlos gasta CPU y no ahorra nada. Es meter una maleta cerrada dentro de
otra maleta. Las fuentes .woff2 también quedan fuera por lo mismo.
Si tu servidor no tiene mod_deflate, hay alternativa desde PHP:
<?php ob_start("ob_gzhandler"); ?>O más fácil todavía, en el php.ini de tu raíz:
zlib.output_compression=on
Brotli (el gzip del siglo XXI)
Comprime entre 15% y 20% mejor que gzip. Si tu hosting lo tiene, actívalo; si no, el bloque se ignora:
<IfModule mod_brotli.c> AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/xml AddOutputFilterByType BROTLI_COMPRESS text/css text/javascript AddOutputFilterByType BROTLI_COMPRESS application/javascript AddOutputFilterByType BROTLI_COMPRESS application/json AddOutputFilterByType BROTLI_COMPRESS image/svg+xml </IfModule>
Puedes tener los dos bloques a la vez. El servidor negocia con el navegador y usa el mejor que ambos soporten.
Caché del navegador con mod_expires
Le dice al navegador: "el logo no ha cambiado desde 2019, no me lo vuelvas a pedir". Para usuarios recurrentes, la segunda visita se vuelve casi instantánea.
<IfModule mod_expires.c> ExpiresActive On ExpiresDefault "access plus 1 month" # HTML: nunca cachear agresivamente, cambia seguido ExpiresByType text/html "access plus 0 seconds" # Datos que cambian ExpiresByType application/json "access plus 0 seconds" ExpiresByType application/xml "access plus 0 seconds" # Imágenes: un año ExpiresByType image/jpeg "access plus 1 year" ExpiresByType image/png "access plus 1 year" ExpiresByType image/webp "access plus 1 year" ExpiresByType image/avif "access plus 1 year" ExpiresByType image/svg+xml "access plus 1 year" ExpiresByType image/x-icon "access plus 1 year" # CSS y JavaScript ExpiresByType text/css "access plus 1 year" ExpiresByType application/javascript "access plus 1 year" # Fuentes ExpiresByType font/woff2 "access plus 1 year" ExpiresByType font/woff "access plus 1 year" </IfModule>
<!-- Mal: el navegador no sabe que cambió --> <link rel="stylesheet" href="/css/estilo.css"> <!-- Bien: cambias el número y lo trata como archivo nuevo --> <link rel="stylesheet" href="/css/estilo.css?v=7"> <!-- Mejor todavía --> <link rel="stylesheet" href="/css/estilo.a83f2c.css">
Cache-Control, Keep-Alive y ETags
mod_expires es la versión clásica; Cache-Control es la moderna y más
precisa. Puedes usar ambas. El immutable le dice al navegador que ni se moleste en
preguntar si el archivo cambió.
<IfModule mod_headers.c>
# Recursos estáticos con nombre versionado: cachear a lo bestia
<FilesMatch "\.(jpg|jpeg|png|gif|webp|avif|svg|ico|css|js|woff2|woff)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
# HTML: siempre revalidar
<FilesMatch "\.(html|htm|php)$">
Header set Cache-Control "no-cache, must-revalidate, max-age=0"
</FilesMatch>
# Keep-Alive: reutiliza la conexión en vez de abrir una por archivo
Header set Connection keep-alive
# ETags: redundantes si ya tienes Expires y Cache-Control,
# y en servidores múltiples rompen la caché
Header unset ETag
</IfModule>
FileETag NoneCanonicalización en un solo salto (HTTPS + www)
Aquí hay una trampa de velocidad que casi nadie ve. Muchos sitios tienen una regla que redirige HTTP a HTTPS y otra separada que redirige sin-www a con-www. Resultado: dos redirecciones encadenadas antes de ver nada. Cada una es un viaje completo de ida y vuelta al servidor.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.littleitalykitchen.com/$1 [R=301,L]
</IfModule>
El RewriteBase / solo se usa en .htaccess, no en la configuración del
servidor. Y el signo de exclamación al inicio de una expresión regular significa "no". Si prefieres
la versión sin www, invierte la lógica: lo importante es elegir un sistema y ser fiel a
él.
→ Más sobre redirecciones 301 aquí
Servir WebP automáticamente (la joya de la corona)
Mi directiva favorita. La idea: guardas dos versiones de cada imagen
(pizza.jpg y pizza.webp), dejas tu HTML tal cual con el
.jpg, y el servidor entrega el WebP automáticamente a los navegadores
que lo soportan.
<IfModule mod_rewrite.c>
RewriteEngine On
# ¿El navegador acepta WebP?
RewriteCond %{HTTP_ACCEPT} image/webp
# ¿La petición es de un JPG o PNG?
RewriteCond %{REQUEST_FILENAME} (.+)\.(jpe?g|png)$
# ¿Existe la versión .webp del mismo archivo?
RewriteCond %1\.webp -f
# Entonces sirve el .webp
RewriteRule (.+)\.(jpe?g|png)$ $1.webp [T=image/webp,E=REQUEST_image,L]
</IfModule>
<IfModule mod_headers.c>
Header append Vary Accept env=REQUEST_image
</IfModule>
<IfModule mod_mime.c>
AddType image/webp .webp
AddType image/avif .avif
</IfModule>
El Vary: Accept es obligatorio: avisa a las cachés intermedias y CDNs que el contenido
de esa URL cambia según el navegador. Sin él, un proxy podría cachear el WebP y servírselo a un
navegador que no lo soporta, y ahí sí se arma el desastre.
Protección contra hotlinking
Si otro sitio pone tus fotos directamente en su página, tú pagas el ancho de banda y ellos se llevan las visitas.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?littleitalykitchen\.com [NC]
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?google\. [NC]
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?bing\.com [NC]
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?facebook\.com [NC]
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?instagram\.com [NC]
RewriteRule \.(jpg|jpeg|png|gif|webp|avif)$ - [F,NC]
</IfModule>El .htaccess completo, ordenado
Pégalo, cambia el dominio, súbelo, y prueba tu sitio inmediatamente:
# ==========================================================
# LITTLE ITALY KITCHEN - .htaccess optimizado
# ==========================================================
# ---------- 1. REDIRECCIONES (van primero) ----------
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.littleitalykitchen.com/$1 [R=301,L]
# WebP automático
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_FILENAME} (.+)\.(jpe?g|png)$
RewriteCond %1\.webp -f
RewriteRule (.+)\.(jpe?g|png)$ $1.webp [T=image/webp,E=REQUEST_image,L]
</IfModule>
# ---------- 2. TIPOS MIME ----------
<IfModule mod_mime.c>
AddType image/webp .webp
AddType image/avif .avif
AddType font/woff2 .woff2
</IfModule>
# ---------- 3. COMPRESIÓN ----------
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css
AddOutputFilterByType DEFLATE text/javascript application/javascript
AddOutputFilterByType DEFLATE application/json application/xml
AddOutputFilterByType DEFLATE application/rss+xml image/svg+xml
</IfModule>
<IfModule mod_brotli.c>
AddOutputFilterByType BROTLI_COMPRESS text/html text/css
AddOutputFilterByType BROTLI_COMPRESS application/javascript
AddOutputFilterByType BROTLI_COMPRESS application/json image/svg+xml
</IfModule>
# ---------- 4. CACHÉ ----------
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 1 month"
ExpiresByType text/html "access plus 0 seconds"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/avif "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
</IfModule>
# ---------- 5. HEADERS ----------
<IfModule mod_headers.c>
Header append Vary Accept env=REQUEST_image
Header set Connection keep-alive
Header unset ETag
<FilesMatch "\.(jpg|jpeg|png|webp|avif|svg|ico|css|js|woff2)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
</IfModule>
FileETag None
# ---------- 6. VARIOS ----------
Options -Indexes
ErrorDocument 404 /404.html
ServerSignature Off
Deja una línea en blanco al final del archivo: el servidor lo lee línea por línea y necesita ese retorno de carro para saber que terminaste.
Lo del 404 no es solo estética: si tu sitio usa lenguajes del lado del servidor, los errores crípticos que muestra por defecto son precisamente lo que el buscador va a indexar en vez de tu contenido.
Imágenes rápidas sin pagar un servicio
Aquí está el verdadero botín. Según HTTP Archive, las imágenes representan en promedio el 21% del peso total de una página. En un sitio de restaurante, con galerías de platos, ese porcentaje se dispara fácil al 60% o 70%.
Y ojo: el LCP suele ser precisamente una imagen. Si arreglas tus imágenes, arreglas tu LCP. Es la relación esfuerzo/beneficio más alta de todo el SEO técnico.
Elige el formato correcto
| Formato | Cuándo usarlo |
|---|---|
| JPEG | Fotografías. Puedes ajustar el nivel de calidad para equilibrar peso y apariencia |
| PNG | Capturas, logos, transparencias. Mejor calidad, archivo más pesado |
| WebP | El estándar actual. Compresión con o sin pérdida; pesa entre 25% y 35% menos que un JPEG equivalente |
| AVIF | Todavía más eficiente que WebP. Soportado por los navegadores modernos |
| SVG | Logos, iconos, ilustraciones planas. Es texto, escala infinitamente y no pesa nada |
Advertencia curiosa: cuidado si usas imágenes .jpg dentro de un SVG en línea, porque
los sistemas de Google no pueden indexar eso.
Flujo recomendado: trabaja los originales en PNG o JPEG de alta calidad y conviértelos a WebP (y opcionalmente AVIF) para publicar. Guarda siempre los originales; nunca comprimas encima del único archivo que tienes.
Comprime antes de subir (herramientas 100% gratis)
En el navegador: Squoosh, hecho por Google, funciona local y no sube tus archivos a ningún lado; tiene comparador lado a lado y exporta a WebP y AVIF. De escritorio: GIMP, que exporta a WebP directamente.
Y en línea de comandos, que es donde te ahorras horas:
# Instalar las herramientas (Debian/Ubuntu)
sudo apt install webp imagemagick jpegoptim optipng
# Convertir una imagen a WebP con calidad 80
cwebp -q 80 margherita.jpg -o margherita.webp
# Convertir TODA una carpeta de golpe
for f in *.jpg; do cwebp -q 80 "$f" -o "${f%.jpg}.webp"; done
for f in *.png; do cwebp -q 80 "$f" -o "${f%.png}.webp"; done
# Redimensionar a 1600px de ancho máximo y quitar metadatos EXIF
mogrify -resize '1600x>' -quality 82 -strip *.jpg
# Optimizar JPEG sin cambiar de formato
jpegoptim --strip-all --max=82 *.jpg
# Optimizar PNG
optipng -o5 *.png
Ese -strip no es cosmético: quita los metadatos EXIF (modelo de cámara, GPS, fecha) que
pueden pesar decenas de kilobytes por foto y que a nadie le sirven en la web.
Un script de tres líneas te procesa las 200 fotos del menú mientras te tomas un espresso. Resultado típico: una foto de 4,2 MB salida del celular termina pesando 180 KB, y se ve exactamente igual en pantalla.
No subas imágenes más grandes de lo que se van a mostrar
El error número uno y el más fácil de arreglar. Si tu página muestra la foto en un contenedor de 800 píxeles, no subas una imagen de 4000 y la reduzcas con CSS.
La razón es que cambiar el tamaño de visualización no reduce el tamaño del archivo que se envía, a veces por conexiones de bajo ancho de banda, al dispositivo móvil de una persona. El navegador descarga los 4 MB completos y luego los encoge. Es pedir una pizza familiar para comerte una porción.
Regla práctica: sube al doble del tamaño de visualización (por las pantallas retina) y ni un píxel más. Y si quieres ofrecer imágenes muy grandes, ponlas en una página aparte con un thumbnail que enlace: así solo esperan la carga los usuarios que de verdad quieren verlas.
Siempre pon width y height
La optimización más barata que existe: dos atributos. Permiten al navegador reservar el espacio de la imagen antes de que cargue el CSS, lo que evita que la página salte. Y ese salto es exactamente lo que mide el CLS.
<!-- Mal: el navegador no sabe cuánto espacio reservar --> <img src="lasagna.webp" alt="Lasaña"> <!-- Bien --> <img src="lasagna.webp" width="800" height="600" alt="Lasaña de la casa">
Si usas AMP o PWAs, además, definir las dimensiones es obligatorio.
Imágenes responsivas: srcset y picture
El objetivo es que el navegador descargue la versión adecuada al dispositivo. Quien ve el menú desde un móvil no debería descargar la misma imagen que alguien en un monitor 4K.
Opción 1: srcset con sizes, la más simple:
<img srcset="pizza-480.webp 480w,
pizza-800.webp 800w,
pizza-1600.webp 1600w"
sizes="(max-width: 600px) 100vw,
800px"
src="pizza-800.webp"
width="800" height="600"
alt="Pizza margherita saliendo del horno de leña">
Opción 2: el elemento <picture>, cuando quieres servir formatos
distintos. Puede contener múltiples <source>, y debe incluir un
<img> como respaldo para navegadores viejos:
<picture>
<source type="image/avif"
srcset="tiramisu-800.avif 800w, tiramisu-1600.avif 1600w"
sizes="(max-width: 600px) 100vw, 800px">
<source type="image/webp"
srcset="tiramisu-800.webp 800w, tiramisu-1600.webp 1600w"
sizes="(max-width: 600px) 100vw, 800px">
<img src="tiramisu-800.jpg"
width="800" height="600"
alt="Tiramisú casero de Little Italy Kitchen en LoDo, Denver">
</picture>
El navegador elige de arriba hacia abajo: si soporta AVIF usa AVIF; si no, WebP; si no, el JPEG del
<img>. Nadie se queda sin ver la foto.
Para artículos y blogs, Google recomienda incluir imágenes de alta resolución en tres proporciones: 1×1, 4×3 y 16×9. Y esto también aplica a varios tipos de schema, incluido LocalBusiness, Recipe, Product y Event: exactamente los que necesita un restaurante.
→ Más sobre datos estructurados y Schema aquí
Lazy loading (con una advertencia importante)
Hace que las imágenes de más abajo no se descarguen hasta que el usuario haga scroll. Hoy es nativo, sin JavaScript:
<img src="cannoli.webp" width="600" height="400"
alt="Cannoli siciliano" loading="lazy" decoding="async">loading="lazy" nativo es seguro; los que dan problemas
son los scripts caseros o los plugins que reemplazan el src con placeholders. Para
mitigar el riesgo, usa sitemaps de imágenes.
Y ahora el error que cometen 9 de cada 10 sitios: poner
loading="lazy" en la imagen principal del banner. Esa es justamente tu elemento LCP.
Ponerle lazy es como decirle al mesero "tráeme el plato principal solo cuando yo lo pida
específicamente". Para esa imagen, haz lo contrario:
<!-- La imagen hero: prioridad máxima, sin lazy -->
<img src="hero-restaurante.webp" width="1600" height="900"
alt="Interior de Little Italy Kitchen en el barrio LoDo de Denver"
loading="eager" fetchpriority="high" decoding="async">Y si quieres exprimir el último segundo, precárgala desde el <head>:
<link rel="preload" as="image" href="/img/hero-restaurante.webp"
fetchpriority="high">Bonus: nombres de archivo, alt y sitemap
Ya que estás procesando todo, aprovecha para renombrar bien. Google reveló que usa la ruta y el nombre del archivo para rankear imágenes. En vez de tirar todo en una carpeta genérica, estructura subcarpetas por categorías temáticas:
Mal: /media/IMG_20240815_193042.jpg Bien: /platos/pastas/lasagna-bolognesa-horno-lena.webp
Y el alt, siempre. Google lo usa para determinar cuál es la mejor imagen que puede
devolver ante una consulta, y además es un requisito de accesibilidad para quienes no pueden ver las
imágenes.
<!-- Inútil --> <img src="pizza.webp" alt="pizza"> <!-- Útil --> <img src="pizza.webp" alt="Pizza margherita en horno de leña de Little Italy Kitchen, Denver">
Regla de proporción: alt breve para imágenes pequeñas, más largo para imágenes grandes. Como guía general, no debería pasar de 12 palabras.
Por último, tener tus imágenes en un sitemap de imágenes aumenta enormemente las
probabilidades de que se rastreen e indexen. Y revisa que tu robots.txt no esté
bloqueando los directorios de imágenes: sería una pena hacer todo este trabajo y descubrir que
tenías un Disallow: /img/ de hace tres años.
Ah, y un consejo final: no uses las mismas fotos de stock que usa todo el mundo. Toma tus propias fotos. Además del beneficio SEO, ningún banco de imágenes tiene la lasaña de tu cocina.
Plan de acción para una sola tarde
Si Little Italy Kitchen tuviera libre la tarde entre el almuerzo y la cena, este sería el orden.
Primera hora: medir
- Corre PageSpeed Insights en tu home, tu página de menú y una de plato.
- Anota tu LCP, INP y CLS actuales. Guarda una captura para comparar después.
- Identifica cuál es tu elemento LCP (spoiler: probablemente la foto del banner).
Segunda hora: imágenes
- Descarga todas tus imágenes por FTP.
- Corre
mogrifypara redimensionar a máximo 1600px y quitar EXIF. - Corre
cwebppara generar las versiones WebP. - Renombra las que tengan nombres tipo
IMG_4823.jpg. - Sube todo: los JPG optimizados y los WebP.
Tercera hora: .htaccess
- Descarga y respalda tu
.htaccessactual. - Pega el bloque completo, cambiando el dominio.
- Súbelo y prueba el sitio de inmediato. Si algo se rompió, restaura el respaldo.
Cuarta hora: HTML
- Agrega
widthyheighta cada<img>. - Pon
loading="lazy"a todas las imágenes menos la del banner. - A la del banner, ponle
fetchpriority="high"y unpreload. - Escribe alt descriptivos donde falten.
Al final: volver a medir
Corre PageSpeed Insights otra vez y compara. Los datos de campo — los de usuarios reales — tardan unos 28 días en actualizarse, así que ten paciencia con esos. Los de laboratorio cambian de inmediato.
Cierre
La velocidad web no es un problema de dinero, es un problema de atención al detalle. Casi todo lo que hace lento a un sitio típico — imágenes gigantes sin comprimir, cero caché, cero compresión, quince scripts de terceros — se arregla con herramientas gratuitas y una tarde de trabajo.
Y lo mejor: a diferencia del link building o del contenido, esto es determinista. Comprimes una imagen de 4 MB a 180 KB y esa mejora existe, es real, es medible, y no depende de que a un algoritmo le caigas bien.
Ahora ve a revisar cuánto pesa la foto de tu página principal. Te va a sorprender.
Bibliografía
- theartofseo.txt — The Art of SEO (Enge, Spencer, Stricchiola).
Capítulo 7, "Developing an SEO-Friendly Website": Core Web Vitals y LCP (pp. 358–360), el riesgo
de empeorar el CLS al eliminar recursos que bloquean el render (pp. 358–359), herramientas de
medición (pp. 366–367), configuración de servidor y compresión gzip (p. 368), caché y elección
de plataforma (p. 368), CDNs y desfragmentación de base de datos (p. 369), scripts de terceros y
el límite de tres herramientas de analítica (pp. 369–370),
RewriteBase, negación en expresiones regulares y uso del 301 (pp. 289–293). Capítulo 12, "Vertical, Local, and Mobile SEO": nombres de archivo y atributo alt (pp. 596–598), advertencia sobre lazy loading asíncrono y sitemaps de imágenes (p. 597), elemento<picture>con respaldo, proporciones 1×1, 4×3 y 16×9, tipos de schema asociados, y advertencia sobre hotlinking y robots.txt bloqueando imágenes (p. 598). - seoallinone.txt — SEO All-in-One For Dummies (Clay, Esparza). Libro 4,
Capítulo 3, "Page Experience Update", pp. 255–256: Core Web Vitals, cómo arreglar LCP y CLS,
eliminación de recursos que bloquean el render, hosting como cuello de botella, caché del
navegador y auditoría de LCP y waterfall en GTmetrix. Libro 5, "Creating Content", pp. 329–330:
longitud del atributo alt (guía de 12 palabras), por qué redimensionar con CSS no reduce el
archivo enviado, y la recomendación de poner las imágenes muy grandes en página aparte con
thumbnail. Libro 7, "Optimizing the Foundations": factores de velocidad y compresión gzip
(pp. 519–520),
.htaccessy sus advertencias sobre archivo oculto, formato UNIX, línea final y riesgo de tumbar el sitio (pp. 563–567), ymod_rewrite(p. 583). - SEOWarrior.txt — SEO Warrior (John I. Jerkovic). Capítulo 8, "Search
Engine Traps": trampas de rendimiento del sitio, beneficios de la compresión del servidor web,
la alternativa por PHP con
ob_gzhandlery la configuración dezlib.output_compression, la técnica del snapshot estático conwgety cron, y la advertencia sobre páginas de error crípticas que terminan indexadas. - SEJ_On-Page-SEO_eBook_Final_2021A.pdf — The Complete Guide to On-Page
SEO (Search Engine Journal), pp. 210–226: los doce consejos de optimización de imágenes.
Elección de formato y la advertencia sobre JPG dentro de SVG en línea (p. 211), compresión y el
dato de HTTP Archive sobre el 21% del peso de página (p. 212), imágenes propias frente a stock
(pp. 214–215), nombres de archivo y estructura de carpetas como factor de ranking (pp. 216,
220), texto alt y su requisito de accesibilidad (pp. 218–219),
widthyheightcontra el CLS y su obligatoriedad en AMP y PWAs (p. 222), imágenes responsivas consrcsety el formato del atributo (p. 223), y sitemaps de imágenes (p. 224). - SEJ_LocalSEO-Feb2022.pdf — Local SEO: The Definitive Guide (Search Engine Journal), p. 75: codificación HTML y CSS de alta calidad y su efecto en reducir el tiempo de renderizado.
- Search-Engine-Optimization-SEO-Secrets.txt — SEO Secrets (Danny Dover), p. 358: errores comunes de canonicalización y redirecciones 301 en Apache; informe de tiempo de descarga de páginas.
- Inbound_Marketing_and_SEO_Insights_from_the_Moz_Blog.pdf — p. 279: informes de velocidad del sitio en analítica y su relación con conversiones y posiciones.
- Google Search Central / web.dev — Anuncio oficial del reemplazo de First Input Delay (FID) por Interaction to Next Paint (INP) como Core Web Vital, efectivo el 12 de marzo de 2024. Fuente consultada en línea, ya que este cambio es posterior a la publicación de todos los libros citados arriba.
Comentarios