Actualizaciones parciales declarativas

Publicación: 19 de mayo de 2026; última actualización: 8 de septiembre de 2026

La Web hace mucho que dejó de ser el medio estático y basado en documentos que era en sus inicios. Todos usan apps web modernas y enriquecidas por muchos motivos, desde comunicarse, comprar y consumir contenido enriquecido hasta administrar nuestras vidas complejas.

A pesar de todos sus avances, el HTML se sigue entregando en orden, de arriba abajo, sin tener en cuenta cuándo está listo el contenido o cuándo lo consume el usuario. CSS te permite cambiar el orden del contenido, pero, a menudo, con efectos secundarios significativos en la accesibilidad. JavaScript te permite manipular el DOM a través de varias APIs para liberarte un poco de esto, pero estas suelen requerir una sintaxis detallada o la construcción de árboles del DOM para conectarlos a HTML.

El rendimiento es muy importante para la Web, dada la naturaleza cliente-servidor del medio. Sin embargo, a menudo se toman decisiones subóptimas para eludir esta naturaleza ordenada de HTML, lo que ralentiza el rendimiento. Esto incluye esperar hasta que toda la página esté lista o usar un framework pesado para entregar componentes de forma asíncrona. La popularidad de los frameworks de JavaScript demuestra que los desarrolladores web prefieren un modelo basado en componentes en lugar del modelo mental de documentos rígidos de los orígenes de la Web.

El equipo de Chrome ha estado considerando este problema y desarrollando nuevas incorporaciones a la plataforma web con el nombre de Actualizaciones parciales declarativas.

Los primeros dos conjuntos nuevos de APIs facilitan la entrega de HTML de una manera menos lineal, ya sea de forma desordenada en el documento HTML o a través de formas más sencillas de insertar HTML de forma dinámica en documentos existentes con las nuevas APIs de JavaScript. También hay polyfills disponibles para que puedas usar estas nuevas APIs de inmediato, incluso en navegadores que aún no las admiten.

Transmisión desordenada

Browser Support

  • Chrome: 150.
  • Edge: 150.
  • Firefox: not supported.
  • Safari: not supported.

Source

El primer conjunto de cambios son las nuevas APIs de transmisión desordenada que usan marcadores de posición de instrucciones de procesamiento y el elemento HTML <template> con el atributo for. Por ejemplo:

<div>
  <?marker name="placeholder">
</div>

...

<template for="placeholder">
  Here is some <em>HTML content</em>!
</template>

Las instrucciones de procesamiento existen en XML desde hace mucho tiempo, pero se tratan como comentarios en HTML y se ignoran. Esta nueva API cambia eso y agrega instrucciones de procesamiento a HTML. Por ejemplo, cuando el navegador ve la instrucción de procesamiento <?marker name="placeholder">, no hace nada de inmediato, como antes, pero se puede hacer referencia a ella más adelante.

El elemento <template> con el atributo for busca las instrucciones de procesamiento correspondientes con un atributo name y reemplaza el contenido. En este caso, después de analizarse, el DOM termina de la siguiente manera (sin tener en cuenta algunas diferencias de espacios en blanco):

<div>
  Here is some <em>HTML content</em>!
</div>

Además del atributo <?marker> para los reemplazos, también hay marcadores de rango <?start> y <?end> que permiten que se muestre contenido de marcador de posición temporal antes de que se procese la plantilla:

<div>
  <?start name="another-placeholder">
  Loading…
  <?end>
</div>

...

<template for="another-placeholder">
  Here is some <em>HTML content</em>!
</template>

En este caso, se muestra una cadena Loading… hasta que se ve el <template> y, luego, se reemplaza por el contenido nuevo.

También es posible incluir instrucciones de procesamiento en las plantillas para permitir varias actualizaciones:

<ul id="results">
  <?start name="results">
  Loading…
  <?end>
</ul>

...

<template for="results">
  <li>Result One</li>
  <?marker name="results">
</template>

...

<template for="results">
  <li>Result Two</li>
  <?marker name="results">
</template>

...

Esto genera el siguiente código HTML después de analizarlo y procesarlo:

<ul id="results">
  <li>Result One</li>
  <li>Result Two</li>
  <?marker name="results">
