El módulo PageSpeed de Google (mod_pagespeed para Apache y ngx_pagespeed para Nginx) reescribía las páginas al vuelo para comprimir, minificar y convertir imágenes. El proyecto dejó de mantenerse: Google abandonó el desarrollo y el proyecto de la Apache Software Foundation se retiró en 2023, así que no hay versiones para el Nginx de Ubuntu 24.04 ni parches de seguridad. En esta guía verás cómo retirarlo si aún lo tienes y cómo obtener las mismas mejoras con herramientas mantenidas en Nginx o Apache sobre Ubuntu 24.04.
Requisitos previos
- Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath.
- Un usuario no root con privilegios
sudo. - Nginx (paquete
nginxde Ubuntu) o Apache (apache2) sirviendo tu sitio entudominio.com.
Por qué no instalar PageSpeed hoy
| Optimización de PageSpeed | Alternativa mantenida |
|---|---|
| Compresión (gzip) | gzip y Brotli nativos del servidor web |
extend_cache | Cabeceras Cache-Control largas con nombres de archivo versionados |
rewrite_css, rewrite_javascript, combine_* | Minificación en el proceso de build (Vite, esbuild, webpack) |
recompress_images, convert_*_to_webp | Conversión previa con cwebp y negociación por cabecera Accept |
lazyload_images | Atributo HTML nativo loading="lazy" |
Hacer estas tareas antes de servir la página, en lugar de en cada petición, consume menos CPU y memoria y no rompe el HTML, que era el problema más habitual de PageSpeed.
Paso 1: Retirar PageSpeed si está instalado
En Apache, comprueba si el módulo está cargado:
sudo apache2ctl -M | grep pagespeed
Si aparece pagespeed_module, desactívalo y elimina el paquete y su repositorio:
sudo a2dismod pagespeed
sudo apt purge mod-pagespeed-stable
sudo rm -f /etc/apt/sources.list.d/mod-pagespeed.list
sudo systemctl restart apache2
En Nginx, ngx_pagespeed solo existía compilado a mano. Comprueba si tu binario lo incluye:
nginx -V 2>&1 | grep -o pagespeed
Si aparece, reinstala el paquete de Ubuntu para volver al binario oficial y elimina las directivas pagespeed de tu configuración:
sudo apt install --reinstall nginx
sudo grep -rl pagespeed /etc/nginx/
Edita cada archivo que devuelva el último comando, borra las líneas que empiezan por pagespeed y comprueba la configuración con sudo nginx -t.
Paso 2: Activar compresión Brotli y gzip
Brotli comprime HTML, CSS y JavaScript entre un 15 y un 20 % más que gzip y lo soportan todos los navegadores actuales. Mantén gzip para clientes antiguos.
Nginx
Instala los módulos de Brotli empaquetados en Ubuntu:
sudo apt install libnginx-mod-http-brotli-filter libnginx-mod-http-brotli-static
El paquete los activa en /etc/nginx/modules-enabled/. Crea un archivo de compresión que se incluirá en el bloque http:
sudo nano /etc/nginx/conf.d/compression.conf
# gzip ya está activado con "gzip on;" en nginx.conf: no lo repitas aquí
gzip_vary on;
gzip_proxied any;
gzip_comp_level 5;
gzip_min_length 256;
gzip_types text/plain text/css text/javascript application/javascript application/json application/xml image/svg+xml;
brotli on;
brotli_comp_level 5;
brotli_min_length 256;
brotli_types text/plain text/css text/javascript application/javascript application/json application/xml image/svg+xml;
text/html se comprime siempre y no debe aparecer en las listas. Comprueba y recarga:
sudo nginx -t
sudo systemctl reload nginx
Apache
Ubuntu incluye mod_brotli y mod_deflate. Activa Brotli:
sudo a2enmod brotli
sudo nano /etc/apache2/conf-available/brotli.conf
<IfModule mod_brotli.c>
AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/css text/javascript application/javascript application/json application/xml image/svg+xml
</IfModule>
sudo a2enconf brotli
sudo apache2ctl configtest
sudo systemctl reload apache2
Verificación
Pide una página anunciando soporte de Brotli:
curl -s -o /dev/null -D - -H "Accept-Encoding: br, gzip" https://tudominio.com/ | grep -i content-encoding
content-encoding: br
Paso 3: Cabeceras de caché para estáticos
El filtro extend_cache de PageSpeed renombraba los recursos para poder cachearlos durante un año. Si tu build ya genera nombres con hash (app.3f9a1c.js), basta con enviar una cabecera de caché larga.
Nginx
Añade este bloque dentro del server de tu sitio, en /etc/nginx/sites-available/tudominio.com:
location ~* \.(css|js|mjs|woff2|svg|png|jpe?g|gif|webp|avif|ico)$ {
add_header Cache-Control "public, max-age=31536000, immutable";
access_log off;
try_files $uri =404;
}
Apache
Activa mod_expires y mod_headers:
sudo a2enmod expires headers
Añade dentro del <VirtualHost> de tu sitio:
<FilesMatch "\.(css|js|mjs|woff2|svg|png|jpe?g|gif|webp|avif|ico)$">
ExpiresActive On
ExpiresDefault "access plus 1 year"
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
Recarga el servidor y verifica sobre un recurso real:
curl -sI https://tudominio.com/css/app.css | grep -i cache-control
cache-control: public, max-age=31536000, immutable
Importanteusa
immutablesolo con archivos cuyo nombre cambia en cada versión. Si publicas siemprestyle.csscon el mismo nombre, reduce el tiempo (por ejemplomax-age=3600) o los visitantes verán la versión antigua.
Paso 4: Servir imágenes WebP
En lugar de convertir en cada petición, genera la versión WebP junto al original una vez y deja que el servidor elija según la cabecera Accept del navegador. Instala el conversor:
sudo apt install webp
Convierte las imágenes del sitio creando foto.jpg.webp junto a foto.jpg:
find /var/www/tudominio.com/images -type f \( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' \) \
-exec sh -c 'cwebp -quiet -q 80 "$1" -o "$1.webp"' _ {} \;
En Nginx, crea el mapa que decide el sufijo:
sudo nano /etc/nginx/conf.d/webp.conf
map $http_accept $webp_suffix {
default "";
"~*image/webp" ".webp";
}
Y en el server de tu sitio, coloca este bloque antes del de estáticos del paso 3:
location ~* \.(jpe?g|png)$ {
add_header Vary Accept;
add_header Cache-Control "public, max-age=2592000";
try_files $uri$webp_suffix $uri =404;
}
Recarga Nginx y comprueba que un navegador con soporte WebP recibe la versión convertida:
sudo nginx -t && sudo systemctl reload nginx
curl -sI -H "Accept: image/webp" https://tudominio.com/images/foto.jpg | grep -i content-type
content-type: image/webp
Para automatizar la conversión de las imágenes nuevas y añadir AVIF, consulta la guía de pipeline de optimización de imágenes.
Paso 5: Minificar y aplicar carga diferida en origen
La minificación y la combinación de CSS y JavaScript deben hacerse al compilar el frontend: herramientas como Vite o esbuild ya minifican en modo producción (npm run build). En sitios PHP como WordPress, un plugin de caché o de optimización cumple la misma función.
Para la carga diferida de imágenes, añade el atributo nativo en las plantillas en lugar de reescribir el HTML en el servidor:
<img src="/images/foto.jpg" alt="Descripción" width="800" height="600" loading="lazy">
Indicar width y height reserva el espacio de la imagen y evita saltos de diseño (CLS). No uses loading="lazy" en la imagen principal visible al cargar, porque retrasaría el LCP.
Solución de problemas
nginx: [emerg] "gzip" directive is duplicate. Has escrito gzip on; en un archivo de conf.d, pero ya está en /etc/nginx/nginx.conf. Elimina la línea duplicada.
unknown directive "brotli". Los módulos no se cargan. Comprueba que existen los enlaces en /etc/nginx/modules-enabled/ con ls /etc/nginx/modules-enabled/ | grep brotli.
Las imágenes siguen llegando como JPEG. Verifica que existe foto.jpg.webp en disco y que ningún otro location con regex anterior captura la petición: Nginx usa el primer bloque regex que coincide.
Conclusión
Has retirado un módulo sin mantenimiento y has cubierto sus optimizaciones principales con compresión Brotli, cabeceras de caché, WebP negociado y carga diferida nativa, todo con paquetes de Ubuntu que reciben actualizaciones. Como siguientes pasos, mide el resultado con PageSpeed Insights, activa HTTP/3 en tu servidor web y automatiza la conversión de imágenes con un temporizador de systemd.
