Publicado: 19 de mayo de 2026, última actualización: 8 de septiembre de 2026
Hace mucho tiempo que la Web dejó de ser el medio estático basado en documentos que era en sus inicios. Todo el mundo usa 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 lenguaje HTML sigue entregándose en orden, de arriba hacia abajo, sin tener en cuenta cuándo el contenido está listo o cuándo el usuario lo consume. 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 a menudo requieren una sintaxis detallada o la construcción de árboles DOM para conectarlos a HTML.
El rendimiento es increíblemente importante para la Web, dada la naturaleza cliente-servidor del medio. Sin embargo, a menudo se toman decisiones subóptimas para evitar esta naturaleza ordenada del 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 rígido de documentos de los orígenes de la Web.
El equipo de Chrome ha estado considerando este problema y ha desarrollado nuevas incorporaciones a la plataforma web con el nombre de Actualizaciones parciales declarativas.
Los dos primeros conjuntos nuevos de APIs facilitan la entrega de HTML de una manera menos lineal, ya sea fuera de orden en el documento HTML en sí 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
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 trataron como comentarios en HTML y se ignoraron. 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 (ignorando 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 mostrar 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>
...
Después de analizarse y procesarse, el resultado es el siguiente código HTML:
<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é se usan 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> (para agregar filas adicionales opcionales, por ejemplo).
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 problemas de compatibilidad con versiones anteriores. 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 HTML de transmisión continua:
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 parche HTML 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 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 usarlo para islas más interactivas o para controlar componentes. - Publica 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 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 este lenguaje implica que, a menudo, el contenido se retrasa o se recurre a manipulaciones complejas del DOM de JavaScript. Ahora puedes entregar el contenido estático mientras esperas y, luego, insertar contenido más costoso y dinámico al final de la transmisión HTML.
- El código HTML se puede entregar en el orden óptimo para el rendimiento de carga de la página. Si vas un paso más allá, puedes cambiar el orden incluso cuando esté listo. Por ejemplo, los menús desplegables 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 necesario para la carga de página inicial. El orden ya no es un obstáculo con HTML.
Estos son solo algunos casos de uso, y nos entusiasma ver para qué usarán los desarrolladores esta nueva API.
Restricciones y detalles
La API incluye algunas restricciones y detalles que debes tener en cuenta:
- Por motivos de seguridad,
<template for>solo puede actualizar las instrucciones de procesamiento dentro del mismo elemento principal. Si agregas<template for>directamente al elemento<body>, este tendrá 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 se haya iniciado la transmisión de un
<template for>también puede tener consecuencias inesperadas, ya que el contenido nuevo seguirá transmitiéndose a la ubicación anterior. - Ten en cuenta que, cuando se inserta
<template for>de forma dinámica con un método comosetHTMLo la propiedadinnerHTML, 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 realiza "in situ" dentro del fragmento. Sin embargo, cuando se transmite contenido con métodos comostreamHTMLUnsafe(que se explicará en breve), no hay fragmentos intermedios, 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 se admite en todos los navegadores.
Posibles incorporaciones futuras
Estas son algunas posibles incorporaciones futuras que se están considerando:
- Incluye el lado del cliente. Por ejemplo,
<template for="footer" src="/partials/footer.html">o incluso sin parches<template src="/partials/footer.html">. Para obtener más detalles, consulta el video explicativo. Esta opción está disponible detrás de la marcachrome://flags/#enable-experimental-web-platform-features. - Evita sobrescribir el contenido que no cambiará. Esto se podría lograr con un número de revisión o control de versiones del contenido. Esto permitiría mantener el estado entre los cambios de ruta o las actualizaciones, en lugar de restablecer el contenido.
- Limpieza durante la reparación 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 se lance en otros navegadores.
Existen algunas limitaciones, ya que no puede actualizar directamente los analizadores de HTML del navegador, pero se cubren los casos de uso más comunes. Los sitios deben seguir probándose en otros navegadores.
Se renovaron los métodos de inserción y transmisión de HTML
No todo el contenido se puede entregar como HTML. Una segunda parte del trabajo que Chrome realizó en esta área tiene como objetivo facilitar la actualización del contenido con JavaScript.
Ya existen varias formas de insertar HTML de forma dinámica en un documento existente con JavaScript:
setHTMLsetHTMLUnsafeinnerHTMLyouterHTMLcreateContextualFragmentinsertAdjacentHTML
Sin embargo, todos funcionan de maneras ligeramente diferentes, con sutilezas y diferencias que los desarrolladores no siempre tienen en cuenta:
- ¿El contenido nuevo reemplaza el contenido existente o se agrega a él?
- ¿Sanean el HTML potencialmente peligroso, por ejemplo, escapando las etiquetas
<script>? - Si no es así, ¿se debería ejecutar
<script>? - ¿Cómo funcionan con Trusted Types?
Pocos desarrolladores podrían mirar 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 el streaming de HTML. En la práctica, esto significa que debes descargar todo el contenido antes de insertarlo, cuando uno de los puntos fuertes del HTML es la capacidad de transmitir contenido de inmediato. Esto se puede solucionar de forma limitada dividiendo las cargas útiles o usando métodos hacky y obsoletos como document.write, pero estos métodos introducen sus propios problemas.
Un nuevo conjunto de APIs de transmisión y estáticas
Browser Support
Chrome trabajó en un conjunto de nuevas APIs 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, además de métodos para insertar contenido antes o después del código 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 con este código 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 código 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); |
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 nomenclatura coherente hace que sea más obvio lo que hace cada uno en comparación con los métodos no relacionados que se mencionaron anteriormente.
Las versiones estáticas toman el nuevo HTML como un argumento de cadena 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 bien, 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
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, de forma predeterminada, es default, lo que significa la configuración predeterminada del filtro. 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 "inseguros"
También hay versiones "inseguras" 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 con este código 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 código 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); |
Estos métodos "inseguros" desactivan el filtro de forma predeterminada, y puedes especificar un filtro personalizado si lo deseas. Estos métodos también permiten que se ejecuten secuencias de comandos con una opción runScripts opcional, que, de forma predeterminada, es 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 "inseguro" en el método tiene como objetivo recordarles a los desarrolladores el riesgo potencial y cómo podrían querer limpiar o restringir los scripts, no decir que estos métodos no se deben usar.
El nivel de "inseguridad" depende de la confiabilidad de las entradas. Todos los métodos estáticos de Unsafe funcionan con la cadena del DOM o con TrustedHTML como argumentos de html y también permiten el uso de saneadores. Sin embargo, con runScript, la intención es permitir scripts, por lo que, de forma predeterminada, no se usa ningún sanitizador.
Casos de uso
Estas nuevas APIs facilitan a los desarrolladores la tarea de agregar HTML a las páginas existentes, ya que agregan APIs nuevas con nombres y opciones coherentes. Las APIs de transmisión brindan 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 grandes 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 de HTML iniciales, hasta ahora.
- Insertar contenido común, como pies de página en HTML El uso de las APIs de JavaScript te permite extraer parciales e insertarlos en la página, lo que te beneficia del almacenamiento en caché, en lugar de repetirlos en cada página enviada. Sin embargo, dada la dependencia de JavaScript para ejecutarse, esto solo debe usarse para el contenido que no se verá en la carga inicial.
Una vez más, estos son solo algunos ejemplos, y nos entusiasma ver lo que se les ocurre a todos.
Restricciones y detalles
Estas nuevas APIs también incluyen algunas restricciones y detalles 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
createParserOptionsque permite insertar un sanitizador en cualquier operación de configuración de HTML. Consulta el video explicativo para obtener más detalles sobre la integración de Trusted Types - Al igual que con
<template for>, mover elementos que se están transmitiendo puede generar consecuencias inesperadas o errores de transmisión. streamHTMLUnsafefunciona más como el analizador principal en muchos sentidos, incluido el procesamiento de las instrucciones<template for>a medida que se agregan al documento principal y el aplazamiento de las secuencias de comandosdeferhasta el final de la transmisión.
Estado de estandarización
Los métodos de inserción y transmisión más recientes 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 se lance en otros navegadores.
Ten en cuenta que este polyfill no transmite, sino que se 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 de contenido seguro depende de setHTML y de la API de Sanitizer, que no es compatible con Safari.
Usar ambas en conjunto
Si bien estas son dos APIs independientes, su verdadero poder reside en combinarlas. Si transmites nuevos elementos <template for> al HTML, puedes actualizar de forma dinámica diferentes partes del contenido sin tener que segmentar directamente cada una con referencias de JavaScript independientes al DOM.
Se podría implementar una carga de página básica al estilo de SPA cargando una página de esquema con instrucciones de procesamiento y, luego, transmitiendo las plantillas de cada página nueva a la parte inferior del HTML para insertarlas 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. Al facilitar la administración de las actualizaciones parciales, puedes reducir parte del código estándar, facilitar las actualizaciones y desbloquear nuevas posibilidades para la Web.
Chrome está trabajando en algunas APIs más en el 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 novedades en este espacio.