Опубликовано: 19 мая 2026 г., Последнее обновление: 8 сентября 2026 г.
Интернет давно отошел от статической, основанной на документах среды, с которой он начинался. Современные многофункциональные веб-приложения используются всеми по самым разным причинам: от общения и покупок до потребления контента и управления нашей сложной жизнью.
HTML, несмотря на все свои достижения, по-прежнему отображается в порядке сверху вниз, практически не обращая внимания на то, когда контент готов или когда пользователь его просматривает. CSS позволяет изменять порядок контента, но часто с существенными побочными эффектами, влияющими на доступность. JavaScript позволяет манипулировать DOM с помощью различных API, чтобы в некоторой степени обойти это ограничение, но они часто требуют многословного синтаксиса или построения деревьев DOM для интеграции в HTML.
Производительность невероятно важна для веб-разработки, учитывая клиент-серверную природу этого средства. Однако часто принимаются неоптимальные решения, чтобы обойти эту последовательную структуру HTML, что замедляет производительность. К ним относятся ожидание полной готовности всей страницы или использование ресурсоемкого фреймворка для асинхронной доставки компонентов. Популярность JavaScript-фреймворков показывает, что веб-разработчики предпочитают компонентно-ориентированную модель жесткой документоориентированной модели, унаследованной от истоков веб-разработки.
Команда Chrome рассматривает эту проблему и разрабатывает новые дополнения для веб-платформы под названием «Декларативные частичные обновления» .
Первые два новых набора API упрощают передачу HTML-кода менее линейным способом, будь то в произвольном порядке в самом HTML-документе или с помощью более простых способов динамической вставки HTML в существующие документы с использованием новых API JavaScript. Также доступны полифилы, позволяющие сразу же использовать эти новые API, даже в браузерах, которые их еще не поддерживают.
Потоковое вещание не по порядку
Первая группа изменений включает в себя новые API для потоковой передачи данных в произвольном порядке с использованием заполнителей инструкций обработки и HTML-элемента <template> с атрибутом for . Например:
<div>
<?marker name="placeholder">
</div>
...
<template for="placeholder">
Here is some <em>HTML content</em>!
</template>
Инструкции по обработке существовали в XML давно, но в HTML они рассматривались как комментарии и игнорировались. Новый API меняет это и переносит инструкции по обработке в HTML. Например, когда браузер видит инструкцию по обработке <?marker name="placeholder"> , он ничего не делает сразу — как и раньше — но на неё можно сослаться позже.
Элемент <template> с атрибутом for находит соответствующие инструкции обработки с атрибутом name и заменяет содержимое. В этом случае после парсинга DOM-структура выглядит следующим образом (без учета некоторых различий в пробелах):
<div>
Here is some <em>HTML content</em>!
</div>
Помимо атрибута <?marker> для замен, существуют также маркеры диапазона <?start> и <?end> , которые позволяют отображать временное содержимое-заполнитель до обработки шаблона:
<div>
<?start name="another-placeholder">
Loading…
<?end>
</div>
...
<template for="another-placeholder">
Here is some <em>HTML content</em>!
</template>
В этом случае строка Loading… отображается до тех пор, пока не будет показан <template> , после чего она заменяется новым содержимым.
Также можно включать инструкции по обработке в шаблоны, что позволяет выполнять множественные обновления:
<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>
...
В результате после анализа и обработки получается следующий HTML-код:
<ul id="results">
<li>Result One</li>
<li>Result Two</li>
<?marker name="results">
</ul>
В конце приводится окончательная инструкция по обработке на случай, если в документ позже будут добавлены дополнительные заполнители <template for="results"> .
Почему именно инструкции по обработке, а не стандартные HTML-элементы?
Это распространенный вопрос для тех, кто впервые использует этот API, и часто предлагаются варианты использования элементов <slot> или даже <template> . Первоначальная версия этого предложения работала со стандартными HTML-элементами, но в процессе доработки дизайна были изменены инструкции обработки. Инструкции обработки позволяют вносить изменения без влияния на DOM. Это позволяет использовать их в <head> — например, для обновления <title> — или даже внутри других элементов, таких как <table> (например, для добавления дополнительных строк).
Несмотря на то, что синтаксис этих инструкций незнаком многим веб-разработчикам, они обеспечивают гораздо большую гибкость и снижают вероятность проблем с обратной совместимостью. Они уже используются в XML и благодаря этому предложению стали частью стандарта HTML .
Демо
В этом видео реализовано базовое приложение для создания фотоальбомов с использованием потокового HTML:
И статус, и фотографии передаются в HTML-код после первоначальной разметки.
Варианты использования
Существует множество вариантов применения такого способа внесения изменений в HTML-код в произвольном порядке в сочетании с потоковой передачей HTML:
- Островная архитектура. Распространенный шаблон, популяризированный такими фреймворками, как Astro, — островная архитектура , в которой компоненты независимо загружаются поверх статического HTML. API
<template for>позволяет обрабатывать статическое содержимое аналогичным образом непосредственно в HTML. JavaScript-фреймворки также могут использовать это для создания более интерактивных островных архитектур или для обработки компонентов. - Доставка контента по мере его готовности. Благодаря такой изолированной архитектуре контент может передаваться потоком по мере готовности, а не задерживаться для контента, требующего дополнительной обработки — например, для поиска в базе данных. Хотя многие платформы позволяют передавать HTML потоком, последовательная структура HTML означает, что контент часто задерживается или приходится прибегать к сложным манипуляциям с DOM на JavaScript. Теперь вы можете передавать статический контент, пока ждете, а затем добавлять более дорогостоящий и динамический контент в конце потока HTML.
- HTML-код можно размещать в оптимальном порядке для обеспечения высокой скорости загрузки страницы. Более того, порядок можно изменять даже после завершения загрузки. Например, мега-меню — распространенный элемент навигации, содержащий большой объем HTML-кода, который пользователь увидит только после того, как страница станет интерактивной. Этот большой фрагмент HTML-кода можно разместить позже в документе, чтобы отдать приоритет более важному HTML-коду, необходимому для первоначальной загрузки страницы. Порядок больше не является препятствием для HTML-кода.
Это лишь некоторые примеры использования, и нам не терпится увидеть, для чего разработчики будут применять этот новый API.
Ограничения и тонкости
API содержит ряд ограничений и нюансов, о которых следует помнить:
- В целях безопасности
<template for>может обновлять инструкции обработки только внутри того же родительского элемента. Добавление<template for>непосредственно к элементу<body>дает ему доступ ко всему документу (включая<head>). - Инструкция обработки
<?end>является необязательной, и если она отсутствует, содержимое между элементом<?start>и концом содержащего его элемента будет заменено. - Перемещение инструкций обработки после начала потоковой передачи
<template for>также может привести к неожиданным последствиям, поскольку новый контент продолжит передаваться в старое местоположение. - Обратите внимание, что при динамической вставке
<template for>с помощью таких методов, какsetHTMLили свойствоinnerHTML, «родительским» элементом шаблона при его анализе является промежуточный фрагмент документа. Это означает, что вставка HTML с помощью этих методов не может изменять существующий DOM, и патчинг происходит «на месте» внутри фрагмента. Однако при потоковой передаче с использованием таких методов, какstreamHTMLUnsafe(рассмотренных чуть позже), промежуточного фрагмента нет, поэтому шаблоны могут заменять существующее содержимое.
Статус стандартизации
Атрибут <template for> является частью стандарта HTML , но пока поддерживается не всеми браузерами.
Возможные дополнения в будущем
В числе потенциальных дополнений, которые находятся на стадии рассмотрения, можно выделить следующие:
- Включает в себя, например,
<template for="footer" src="/partials/footer.html">или даже без внесения изменений<template src="/partials/footer.html">. Для получения более подробной информации см. пояснение . Это доступно по флагуchrome://flags/#enable-experimental-web-platform-features. - Предотвращение перезаписи контента, который не будет изменяться. Этого можно достичь с помощью номера ревизии контента или версионирования. Это позволит сохранять состояние между изменениями маршрутов или другими обновлениями, вместо сброса контента.
- Очистка данных во время установки патчей. Например,
<template for=icon safe><svg id="from-untrusted-source">...</svg></template>
Полиэфирный наполнитель
Команда Chrome выпустила template-for-polyfill доступный в npm , чтобы сайты могли сразу же использовать эту новую функциональность, еще до того, как она появится в других браузерах.
Есть некоторые ограничения , поскольку он не может напрямую обновлять HTML-парсеры браузеров, но наиболее распространенные сценарии использования охвачены. Тем не менее, сайты следует тестировать в других браузерах.
Обновлены методы вставки и потоковой передачи HTML-кода.
Не весь контент может быть представлен в формате HTML. Вторая часть работы, проделанной Chrome в этой области, направлена на упрощение обновления контента с помощью JavaScript.
Уже существует множество способов динамического внедрения HTML-кода в существующий документ с помощью JavaScript:
-
setHTML -
setHTMLUnsafe -
innerHTMLиouterHTML -
createContextualFragment -
insertAdjacentHTML
Однако все они работают несколько по-разному, с нюансами и различиями, которые разработчики не всегда могут учитывать:
- Новое содержимое перезаписывает или добавляется?
- Они очищают потенциально опасный HTML-код, например, экранируя теги
<script>? - В противном случае, следует ли запустить
<script>? - Как они работают с доверенными типами ?
Немногие разработчики, честно взглянув на эти API, смогли бы с уверенностью ответить на эти вопросы по каждому из них.
Существенным ограничением является то, что их можно использовать только для полного набора HTML-кода, известного заранее, при условии, что были сделаны запросы на потоковую передачу HTML . На практике это означает, что вам нужно загрузить весь контент перед его вставкой, тогда как одним из сильных сторон HTML является возможность мгновенной потоковой передачи контента. Это можно частично обойти, разделив полезную нагрузку или используя устаревшие, неоптимальные методы, такие как document.write , но они создают свои собственные проблемы.
Новый набор статических и потоковых API.
Browser Support
Chrome разработал набор новых API и расширений для существующих функций setHTML и setHTMLUnsafe , которые упрощают этот процесс, а также внедрили функциональность потоковой передачи данных.
Эти функции готовы к тестированию разработчиками начиная с Chrome 148 с использованием chrome://flags/#enable-experimental-web-platform-features и планируются к запуску в Chrome 155.
Существуют методы для установки или замены, а также методы для вставки контента до или после существующего HTML-кода. Для каждого метода есть эквиваленты в потоке:
| Действие | Статический | Стриминг |
|---|---|---|
| Задайте HTML-содержимое элемента | setHTML(html, options); | streamHTML(options); |
| Замените весь элемент этим HTML-кодом. | replaceWithHTML(html, options); | streamReplaceWithHTML(options); |
| Добавьте HTML-код перед элементом. | beforeHTML(html, options); | streamBeforeHTML(options); |
| Добавьте HTML-код в качестве первого дочернего элемента. | prependHTML(html, options); | streamPrependHTML(options); |
| Добавьте HTML-код в качестве последнего дочернего элемента. | appendHTML(html, options); | streamAppendHTML(options); |
| Добавьте HTML-код после элемента. | afterHTML(html, options); | streamAfterHTML(options); |
Существуют также Unsafe версии, которые будут рассмотрены чуть позже. Хотя их может показаться много (особенно если учесть Unsafe аналоги), последовательная система именования делает более очевидным назначение каждой из них по сравнению с несвязанными методами, упомянутыми ранее.
Статические версии принимают новый HTML-код в качестве аргумента DOM-строки, а также необязательные параметры:
const newHTML = "<p>This is a new paragraph</p>";
const contentElement = document.querySelector('#content-to-update');
contentElement.setHTML(newHTML);
Потоковые версии работают с API Streams, например, с помощью метода 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();
Или, в качестве альтернативы, из ответа на запрос с использованием цепочек каналов :
const contentElement = document.querySelector('#content-to-update');
const response = await fetch('/api/content.html');
response.body
.pipeThrough(new TextDecoderStream())
.pipeTo(contentElement.streamHTMLUnsafe());
вспомогательный метод textStream()
Browser Support
Также был добавлен удобный метод textStream , позволяющий осуществлять прямую передачу данных без необходимости использования промежуточного шага TextDecoderStream() :
const contentElement = document.querySelector('#content-to-update');
const response = await fetch('/api/content.html');
response.textStream().pipeTo(contentElement.streamHTMLUnsafe());
options
Аргумент options позволяет указать пользовательский sanitizer , который по умолчанию использует конфигурацию санитайзера по умолчанию default Он используется следующим образом:
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});
«Небезопасные» методы
Существуют также «небезопасные» версии каждого из API:
| Действие | Статический | Стриминг |
|---|---|---|
| Задайте HTML-содержимое элемента | setHTMLUnsafe(html,options); | streamHTMLUnsafe(options); |
| Замените весь элемент этим HTML-кодом. | replaceWithHTMLUnsafe(html, options); | streamReplaceWithHTMLUnsafe(options); |
| Добавьте HTML-код перед элементом. | beforeHTMLUnsafe(html, options); | streamBeforeHTMLUnsafe(options); |
| Добавьте HTML-код в качестве первого дочернего элемента. | prependHTMLUnsafe(html, options); | streamPrependHTMLUnsafe(options); |
| Добавьте HTML-код в качестве последнего дочернего элемента. | appendHTMLUnsafe(html, options); | streamAppendHTMLUnsafe(options); |
| Добавьте HTML-код после элемента. | afterHTMLUnsafe(html, options); | streamAfterHTMLUnsafe(options); |
Эти «небезопасные» методы по умолчанию отключают санитайзер, и при желании вы можете указать собственный санитайзер. Эти методы также позволяют запускать скрипты с необязательной опцией runScripts , которая по умолчанию имеет значение false .
Подобно методу setHTML , метод setHTMLUnsafe уже существует, но в него добавлен параметр параметров runScripts , позволяющий использовать его при выполнении скриптов:
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});
Использование слова «небезопасный» в описании метода призвано напомнить разработчикам о потенциальном риске и о том, как они могут захотеть очистить или ограничить работу скриптов, а не утверждать, что эти методы не следует использовать.
Насколько это «небезопасно», зависит от того, насколько надежны входные данные. Все статические методы Unsafe работают как с DOM String, так и TrustedHTML в качестве аргументов html , а также позволяют использовать санитайзеры. Однако в случае с runScript основная цель — разрешить использование скриптов, поэтому по умолчанию санитайзер не используется.
Варианты использования
Эти новые API упрощают разработчикам добавление HTML-кода на существующие страницы, предоставляя новые API с согласованными именами и параметрами. API для потоковой передачи данных обеспечивают преимущества в производительности, поскольку не нужно ждать, пока весь новый контент станет доступен платформе.
Примеры использования включают:
- Динамическая потоковая передача больших объемов обновлений контента в одностраничных приложениях (SPA). Как уже упоминалось, существенным недостатком текущей архитектуры SPA является то, что она не использует преимущества потоковой передачи при первоначальной загрузке HTML-кода — до настоящего времени!
- Вставка распространенного контента, такого как HTML-футеры. Использование API JavaScript позволяет подтягивать частичные шаблоны и вставлять их на страницу, используя преимущества кэширования, вместо того, чтобы повторять их на каждой загружаемой странице. Однако, учитывая зависимость от JavaScript для работы, этот метод следует использовать только для контента, который не будет виден при первоначальной загрузке.
Повторюсь, это всего лишь пара примеров, и нам не терпится увидеть, что вы придумаете!
Ограничения и тонкости
Эти новые API также содержат ряд ограничений и нюансов, о которых следует помнить:
- Для интеграции потоковой обработки данных с API Trusted Types требуется использовать новый метод
createParserOptions, который позволяет внедрять санитайзер в любую операцию настройки HTML. Более подробную информацию об интеграции Trusted Types см. в пояснительной статье. - Подобно шаблону
<template for>, перемещение элементов, в которые осуществляется потоковая передача, может привести к неожиданным последствиям или ошибкам потоковой передачи. -
streamHTMLUnsafeво многом работает аналогично основному парсеру, включая обработку инструкций<template for>по мере их добавления в основной документ и откладывание выполнения скриптовdeferдо конца потока.
Статус стандартизации
Новые методы вставки и потоковой передачи данных находятся в процессе добавления в стандарт HTML , но пока поддерживаются не во всех браузерах.
Полиэфирный наполнитель
Команда Chrome выпустила html-setters-polyfill , доступный в npm , чтобы сайты могли сразу же использовать эту новую функциональность, еще до того, как она появится в других браузерах.
Обратите внимание, что этот полифил не использует потоковую передачу, а вместо этого буферизует данные и применяет их по завершении. Это скорее полифил для структуры API, чем для функциональности.
Кроме того, настройка безопасного контента зависит от setHTML и API Sanitizer , которые не поддерживаются в Safari.
Используйте их оба вместе.
Хотя это два отдельных API, настоящая мощь заключается в их объединении. Передавая новые элементы <template for> в HTML, вы можете динамически обновлять различные части контента, не прибегая к отдельным ссылкам на DOM в JavaScript для каждой из них.
Простейшую загрузку страницы в стиле SPA можно реализовать, загрузив страницу-шаблон с инструкциями по обработке, а затем передавая шаблоны каждой новой страницы в конец HTML-кода для вставки в эти инструкции по обработке.
Несомненно, у обоих этих API гораздо больше потенциала и вариантов применения, поэтому не позволяйте нашей (ограниченной!) фантазии вас ограничивать. Упростив управление частичными обновлениями, вы можете сократить количество шаблонного кода, упростить обновления и открыть новые возможности для веб-разработки!
В рамках проекта Declarative Partial Updates Chrome работает над ещё несколькими API, но мы с нетерпением ждём возможности предоставить вам первые два. Мы будем держать вас в курсе и сообщим, когда появятся новые возможности в этой области.