WordPress contra Shopify contra Next.js: la consulta a CrUX que zanja la discusión con datos de España

WordPress contra Shopify contra Next.js: la consulta a CrUX que zanja la discusión con datos de España

El café ya estaba frío cuando el técnico de la otra parte giró el portátil y enseñó una barra. Una sola barra, con tres colores. «WordPress carga en cinco segundos, Next.js en uno y pico. Por eso migramos.» En la sala había siete personas y nadie preguntó lo evidente: cinco segundos, ¿de qué sitios? ¿medidos por quién? ¿en qué país? ¿con qué móvil?

Lo pregunté yo, más por curiosidad que por polémica. La respuesta tardó en llegar y fue peor de lo que esperaba: el número salía de un panel interno de cuarenta webs, todas del mismo hosting, promediadas. Cuarenta. Con eso se estaba justificando una migración de seis cifras.

Esa noche abrí BigQuery. Porque resulta que la discusión lleva años zanjada y nadie la mira: los datos están publicados, son gratis hasta el terabyte mensual y cubren millones de orígenes reales con usuarios reales.

Dos tablas públicas que casi nadie cruza

La primera es el Chrome UX Report. Google recoge métricas de campo de los usuarios de Chrome que tienen activada la sincronización y las publica agregadas por origen y por mes, con desglose por país. No es un laboratorio, no es Lighthouse simulando un móvil de gama media en un centro de datos de Iowa: son personas cargando tu web desde el metro de Madrid con dos barras de cobertura.

La segunda es HTTP Archive, que rastrea cientos de miles de webs cada mes y, entre otras cosas, detecta qué tecnología llevan por debajo. WordPress, Shopify, Next.js, Prestashop, lo que sea. Esa detección tiene sus fallos, ya volveremos a ello.

Cruzando las dos por el origen tienes lo que faltaba en aquella reunión: rendimiento real, por plataforma, en España, con el volumen suficiente para que un caso raro no mueva la aguja.

La trampa está en pedir la mediana

Aquí viene lo que me hizo tirar mi primera consulta a la basura. Yo pedí el percentil 75 de LCP por plataforma, que es lo que mira todo el mundo, y salieron tres números apretados entre sí. Con esa foto, cualquiera de los dos bandos gana la discusión eligiendo el decimal que le conviene.

El histograma cuenta otra historia. CrUX no te da un número por web, te da la distribución completa en cajones: qué proporción de visitas cargó por debajo de 2,5 segundos, cuánta entre 2,5 y 4, cuánta por encima. Y ahí cada plataforma tiene una silueta propia. Una puede tener el grueso bien colocado y un 8% de visitas catastróficas. Otra puede estar toda apelotonada en la zona regular sin desastres. El promedio las empata y son problemas completamente distintos.

Así que dejé de preguntar «cuál es más rápida» y empecé a preguntar «qué porcentaje de orígenes de cada plataforma tiene una cola larga», entendiendo por cola larga que más de una cuarta parte de sus visitas se van por encima de cuatro segundos.

La consulta, entera