</ul>

Con la instrucción de procesamiento final al final, en caso de que se agreguen más marcadores de posición <template for="results"> al documento más adelante.

¿Por qué usar instrucciones de procesamiento en lugar de elementos HTML estándar?

Esta es una pregunta común para quienes usan esta API por primera vez, con sugerencias para usar elementos <slot> o incluso <template>. Una versión inicial de esta propuesta funcionaba con elementos HTML estándar, pero se cambiaron las instrucciones de procesamiento a medida que se iteraba el diseño. Las instrucciones de procesamiento permiten que se apliquen parches sin afectar el DOM. Esto permite que se use en <head>, por ejemplo, para actualizaciones de <title>, o incluso dentro de otros elementos, como <table> (por ejemplo, para agregar filas adicionales opcionales).

A pesar de que la sintaxis no es familiar para muchos desarrolladores web, las instrucciones de procesamiento ofrecen mucha más flexibilidad con menos posibilidades de que se produzcan problemas de retrocompatibilidad. Ya se usan en XML y, gracias a esta propuesta, ahora forman parte del estándar HTML.

Demostración

En este video, se implementa una aplicación básica de álbum de fotos con transmisión de HTML:

Demostración de un álbum de fotos implementado con transmisión desordenada (fuente)

Tanto el estado como las fotos se transmiten al HTML después del diseño inicial.

Casos de uso

Existen muchos casos de uso para este HTML de aplicación de parches fuera de orden cuando se combina con el HTML de transmisión:

  • Arquitectura de islas. Un patrón común popularizado por frameworks como Astro es la arquitectura de islas, en la que los componentes se hidratan de forma independiente sobre el HTML estático. La API de <template for> permite que el contenido estático se controle de manera similar directamente en HTML. Los frameworks de JavaScript también pueden usar esto para islas más interactivas o para controlar componentes.
  • Entrega el contenido cuando esté listo. Gracias a esta arquitectura de islas, el contenido se puede transmitir cuando está listo, en lugar de retenerse para el contenido que requiere un procesamiento adicional, por ejemplo, una búsqueda en la base de datos. Si bien muchas plataformas permiten la transmisión de HTML, la naturaleza ordenada de HTML implica que el contenido suele retenerse o que se recurre a manipulaciones complejas del DOM de JavaScript. Ahora puedes entregar el contenido estático mientras esperas y, luego, conectar contenido más costoso y dinámico al final de la transmisión de HTML.
  • El HTML se puede entregar en el orden óptimo para el rendimiento de la carga de la página. Para ir un paso más allá, puedes cambiar el pedido incluso cuando esté listo. Por ejemplo, los megamenús son una función de navegación común que contiene mucho código HTML que el usuario no verá hasta que la página se vuelva interactiva. Este gran fragmento de HTML se puede entregar más adelante en el documento HTML para priorizar el HTML más importante que se necesita para la carga inicial de la página. El orden ya no es una barrera con HTML.

Estos son solo algunos casos de uso, y nos entusiasma ver para qué usan los desarrolladores esta nueva API.

Restricciones y sutilezas

La API incluye algunas restricciones y sutilezas que debes tener en cuenta:

  • Por motivos de seguridad, <template for> solo puede actualizar las instrucciones de procesamiento dentro del mismo elemento superior. Agregar <template for> directamente al elemento <body> le da acceso a todo el documento (incluido el <head>).
  • La instrucción de procesamiento <?end> es opcional y, si falta, se reemplazará el contenido entre el elemento <?start> y el final del elemento contenedor.
  • Mover las instrucciones de procesamiento después de que un <template for> haya comenzado a transmitirse también puede tener consecuencias inesperadas, ya que el contenido nuevo se seguirá transmitiendo a la ubicación anterior.
  • Ten en cuenta que, cuando se inserta <template for> de forma dinámica con un método como setHTML o la propiedad innerHTML, el "elemento superior" de la plantilla cuando se analiza es un fragmento de documento intermedio. Esto significa que insertar HTML con estos métodos no puede modificar el DOM existente, y la aplicación de parches se produce "en el lugar" dentro del fragmento. Sin embargo, cuando se transmite con métodos como streamHTMLUnsafe (que se explica en breve), no hay un fragmento intermedio, por lo que las plantillas pueden reemplazar el contenido existente.

