Has montado tu web, la ves bien en tu ordenador y, aun así, PageSpeed Insights te devuelve un naranja o un rojo y un aviso que suena a chino: «Solicitudes que bloquean la renderización». Lo normal es que no sepas por dónde empezar, y que el miedo a romper el sitio al tocar el código te haga dejarlo para «otro día».

Te entiendo, me ha pasado con proyectos propios y de clientes. La buena noticia es que este problema, que es de los más frecuentes en WordPress, casi siempre se puede arreglar sin tocar el diseño y sin ser programador. En este artículo te explico qué está pasando, cómo comprobar si te afecta y qué opciones tienes, de menos a más técnica. Y si tu web está hecha con React, más abajo te cuento qué cambia.

Resumen rápido

  • Un script del <head> sin defer ni async hace que el navegador espere a descargarlo y ejecutarlo antes de pintar la página.
  • No hay una cifra mágica de segundos: Google marca como «buenos» un LCP de 2,5 s o menos, un INP de 200 ms o menos y un CLS de 0,1 o menos.
  • defer y async no son lo mismo, y async no es «más eficiente» por defecto. Cada uno sirve para un caso.
  • Si tu web usa React u otro framework que pinta el contenido en el navegador, el HTML inicial puede llegar casi vacío. Conviene renderizar en el servidor o pregenerar las páginas.
  • Antes de aplazar nada, haz copia de seguridad y prueba el sitio después. Hay scripts que se rompen si cambias el orden en el que cargan.

¿Qué es el JavaScript que bloquea el renderizado?

Cuando alguien abre tu página, el navegador va leyendo el HTML de arriba abajo. Si en el <head> encuentra un <script> normal, para y no sigue hasta descargarlo y ejecutarlo. Mientras tanto, el visitante ve una pantalla en blanco.

Lighthouse, la herramienta que hay detrás de PageSpeed Insights, considera bloqueante un script en el <head> que no lleve defer ni async. Lo mismo ocurre con las hojas de estilo que el navegador necesita antes del primer pintado, aunque en este artículo nos centramos en JavaScript.

Y esto importa por la experiencia, no solo por el SEO: cuanto más tarda en aparecer algo útil, más probable es que el usuario se marche.

¿Cuánto tiene que tardar mi página para que Google la considere rápida?

Aquí quiero corregir algo que se repite mucho en tutoriales antiguos: no existe un umbral de «0,5 segundos». Google no mide la velocidad con un único número, sino con tres métricas llamadas Core Web Vitals:

Métrica Qué mide Valor «bueno»
LCP (Largest Contentful Paint) Cuándo aparece el elemento principal de la página 2,5 s o menos
INP (Interaction to Next Paint) Lo rápido que responde la página cuando interactúas 200 ms o menos
CLS (Cumulative Layout Shift) Cuánto se mueve el contenido mientras carga 0,1 o menos

PageSpeed Insights evalúa estos valores en el percentil 75 de visitas reales de los últimos 28 días. Si ese percentil es bueno en las tres métricas, tu página «aprueba» los Core Web Vitals.

El JavaScript bloqueante afecta sobre todo al LCP, porque retrasa el momento en que se pinta lo importante. También puede afectar al INP, si hay demasiado código ejecutándose cuando el usuario intenta hacer clic.

¿Cómo sé si el JavaScript me está frenando?

Antes de tocar nada, confírmalo:

  1. Entra en PageSpeed Insights y analiza tu URL.
  2. Mira primero los datos de campo (usuarios reales) y luego los de laboratorio (la simulación de Lighthouse). Pueden no coincidir, y no pasa nada: el laboratorio sirve para depurar y el campo es lo que realmente vive tu visitante.
  3. Busca en los diagnósticos el aviso de solicitudes que bloquean la renderización. Ahí aparece la lista de archivos .js (y .css) responsables.

Un detalle de actualidad: desde Lighthouse 13, la antigua auditoría «Elimina los recursos que bloqueen la renderización» pasó a mostrarse como una estadística dentro de Performance Insights. Si en algún tutorial antiguo ves un botón «Mostrar cómo corregirlo», que sepas que la interfaz ha cambiado, pero la información sigue estando.

Para saber qué parte de cada archivo se usa de verdad al cargar, puedes abrir la pestaña Coverage de las herramientas de desarrollador de Chrome: lo que sale en verde es crítico para el primer pintado, y lo que sale en rojo no lo es.

¿Qué opciones tengo para solucionarlo?

Esquema del orden de carga del navegador con un script normal, con defer y con async

Hay tres caminos, y no son excluyentes.

1. Poner en línea (inline) el script pequeño y crítico

Si el código es corto y solo lo necesita una página, puedes incluirlo directamente en el HTML de esa página. Así no se descarga como un archivo aparte y no afecta al resto del sitio. Es lo que recomienda Google para el código crítico del primer pintado.