WITH tech AS (

  SELECT DISTINCT REGEXP_EXTRACT(page, r’^(https?://[^/]+)’) AS origin, t.technology AS plataforma

  FROM `httparchive.all.pages`, UNNEST(technologies) AS t

  WHERE date = ‘2026-06-01’ AND client = ‘mobile’

    AND t.technology IN (‘WordPress’, ‘Shopify’, ‘Next.js’)

), lcp AS (

  SELECT origin,

    SUM(IF(bin.start < 2500, bin.density, 0)) / SUM(bin.density) AS bueno,

    SUM(IF(bin.start >= 4000, bin.density, 0)) / SUM(bin.density) AS malo

  FROM `chrome-ux-report.country_es.202606`, UNNEST(largest_contentful_paint.histogram.bin) AS bin

  WHERE form_factor.name = ‘phone’ GROUP BY origin

), inp AS (

  SELECT origin,

    SUM(IF(bin.start < 200, bin.density, 0)) / SUM(bin.density) AS bueno,

    SUM(IF(bin.start >= 500, bin.density, 0)) / SUM(bin.density) AS malo

  FROM `chrome-ux-report.country_es.202606`, UNNEST(experimental.interaction_to_next_paint.histogram.bin) AS bin

  WHERE form_factor.name = ‘phone’ GROUP BY origin

), cls AS (

  SELECT origin,

    SUM(IF(CAST(bin.start AS FLOAT64) < 0.1, bin.density, 0)) / SUM(bin.density) AS bueno

  FROM `chrome-ux-report.country_es.202606`, UNNEST(layout_instability.cumulative_layout_shift.histogram.bin) AS bin

  WHERE form_factor.name = ‘phone’ GROUP BY origin

)

SELECT t.plataforma, COUNT(*) AS origenes,

  ROUND(AVG(lcp.bueno) * 100, 1) AS pct_visitas_lcp_ok,

  ROUND(AVG(inp.bueno) * 100, 1) AS pct_visitas_inp_ok,

  ROUND(AVG(cls.bueno) * 100, 1) AS pct_visitas_cls_ok,

  ROUND(COUNTIF(lcp.malo > 0.25) / COUNT(*) * 100, 1) AS pct_webs_con_cola_larga

FROM tech t

JOIN lcp USING (origin) JOIN inp USING (origin) JOIN cls USING (origin)

GROUP BY t.plataforma ORDER BY pct_webs_con_cola_larga DESC

Tres avisos antes de que la pegues. Uno: cada métrica va en su propio bloque a propósito. Si desanidas los tres histogramas en el mismo FROM, BigQuery te hace el producto cartesiano y las densidades se multiplican entre sí; el resultado sale precioso y es basura. Dos: los cajones de CLS vienen como texto, por eso el CAST. Tres: la ruta de INP se ha movido de sitio más de una vez, así que si el mes que consultas te da error, mira el esquema de la tabla antes de darlo por imposible.

Cambia country_es por el país que quieras, cambia el mes, y sobre todo cambia la lista de tecnologías. Ahí está la gracia: si vendes muebles, filtra por tu vertical con el ranking de HTTP Archive y compara contra tus competidores de verdad, no contra la media mundial que incluye blogs abandonados de 2014.

Lo que sí puedo decirte sin mirar la pantalla

Que cada cola tiene una causa distinta, y es lo único que de verdad importa cuando decides una migración.

  • WordPress arrastra su cola por acumulación: un constructor visual que mete hojas de estilo que nadie usa, quince complementos que cargan su propia librería, y un alojamiento compartido que responde tarde a la primera petición.
  • Shopify tiene el servidor resuelto de fábrica, así que su cola casi nunca es el tiempo de respuesta. Es JavaScript de terceros: aplicaciones que inyectan scripts en todas las páginas aunque solo hagan falta en el carrito. Eso destroza la interactividad más que la carga.
  • Next.js se rompe por presunción. Todo el mundo asume que por ser moderno va rápido, y luego hay un montón de proyectos que hidratan medio árbol de componentes en la portada y sirven imágenes sin optimizar desde un dominio ajeno.

Y la letra pequeña honesta: CrUX solo publica orígenes con tráfico suficiente, así que las webs pequeñas ni aparecen. La detección de tecnología falla con las tiendas que van sin cabecera, donde el escaparate es Next.js pero el motor es Shopify, y ahí puedes contar el mismo sitio dos veces. El cruce por origen se come subdominios y variantes con www si no lo cuidas.

Aun con eso, es infinitamente mejor que una barra de tres colores hecha con cuarenta webs de un mismo hosting. Cuando ejecutes esto con tu vertical vas a ver que la plataforma explica bastante menos varianza de lo que te cuentan en las presentaciones comerciales, y que quien la monta y cuánto le dejan meter dentro explican casi todo lo demás. La reunión, por cierto, siguió adelante con la migración. A veces el dato llega tarde.

Comentarios

Aún no hay comentarios. ¿Por qué no comienzas el debate?

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *