Эти методы управляют потоковой записью HTML прямо в документ. Они удобны во время парсинга страницы, но опасны после загрузки: могут стереть текущее содержимое, блокируют поток, ухудшают производительность и плохо сочетаются с современными практиками. Ниже — безопасные сценарии, риски и актуальные альтернативы.
Функция находится в статусе ограниченной доступности в Baseline.
Как работает потоковая запись в документ
Во время первоначального парсинга HTML вызов document.write()
вставляет текст в текущую позицию парсера. Это синхронная операция: браузер останавливает парсинг, выполняет JavaScript и вставляет фрагмент HTML прямо в поток.
<!doctype html>
<html>
<head><meta charset="utf-8"><title>Потоковая запись</title></head>
<body>
<script>
// Во время парсинга: добавит заголовок в текущую позицию
document.write('<h2>Добавлено во время парсинга</h2>');
</script>
<p>Остальной контент документа.</p>
</body>
</html>
Чем опасен вызов после загрузки
Если вызвать document.write()
после завершения загрузки (document.readyState ≠ "loading"), браузер обычно выполнит неявный document.open()
, очистит текущую страницу и начнёт новый документ. Это частая причина «пропажи» DOM после поздних скриптов.
window.addEventListener('load', () => {
// Плохая идея: страница будет очищена и заменена новым документом
document.write('<p>Старый контент потерян</p>');
document.close();
});
Контролируемая запись в новый документ
Иногда нужно целенаправленно создать новый документ — например, для печати или вывода отчёта в отдельное окно. В таком случае открываем окно, заполняем его HTML и закрываем поток.
const w = window.open('', '_blank', 'noopener');
if (w) {
const html = `<!doctype html>
<html><head><meta charset="utf-8"><title>Report</title></head>
<body><h1>Report</h1><p>Generated at: ${new Date().toISOString()}</p></body></html>`;
w.document.open('text/html', 'replace'); // Явно начинаем новый документ
w.document.write(html);
w.document.close();
}
Запись в <iframe> без риска стереть основную страницу
Для изолированного вывода можно писать в документ встроенного фрейма: это не затронет основной DOM.
const frame = document.createElement('iframe');
frame.setAttribute('title', 'Preview');
frame.style.width = '100%';
frame.style.height = '200px';
document.body.appendChild(frame);
const doc = frame.contentDocument;
doc.open();
doc.write('<!doctype html><meta charset="utf-8"><h2>Превью во фрейме</h2><p>Содержимое из JS</p>');
doc.close();
Чем отличается document.writeln()
document.writeln()
делает то же, что и document.write()
, но добавляет символ перевода строки в конце переданной строки. Это влияет лишь на читаемость исходного HTML, визуально на странице разницы обычно не будет.
document.writeln('<div>A</div>'); // выведет с переводом строки
document.write('<div>B</div>'); // без перевода строки
Проверка безопасного момента для write
Если по историческим причинам вам всё же нужно использовать потоковую запись, убедитесь, что документ ещё парсится, иначе вы рискуете стереть страницу.
if (document.readyState === 'loading') {
document.write('<p>Безопасно во время парсинга</p>');
} else {
// Используйте современные альтернативы, описанные ниже
}
Современные альтернативы (рекомендуется)
В большинстве случаев потоковая запись не нужна. Вот безопасные варианты, которые не стирают DOM и не блокируют рендер:
- Шаблонные элементы и вставка HTML:
const tpl = document.createElement('template'); tpl.innerHTML = '<section class="card"><h2>Title</h2><p>Text</p></section>'; document.body.appendChild(tpl.content.cloneNode(true));
- Точечная вставка:
const container = document.querySelector('#root'); container.insertAdjacentHTML('beforeend', '<li>Item</li>');
- Создание узлов:
const el = document.createElement('div'); el.className = 'notice'; el.textContent = 'Hello!'; document.body.appendChild(el);
- Стриминг с серверной стороны (SSR, HTML streaming) — отдавайте HTML порциями с сервера без
document.write()
.
Производительность и безопасность
Потоковая запись блокирует парсинг и может задерживать загрузку критичных ресурсов. Также она плохо сочетается с CSP, модульными бандлами и ленивой загрузкой. Для аналитики и сторонних виджетов используйте асинхронные скрипты (async
/ defer
) и DOM‑вставки вместо document.write()
.
Итоги
document.open()
/ document.write()
/ document.writeln()
/ document.close()
исторически полезны во время парсинга или для вывода в новый документ/фрейм. В современной разработке предпочтительнее манипуляции DOM‑узлами, шаблоны, insertAdjacentHTML
и SSR. Так вы избежите стирания страницы, блокировок и проблем с безопасностью.