Estado de estandarización

El atributo <template for> es parte del estándar HTML, pero aún no es compatible con todos los navegadores.

Posibles incorporaciones futuras

Estas son algunas de las posibles incorporaciones futuras que se están considerando:

  • Inclusiones del cliente. Por ejemplo, <template for="footer" src="/partials/footer.html"> o incluso sin aplicar parches <template src="/partials/footer.html">. Para obtener más detalles, consulta la explicación. Esta función está disponible detrás de la marca chrome://flags/#enable-experimental-web-platform-features.
  • Evitar reemplazar contenido que no cambiará Esto se podría lograr con un número de revisión o un control de versiones del contenido. Esto permitiría que el estado se mantenga entre los cambios de ruta o de otras actualizaciones, en lugar de restablecer el contenido.
  • Saneamiento durante la aplicación de parches Por ejemplo, <template for=icon safe><svg id="from-untrusted-source">...</svg></template>

Polyfill

El equipo de Chrome lanzó un template-for-polyfill que está disponible en npm para permitir que los sitios usen esta nueva funcionalidad de inmediato, incluso antes de que llegue a otros navegadores.

Existen algunas limitaciones, ya que no puede actualizar directamente los analizadores de HTML del navegador, pero se abarcan los casos de uso más comunes. Los sitios aún deben realizar pruebas en otros navegadores.

Métodos renovados de inserción y transmisión de HTML

No todo el contenido se puede publicar como HTML. La segunda parte del trabajo que Chrome realizó en esta área tiene como objetivo facilitar la actualización de contenido con JavaScript.

Ya existen varias formas de insertar HTML de forma dinámica en un documento existente con JavaScript:

  • setHTML
  • setHTMLUnsafe
  • innerHTML y outerHTML
  • createContextualFragment
  • insertAdjacentHTML

Sin embargo, todas funcionan de maneras un poco diferentes, con sutilezas y diferencias que los desarrolladores no siempre tienen en cuenta:

  • ¿El contenido nuevo reemplaza o agrega?
  • ¿Sanean el código HTML potencialmente peligroso, por ejemplo, escapando las etiquetas <script>?
  • De lo contrario, ¿debería ejecutarse <script>?
  • ¿Cómo funcionan con los tipos de confianza?

Pocos desarrolladores podrían analizar esas APIs con honestidad y responder esas preguntas con confianza para cada una de ellas.

Una gran limitación es que solo se pueden usar para un conjunto completo de HTML conocido de antemano, cuando se realizaron llamadas para permitir que se transmita HTML. En la práctica, esto significa que debes descargar todo el contenido antes de insertarlo, cuando uno de los puntos fuertes de HTML es la capacidad de transmitir contenido de inmediato. Esto se puede solucionar de forma limitada dividiendo las cargas útiles o usando métodos obsoletos y poco recomendables, como document.write, pero estos presentan sus propios problemas.

Un nuevo conjunto de APIs estáticas y de transmisión

Browser Support

  • Chrome: behind a flag.
  • Edge: behind a flag.
  • Firefox: not supported.
  • Safari: not supported.

Chrome trabajó en un conjunto de APIs nuevas y extensiones para las existentes setHTML y setHTMLUnsafe que limpian esto, además de introducir la funcionalidad de transmisión.

Estas funciones están listas para que los desarrolladores las prueben a partir de Chrome 148 con la marca chrome://flags/#enable-experimental-web-platform-features y se planea lanzarlas en Chrome 155.

Existen métodos para establecer o reemplazar, junto con métodos para insertar contenido antes o después del HTML existente. Cada método tiene equivalentes de transmisión:

Acción Estática Transmisión
Establece el contenido HTML del elemento setHTML(html, options); streamHTML(options);
Reemplaza todo el elemento por este HTML replaceWithHTML(html, options); streamReplaceWithHTML(options);
Agrega el código HTML antes del elemento beforeHTML(html, options); streamBeforeHTML(options);
Agrega el código HTML como el primer elemento secundario del elemento prependHTML(html, options); streamPrependHTML(options);
Agrega el HTML como el último elemento secundario del elemento appendHTML(html, options); streamAppendHTML(options);
Agrega el código HTML después del elemento afterHTML(html, options); streamAfterHTML(options);
Los nuevos métodos de inserción y transmisión