2. Aplazarlo con defer

<script src="archivo.js" defer></script>  

El navegador descarga el script mientras sigue leyendo el HTML y lo ejecuta cuando termina de procesar el documento, justo antes de DOMContentLoaded. Si tienes varios con defer, se ejecutan en el orden en que aparecen. Por eso es la opción más segura para la mayoría de scripts que dependen unos de otros.

3. Cargarlo con async

<script src="archivo.js" async></script>  

Aquí el script se descarga en paralelo y se ejecuta en cuanto está listo, sin esperar al resto y sin garantizar el orden. Va bien para scripts independientes, como una herramienta de analítica. No es «más eficiente» que defer en general, simplemente se comporta distinto, y usarlo con scripts que dependen de otros es una receta para errores.

Hoy defer y async funcionan en todos los navegadores actuales, así que la advertencia sobre navegadores antiguos que se repetía en tutoriales de hace años ya no tiene sentido.

¿Cómo lo aplico en WordPress sin romper nada?

Primero lo imprescindible: haz una copia de seguridad y, si puedes, prueba en un entorno de pruebas (staging). Editar header.php o footer.php directamente con un error puede dejar el sitio sin cargar, y esos cambios se pierden si actualizas el tema. Si tocas archivos del tema, hazlo en un tema hijo.

Según tu nivel, estas son las vías, de más sencilla a más técnica:

  • Un plugin de rendimiento. Muchos incluyen una opción para aplazar o retrasar JavaScript. En esta web uso WP Rocket, pero hay más. Lo bueno es que te deja excluir los scripts que den problemas.
  • Cuidado con los plugins antiguos. Muchos tutoriales recomiendan WP Deferred JavaScripts y Async JavaScript. El primero lleva unos 10 años sin actualizarse y está probado solo hasta WordPress 4.6. El segundo se actualizó por última vez hace unos 3 años y ya no está probado con las últimas versiones de WordPress. No son una buena base para una web actual, aunque todavía tengan instalaciones activas.
  • Si desarrollas o tienes quien lo haga. Desde WordPress 6.3, wp_enqueue_script() permite indicar la estrategia al registrar el script:
wp_enqueue_script(      'mi-script',      get_stylesheet_directory_uri() . '/js/mi-script.js',      array(),      '1.0.0',      array( 'strategy' => 'defer' )  );  

Con esta API, WordPress gestiona las dependencias por ti. Si un script con defer tiene otro que lo necesita y es bloqueante, ambos pasan a ser bloqueantes, y un script con código inline en posición «after» también pierde el aplazamiento. Es una protección útil, pero conviene saberlo para no extrañarte.

¿Y qué pasa con jQuery?

Muchos temas y plugins dependen de jQuery y lo usan en el mismo momento en que cargan. Si lo aplazas sin más, es habitual que algo deje de funcionar (menús, sliders, formularios). No lo descartes, pero hazlo con cuidado y revisa después que todo responde.

¿Y si mi web está hecha con React?

Hasta aquí hemos hablado de scripts sueltos en una web WordPress. Es otra historia cuando el contenido entero lo pinta JavaScript en el navegador, como pasa en muchas aplicaciones de una sola página (SPA) hechas con React. Ahí el HTML inicial puede llegar casi vacío, y todo depende de que el buscador ejecute tu código para ver lo que hay.

¿Google puede leer una web en React?

Sí, pero en dos tiempos. Google rastrea la URL, la manda a una cola de renderizado, un Chromium sin interfaz ejecuta el JavaScript y, con el resultado, la indexa. Esa cola puede tardar unos segundos o más, y si la página está bloqueada en el robots.txt, Google no la renderiza. Además, Google avisa de que no todos los bots ejecutan JavaScript, así que lo que solo existe tras ejecutarlo puede quedarse sin ver.

¿Qué opciones tengo para que el contenido llegue en el HTML?

  • Renderizado en el servidor (SSR) o estático. El HTML llega ya con el contenido y React lo «rehidrata» después en el navegador. Frameworks como Next.js lo resuelven de serie, y es lo que Google recomienda.
  • Renderizado dinámico. Servir una versión ya renderizada solo a los rastreadores. Google lo describe como una solución temporal, no a largo plazo, por su complejidad. Y si el contenido que ven los bots difiere del que ven los usuarios, se considera cloaking.
  • Solo en el cliente. Es la opción más arriesgada para el SEO. Puede funcionar, pero dependes de la segunda fase de renderizado.

¿Por qué todas mis páginas tienen el mismo título y la misma descripción?

En una SPA, React solo cambia el contenido de un contenedor del HTML (el típico <div id="root">) y la ruta. Todo lo que queda fuera, incluido el <head>, sigue siendo el del archivo index.html. El resultado es que todas las URLs comparten el mismo title, la misma meta description y las mismas etiquetas robots y canonical. A Google le cuesta entender de qué va cada página, y no puedes marcar solo una como noindex.

