La percepción de velocidad importa tanto como el rendimiento bruto del servidor. En una página típica de Drupal, unos pocos fragmentos — enlaces de cuenta, menús, barras de herramientas, widgets personalizados — cambian según el usuario o la sesión, mientras que el resto del diseño podría almacenarse en caché y enviarse de inmediato. Los placeholders y BigPipe son la forma en que Drupal separa esas responsabilidades: posponer lo costoso, enviar primero el esqueleto y completar los huecos cuando estén listos.
Antes de entrar en archivos de configuración o render arrays, conviene fijar tres términos. En la conversación suelen usarse como sinónimos, pero en Drupal describen capas distintas del mismo flujo.
El modelo mental que evita la mayoría de confusiones es secuencial, no sinónimo:
BigPipe no es el mecanismo de placeholders en sí. El placeholdering pertenece a la Render API; BigPipe es la capa de entrega progresiva que puede apoyarse sobre ella.
Todo controlador, bloque, entity view builder y field formatter termina aportando render arrays. En el camino, el renderizador verifica si un subárbol puede diferirse, si debe convertirse en placeholder y si BigPipe puede transmitir el resultado. El diagrama siguiente muestra esos puntos de decisión.
Drupal generalmente requiere un #lazy_builder en un subárbol del render array antes de que el placeholdering sea posible. Una vez que existe ese callback, la creación del placeholder puede solicitarse de forma explícita, proporcionarse mediante un block plugin o activarse automáticamente cuando la cacheabilidad es baja.
Los block plugins pueden incorporarse al flujo de placeholders mediante un método dedicado en BlockPluginInterface. El valor predeterminado en BlockPluginTrait es FALSE; los bloques individuales lo sobrescriben cuando tiene sentido diferir el renderizado.
public function createPlaceholder(): bool {
return TRUE;
}Esta API aplica solo a block plugins, no a entidades, campos o nodos en general. En el core de Drupal, SystemMenuBlock devuelve TRUE, por eso los bloques de navegación son compatibles con placeholders desde el inicio. Su salida suele depender de la ruta activa del menú y de la ruta actual, contextos de caché que no encajan en una sola entrada compartida de caché de página.
Cualquier código que devuelva un render array puede diferir un subárbol con #lazy_builder y solicitar explícitamente la conversión a placeholder:
$build['dynamic_part'] = [
'#lazy_builder' => [static::class . '::lazyPart', [$id]],
'#create_placeholder' => TRUE,
];Es el patrón de uso general y funciona fuera de la Block API. Los puntos de integración habituales incluyen los arrays build() de bloques, entity view builders, field formatters, contextual link builders y controladores personalizados.
Establecer #create_placeholder en FALSE impide explícitamente el placeholdering aunque exista un lazy builder. Resulta útil cuando necesitas la semántica de renderizado diferido sin pasar por la ruta de entrega de placeholders.
Incluso sin #create_placeholder => TRUE, Drupal puede convertir automáticamente subárboles con lazy builder en placeholders cuando sus metadatos de cacheabilidad coinciden con los umbrales configurados. Los valores predeterminados están en sites/default/default.services.yml, bajo renderer.config:
renderer.config:
auto_placeholder_conditions:
max-age: 0
contexts: ['session', 'user']
tags: []En la práctica, el auto-placeholdering se activa cuando un elemento con lazy builder tiene un max-age igual o inferior al límite configurado (0 por defecto), cuando sus contextos de caché se cruzan con la lista configurada (session y user por defecto) o cuando sus cache tags coinciden con los tags configurados (vacío por defecto). Puedes ajustar o desactivar condiciones individuales: establece max-age en -1 o contexts en [] para deshabilitarlas.
El auto-placeholdering no significa que toda la página pase por BigPipe. Solo afecta a subárboles individuales que ya califican para placeholdering y llevan metadatos de cacheabilidad que cumplen estas reglas.
Una vez que existen placeholders, un conjunto aparte de condiciones determina si BigPipe transmite sus reemplazos o si Drupal los resuelve en el flujo estándar de respuesta única. El placeholdering y BigPipe están relacionados, pero son decisiones independientes.
Según BigPipeStrategy en el core de Drupal, BigPipe se aplica cuando se cumplen todas las condiciones siguientes:
GET (los métodos no almacenables como POST quedan excluidos para que los formularios dentro de placeholders puedan procesarse de inmediato)._no_big_pipe.Cuando BigPipe se activa, usa una de dos subestrategias. Con JavaScript habilitado, los reemplazos se transmiten al final de la página y se intercambian en el DOM — en general, la mejor experiencia de rendimiento percibido. Cuando está presente la cookie big_pipe_nojs, o para placeholders a nivel de atributo que no pueden localizarse de forma eficiente con querySelector, los reemplazos se transmiten en el lugar mediante múltiples flushes. Ambos enfoques pueden coexistir en la misma página.
Echo Flow ayuda a empresas canadienses con ingeniería Drupal de nivel empresarial.
Un patrón habitual en sitios Drupal con mucho contenido muestra cómo encajan estas piezas en producción. Imagina un sitio que habilita el módulo big_pipe en su perfil de instalación: el módulo forma parte del core de Drupal y viene activado por defecto en el perfil Standard.
El tema imprime la navegación principal en el encabezado de la página, a menudo renderizando un bloque de menú colocado en la región de encabezado de page.html.twig. Como SystemMenuBlock opta por el placeholdering y sus contextos de caché varían con la ruta activa, los visitantes autenticados pueden recibir un esqueleto de página rápido mientras el marcado del menú aún se está construyendo.
El código frontend a veces debe contemplar ese retraso. Un componente del tema asociado al encabezado puede escuchar los behaviors de Drupal o vigilar actualizaciones del DOM después de que BigPipe inyecte el HTML final del menú — por ejemplo, para inicializar un toggle móvil, recalcular offsets fijos o enlazar la navegación por teclado una vez que los enlaces estén presentes. Ese tipo de JavaScript defensivo es una señal práctica de que el renderizado basado en placeholders está en juego, incluso cuando no se escribió un lazy builder personalizado para el proyecto.
No necesitas un lazy builder personalizado para aprovechar este patrón. El manejo de bloques y menús del core ya participa en el pipeline de placeholders cuando la cacheabilidad lo justifica.
Declarar un lazy builder hace posible el renderizado diferido, pero por sí solo no fuerza la creación de un placeholder. El auto-placeholdering puede activarse igual si los metadatos de cacheabilidad coinciden con las condiciones configuradas.
$build['links'] = [
'#lazy_builder' => [
static::class . '::renderLinks',
[$entity->id(), $view_mode],
],
];Es el patrón de uso general más directo cuando sabes que un subárbol debe reemplazarse de forma asíncrona.
$build['links'] = [
'#lazy_builder' => [
static::class . '::renderLinks',
[$entity->id(), $view_mode],
],
'#create_placeholder' => TRUE,
];En block plugins, sobrescribir createPlaceholder() indica al block view builder de Drupal que dirija el bloque por la ruta de placeholders.
public function createPlaceholder(): bool {
return TRUE;
}El callback en sí devuelve un render array como cualquier otro builder. Los metadatos de caché de ese array determinan cómo se almacena la salida final y si el auto-placeholdering aplica en etapas anteriores.
public static function lazyPart($id): array {
return [
'#markup' => 'Rendered later: ' . $id,
'#cache' => [
'contexts' => ['user'],
],
];
}Como varía según el usuario, es un candidato sólido para auto-placeholdering bajo las condiciones predeterminadas de renderer.config.
BigPipe rinde cuando la página tiene un esqueleto significativo que se sostiene por sí solo mientras fragmentos dinámicos más pequeños llegan un instante después. El objetivo es un primer pintado más rápido y una sensación de respuesta ágil, no empujar cada operación costosa detrás de un placeholder.
Buenos candidatos:
Malos candidatos:
En páginas de búsqueda pesadas, BigPipe puede ayudar con fragmentos dinámicos periféricos, pero rara vez es la primera palanca para una lista de resultados lenta. Empieza por el costo de las consultas, la configuración de Views, el ajuste del backend de búsqueda y el overhead de renderizado por fila. Drupal 11.3 también introdujo optimizaciones más amplias de render cache y placeholders que reducen la carga en muchas páginas — vale la pena actualizar antes de buscar soluciones personalizadas con BigPipe.
#lazy_builder — este subárbol puede construirse más tarde mediante el callback indicado.#create_placeholder — convierte este subárbol en un placeholder (establece FALSE para excluirlo).createPlaceholder() — método de conveniencia para block plugins; el valor predeterminado es FALSE en BlockPluginTrait.renderer.config; coincide por max-age, contextos de caché y cache tags.El placeholdering es el mecanismo en tiempo de renderizado que permite a Drupal diferir trabajo sin bloquear toda la página. BigPipe es la estrategia de entrega que puede transmitir esos fragmentos diferidos después de que el esqueleto llegue al navegador. Entender dónde ocurre cada decisión — lazy builders, creación explícita o automática de placeholders y elegibilidad de BigPipe — facilita mucho depurar páginas lentas para usuarios autenticados, diseñar bloques con metadatos de caché sensatos y elegir qué fragmentos vale la pena diferir.
Ya sea que mantengas un bloque personalizado, ajustes el encabezado de un tema o perfilas una View compleja, la frase base sigue vigente: el placeholdering define qué se difiere; BigPipe define cómo llega.