También hay versiones de Unsafe que se abordarán en breve. Si bien puede parecer que hay muchos (en especial cuando agregas los equivalentes de Unsafe), la convención de nombres coherente hace que sea más evidente lo que hace cada uno en comparación con los métodos no relacionados que se mencionaron anteriormente.

Las versiones estáticas toman el HTML nuevo como un argumento de cadena del DOM, junto con opciones opcionales:

const newHTML = "<p>This is a new paragraph</p>";
const contentElement = document.querySelector('#content-to-update');

contentElement.setHTML(newHTML);

Las versiones de transmisión funcionan con la API de Streams, como con un getWriter():

const contentElement = document.querySelector('#content-to-update');
const writer = contentElement.streamHTMLUnsafe().getWriter();

// Example stream of updating content
while (true) {
  await writer.write(`<p>${++i}</p>`);
  await new Promise((resolve) => setTimeout(resolve, 1000));
}

writer.close();

O, de forma alternativa, desde una respuesta de recuperación con cadenas de canalización:

const contentElement = document.querySelector('#content-to-update');
const response = await fetch('/api/content.html');

response.body
  .pipeThrough(new TextDecoderStream())
  .pipeTo(contentElement.streamHTMLUnsafe());

Método de conveniencia textStream()

Browser Support

  • Chrome: 151.
  • Edge: 151.
  • Firefox: not supported.
  • Safari: not supported.

Source

También se agregó un método de conveniencia textStream, en el que puedes transmitir directamente sin necesidad del paso intermedio TextDecoderStream():

const contentElement = document.querySelector('#content-to-update');
const response = await fetch('/api/content.html');

response.textStream().pipeTo(contentElement.streamHTMLUnsafe());

options

El argumento options te permite especificar un sanitizer personalizado, que se establece de forma predeterminada en default, lo que significa la configuración predeterminada del limpiador. Se usa de la siguiente manera:

const newHTML = '<p>This is a new paragraph</p>';
const contentElement = document.querySelector('#content-to-update');

// Only allows basic formatting
const basicFormattingSanitzer = new Sanitizer({ elements: ['em', 'i', 'b', 'strong'] });

contentElement.setHTML(newHTML, {sanitizer: basicFormattingSanitzer});

Métodos "no seguros"

También hay versiones "no seguras" de cada una de las APIs:

Acción Estática Transmisión
Establece el contenido HTML del elemento setHTMLUnsafe(html,options); streamHTMLUnsafe(options);
Reemplaza todo el elemento por este HTML replaceWithHTMLUnsafe(html, options); streamReplaceWithHTMLUnsafe(options);
Agrega el código HTML antes del elemento beforeHTMLUnsafe(html, options); streamBeforeHTMLUnsafe(options);
Agrega el código HTML como el primer elemento secundario del elemento prependHTMLUnsafe(html, options); streamPrependHTMLUnsafe(options);
Agrega el HTML como el último elemento secundario del elemento appendHTMLUnsafe(html, options); streamAppendHTMLUnsafe(options);
Agrega el código HTML después del elemento afterHTMLUnsafe(html, options); streamAfterHTMLUnsafe(options);
Los métodos de inserción y transmisión "no seguros"

Estos métodos "no seguros" desactivan el limpiador de forma predeterminada, y puedes especificar uno personalizado si lo deseas. Estos métodos también permiten que las secuencias de comandos se ejecuten con una opción runScripts opcional, que se establece de forma predeterminada en false.

Al igual que setHTML, setHTMLUnsafe es un método existente, pero se le agregó el parámetro de opciones runScripts para permitir que se use con la ejecución de secuencias de comandos:

const newHTML = `<p>This is a new paragraph</p>
                 <script src=script.js></script>`;
const contentElement = document.querySelector('#content-to-update');

contentElement.setHTMLUnsafe(newHTML, {runScripts: true});