La solución es que cada página defina su propio <head>:

  • React 19. Puedes escribir <title> y <meta> dentro del propio componente y React los coloca en el <head>.
  • Versiones anteriores, o si necesitas más control. Una librería como react-helmet-async, un fork de React Helmet que obliga a envolver la aplicación en un HelmetProvider.
  • Páginas dinámicas. Crea un patrón con los datos de cada ficha (nombre, categoría, etc.) para que cada URL tenga un title y una description únicos.
  • Duplicados. Si el index.html trae una meta description por defecto, comprueba que no se queda junto a la nueva.
function Producto({ producto }) {   return (     <>       <title>{producto.nombre} | Mi tienda</title>       <meta name="description" content={producto.resumen} />       {/* resto de la página */}     </>   ) } 

Para comprobarlo, inspecciona el HTML renderizado (clic derecho y «Inspeccionar»), no el «Ver código fuente». Este último te enseña el HTML original, sin los cambios que hace JavaScript. Y ten en cuenta que, si el title solo cambia en el navegador, sigues dependiendo de la fase de renderizado de Google. Con renderizado en el servidor llega ya en el HTML.

¿Qué reviso en una web con React?

  • Enlaces reales. Google solo descubre los enlaces <a> con atributo href, no los que funcionan solo con un onClick.
  • URLs limpias. Usa la History API y evita los fragmentos (#/productos) para cargar contenido.
  • Títulos y descripciones. Google puede leerlos si los cambias con JavaScript, pero es más fiable que ya vengan en el HTML del servidor. En Next.js se definen con la API de metadatos, que se renderiza en el servidor:
export async function generateMetadata({ params }) {   const { slug } = await params   const post = await getPost(slug)   return { title: post.title, description: post.description } } 
  • Canonical y robots. Mejor en el HTML original. Si usas JavaScript para el canonical, que sea una única etiqueta y con el mismo valor. Si el HTML original lleva noindex, Google puede no ejecutar el JavaScript, así que no cuentes con quitarlo después.
  • Códigos de estado. Una página que no existe debe devolver un 404 real. En una SPA, redirige a una URL que devuelva 404 o añade noindex en las páginas de error, para evitar los soft 404.
  • Recursos accesibles. No bloquees en el robots.txt los archivos JavaScript ni las páginas que necesitan renderizarse.

Para comprobarlo, usa la inspección de URL de Search Console y mira el HTML renderizado. Si falta contenido o enlaces ahí, también le faltan a Google.

¿Cómo compruebo que ha funcionado?

  1. Navega por tu web como lo haría un usuario: menú, formularios, sliders, pop-ups, botones de compra o contacto. Abre la consola del navegador y comprueba que no hay errores en rojo.
  2. Vuelve a PageSpeed Insights y compara el LCP antes y después.
  3. Espera a que se actualicen los datos de campo. Se calculan con los últimos 28 días, así que no cambian de un día para otro.
  4. Revisa el informe de Core Web Vitals de Search Console para ver la tendencia real.

Lo que no te voy a prometer

  • Que mejorar la velocidad te suba posiciones. Google recomienda tener buenos Core Web Vitals y dice que se alinean con lo que buscan recompensar sus sistemas de ranking, pero no publica cuánto pesan. La velocidad ayuda, y un contenido relevante sigue siendo lo que más pesa para posicionar.
  • Que React sea malo para el SEO. El problema no es React, sino cómo y cuándo llega el contenido al HTML.
  • Un 100 en PageSpeed. La nota de laboratorio es una simulación y lo que importa son los datos de usuarios reales.
  • Que sea un cambio de cinco minutos. Lo difícil no es aplicar defer, sino localizar qué scripts puedes aplazar sin romper nada.

Checklist rápido

  • ☐ He hecho una copia de seguridad y puedo restaurarla.
  • ☐ He analizado mi URL en PageSpeed Insights y tengo localizados los scripts bloqueantes.
  • ☐ He distinguido qué scripts son críticos y cuáles se pueden aplazar.
  • ☐ He aplicado defer (o async en scripts independientes) con un plugin o con wp_enqueue_script().
  • ☐ He probado menú, formularios y botones, y la consola no muestra errores.
  • ☐ Si uso React u otro framework, el HTML inicial ya incluye el contenido, los enlaces y los metadatos.
  • ☐ He comparado LCP e INP antes y después, y reviso Search Console con el tiempo.

¿Quieres que lo revisemos en tu web?

Cada WordPress es un mundo: tema, plugins y constructores cambian qué puedes aplazar y qué no. Si quieres que le eche un vistazo a tu caso, cuéntamelo y lo vemos.

Cuéntame tu caso

Artículos relacionados

Fuentes

Dame tu valoración