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.
Los conceptos clave
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.
- Un placeholder es un marcador temporal en un render array o en el HTML que llega al navegador. Señala un subárbol que Drupal construirá más adelante.
- Un lazy builder es el callback que Drupal invoca para generar el contenido real de ese placeholder.
- BigPipe es una estrategia de entrega para placeholders. Cuando se cumplen las condiciones, Drupal envía primero el esqueleto de la página y luego transmite el marcado de reemplazo de los placeholders seleccionados.
El modelo mental que evita la mayoría de confusiones es secuencial, no sinónimo:
- Drupal ensambla un render array para la página.
- El renderizador puede convertir partes de ese array en placeholders.
- Si la solicitud cumple los requisitos, BigPipe entrega esos placeholders de forma progresiva en lugar de bloquear toda la respuesta.
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.
Cómo funciona el pipeline de renderizado
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.
Qué activa la creación de placeholders
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.
Block Plugin API
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.
Generic Render API
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.
Auto-placeholdering
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.
Cuándo entra en juego BigPipe
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:
- La solicitud usa un método almacenable en caché, normalmente
GET(los métodos no almacenables comoPOSTquedan excluidos para que los formularios dentro de placeholders puedan procesarse de inmediato). - La ruta no ha optado por excluirse mediante la opción de ruta
_no_big_pipe. - La solicitud está asociada a una sesión. Sin sesión, Drupal asume que la respuesta no es realmente dinámica y deja que la caché interna de página se encargue de los visitantes anónimos. BigPipe sigue beneficiando a usuarios anónimos con sesión — el carrito de compras es el ejemplo clásico.
- La solicitud no es una sub-solicitud. BigPipe no puede procesar con seguridad placeholders renderizados dentro de una sub-solicitud porque la pila de solicitudes difiere cuando se renderizan los reemplazos.
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.
¿Necesitas un experto en Drupal?
Echo Flow ayuda a empresas canadienses con ingeniería Drupal de nivel empresarial.
Ejemplo real: navegación en el encabezado
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.
Patrones de código que funcionan
Solo lazy builder
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],
],
];Lazy builder con placeholder explícito
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,
];Soporte de placeholder en block plugins
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;
}Ejemplo de callback de lazy builder
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.
Cómo elegir los candidatos adecuados
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:
- Barra de herramientas o enlaces de cuenta específicos del usuario
- Enlaces contextuales y tareas locales
- Widgets personalizados en la barra lateral
- Fragmentos guardados o vistos recientemente
- Controles secundarios alrededor de una página de búsqueda o listado
Malos candidatos:
- La lista completa de resultados de búsqueda principal
- Todo el área de contenido principal
- Fragmentos grandes cuya ausencia hace que la página inicial se sienta vacía o rota
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.
Referencia rápida
#lazy_builder— este subárbol puede construirse más tarde mediante el callback indicado.#create_placeholder— convierte este subárbol en un placeholder (estableceFALSEpara excluirlo).createPlaceholder()— método de conveniencia para block plugins; el valor predeterminado esFALSEenBlockPluginTrait.- Auto-placeholdering — configurado en
renderer.config; coincide pormax-age, contextos de caché y cache tags. - BigPipe — transmite reemplazos de placeholders elegibles cuando la solicitud es almacenable en caché, tiene sesión, no es una sub-solicitud y la ruta no ha optado por excluirse.
Conclusión
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.