La palabra "unsafe" en el método es para recordarles a los desarrolladores el riesgo potencial y cómo pueden limpiar o restringir las secuencias de comandos, no para decir que estos métodos no se deben usar.

El nivel de "inseguridad" de esto depende de la confiabilidad de las entradas. Todos los métodos estáticos de Unsafe funcionan con la cadena del DOM o TrustedHTML como argumentos de html y también permiten usar limpiadores. Sin embargo, con runScript, el objetivo es permitir las secuencias de comandos, por lo que, de forma predeterminada, no se usa ningún limpiador.

Casos de uso

Estas nuevas APIs facilitan que los desarrolladores agreguen HTML a las páginas existentes, ya que incorporan nuevas APIs con nombres y opciones coherentes. Las APIs de transmisión aportan los beneficios de rendimiento de no tener que esperar hasta que todo el contenido nuevo esté disponible en la plataforma.

En los casos de uso, se incluye lo siguiente:

  • Transmisión dinámica de actualizaciones de contenido de gran tamaño en aplicaciones de una sola página Como se mencionó anteriormente, un gran inconveniente de la arquitectura de SPA actual es que no se beneficia de la naturaleza de transmisión de las cargas iniciales de HTML, ¡hasta ahora!
  • Insertar contenido común, como pies de página HTML El uso de las APIs de JavaScript te permite extraer parciales y, luego, insertarlos en la página, lo que aprovecha el almacenamiento en caché, en lugar de repetirlos en cada página enviada. Sin embargo, dada la dependencia de JavaScript para ejecutarse, esto solo se debe usar para el contenido que no será visible en la carga inicial.

De nuevo, esos son solo un par de ejemplos, y estamos ansiosos por ver qué se les ocurre.

Restricciones y sutilezas

Estas APIs nuevas también incluyen algunas restricciones y sutilezas que debes tener en cuenta:

  • La integración de la transmisión con la API de Trusted Types requiere el uso de un nuevo método createParserOptions que permite insertar un limpiador en cualquier operación de configuración de HTML. Consulta la explicación para obtener más detalles sobre la integración de tipos de confianza.
  • Al igual que con <template for>, mover elementos que se están transmitiendo puede generar consecuencias inesperadas o errores de transmisión.
  • streamHTMLUnsafe funciona más como el analizador principal en muchos aspectos, incluido el procesamiento de instrucciones <template for> a medida que se agregan al documento principal y el aplazamiento de secuencias de comandos defer hasta el final de la transmisión.

Estado de estandarización

Los métodos de inserción y transmisión más nuevos están en proceso de agregarse al estándar HTML, pero aún no son compatibles con todos los navegadores.

Polyfill

El equipo de Chrome lanzó un html-setters-polyfill que está disponible en npm para permitir que los sitios usen esta nueva funcionalidad de inmediato, incluso antes de que llegue a otros navegadores.

Ten en cuenta que este polyfill no transmite, sino que almacena en búfer y se aplica cuando se completa. Es más un polyfill para la forma de la API que para la funcionalidad.

Además, la configuración del contenido seguro depende de setHTML y de la API de Sanitizer, que no es compatible con Safari.

Usarlas en conjunto

Si bien estas son dos APIs independientes, su verdadero poder reside en combinarlas. Si transmites elementos <template for> nuevos al HTML, puedes actualizar de forma dinámica diferentes partes del contenido sin tener que segmentar cada una de ellas con referencias de JavaScript independientes al DOM.

Se podría implementar una carga de página básica de estilo SPA cargando una página de esquema con instrucciones de procesamiento y, luego, transmitiendo las plantillas de cada página nueva en la parte inferior del HTML para que se inserten en esas instrucciones de procesamiento.

Sin duda, hay más potencial y casos de uso para ambas APIs, así que no dejes que nuestra imaginación (limitada) te detenga. Si facilitas la administración de las actualizaciones parciales, puedes reducir parte del código estándar, facilitar las actualizaciones y desbloquear un nuevo potencial para la Web.

Chrome está trabajando en algunas APIs más en el marco del proyecto de actualizaciones parciales declarativas, pero nos complace poner estas dos primeras en tus manos. Te mantendremos al tanto y te informaremos cuando haya más contenido disponible en este espacio.