Данная заметка является своего рода комментарием к другой статье на Хабре Удивительная история document.write, которая, в свою очередь, представляет из себя перевод публикации с сайта https://eager.io/ The Curious Case of document.write. Я же здесь хочу лишь подчеркнуть определённую полезность данного метода клиентского JavaScript (https://developer.mozilla.org/ru/docs/Web/API/Document/write), а также немного порассуждать о подходах и проблемах, связанных с генерацией разметки.
Один из способов формирования разметки на стороне клиента
document.write
— это крайне полезный метод, представляющий, по сути, примитив для организации элементов препроцессинг-а HTML на стороне клиента (веб-браузер). Подготовив генераторы небольших фрагментов HTML в виде набора своих функций JS с понятными наименованиями, можно получить довольно удобно читаемую разметку со вкраплениями вида <script>ИмяФункцииДляФрагмента(…)</script>
. Соответствующие же функции (вместе с глобальными переменными окна) следовало бы поместить в отдельный, заранее подключаемый скрипт-файл или файлы JS. Можно так же для наглядности использовать для именования подобных функций-генераторов префикс W (от слова write).
Аналогичного эффекта можно достичь так же, используя присваивание строки разметки свойству innerHTML
соответствующего элемента. Такой вариант, в отличие от document.write
, позволяет так же модифицировать HTML-фрагмент, то есть сформировать его по-новому уже после загрузки содержимого страницы в DOM (т. е., когда уже отработало событие DOMContentLoaded
документа). Посему метод document.write
я понимаю прежде всего как доступ к препроцессору HTML, т. е. для изначального формирования разметки в браузере (на стороне клиента).
Вот примеры 3-х простых страниц из моей примитивной псевдо-микро-CMS (подобный документации текстовый контент и JPEG-картинки):
https://handicraft.remelias.ru/sdk/sql_file.html (Технология SQL-файл: MSSQL, SQLCMD);
https://handicraft.remelias.ru/sdk/console.html (Технология Консоль: Console App., Desktop, GUI);
https://handicraft.remelias.ru/csweb/magistral_layout.html (Магистральная раскладка: SPA, десктоп/ноутбук/планшет, C#, WASM-Blazor).
Данные страницы основаны на активном использовании document.write
, для которого здесь применяется более короткая по написанию обёртка WT
(акроним для Write Text). (Вы можете видеть разметку до её предварительной обработки, открывая исходный код по Ctrl+U, а так же исследовать файл процедурного кода common.js, содержащий так же и набор JS-функций вида W…
для генерации HTML-фрагментов.)
Недостатки клиентского рендеринг-а (CSR, Client Side Rendering)
Недостатком интенсивного применения подобной организации, однако, является плохая видимость для SEO (Search Engine Optimization), поскольку крáулер-ы (поисковые роботы) навряд ли эффективно “заползают” (от слова crawl) на подобные фрагменты постпроцессинг-а (работающего уже после считывания страницы с веб-сервера). Результат того, что “дорабатывается” в браузере, им, как правило, не доступен, либо не всегда доступен (т. е. с существенными ограничениями по сравнению с вариантом генерации разметки на стороне веб-сервера).
Фантазии насчёт внедрения серверного JavaScript в страницы HTML, отсутствие стандартов
Хотелось бы (естественным образом, от слова стандарт) иметь возможность применения соответствующего серверного тега в HTML (подобного клиентскому <script>
), что-то наподобие <js>W…(…)</js>
для осуществления элементарной серверной доработки разметки с использованием JavaScript, вкупе с директивами #include
, #if
, #else
и т. п. (Кое-где подобное, вроде как, существует.) В предположении же, например, интегрирования с файловой системой, соответствующая виртуальная папка с “преподготовленными” (по 1-му обращению) HTML-файлами для локального открытия (и адресами без расширения “.html” для внешнего открытия по HTTP), могла бы представлять минимальную серверную альтернативу (JS-препроцессор HTML), с поддержкой, к примеру, вызова html.write
(на уровне базового API серверного движка JS).
В реальности же, желающий использовать JS для формирования разметки на стороне веб-сервера оказывается принуждённым к выбору т. н. шаблонизатор-а: Nunjucks, Handlebars, PUG, и т. п. (одного из многочисленного множества реализованных на базе NodeJS). Насколько мне известно, в HTML-5 не существует на сей день стандарта для include ни на клиенте, ни на сервере, как и для внедрения JS-макросов генерации серверного HTML, при обработке запроса HTTP (это вообще не сфера HTML-5). Для применения необходимых простейших манипуляций подобного рода Вы обязаны сначала выбирать один из многочисленных фреймворк-ов/языков/подсистем (в т. ч., как правило, и на клиенте), с вытекающим принятием правил и ограничений.
Существует, кстати, так же, стандарт для определения пользовательских элементов в HTML. В браузере присутствует соответствующий JavaScript-API: вызовы customElements.define(name, constructor, options)
и т. п., теневой (shadow) DOM (всё это приводится в документации MDN). Однако, не похоже, чтобы эти универсальные подходы для определения повторяющихся пользовательских элементов (стандартно определяемые веб-компоненты) успешно и широко применялись. Многие известные элементы, зачастую (хотя и не всегда), приспосабливаются (предлагаются к использованию) под конкретный SPA-фреймворк.
CSR и SEO (размышления об организации пререндеринг-а для поисковиков)
И ещё про SEO и его сочетание с современными SPA (Single Page Application). Для “одностраничного” приложения (“реактивные” страницы, формируемые и модифицируемые, основным образом, в браузере), так же, насколько мне известно, имеются проблемы либо сложности с SEO. Среди поисковых систем, видите ли, только Гугл способен нормально эмулировать (интерпретировать) браузерный JS, при этом неохотно это делает, с затратами (и только для важных страниц). В связи с этим для SPA применяется т. н. пререндеринг (предварительная обработка для CEO), путём установки соответствующего плагин-а на стороне сервера для параллельного SSR (Server Side Rendering).
Однако, на счёт универсального естественного SSR для SPA (и не только для SPA). Не совсем понятно, что мешает цифровым магнатам (ключевые производители ПО) осуществить применение, что называется (так скажем), прямого подхода по оснащению сайта функцией SSR для SEO, путём внедрения эмулятора браузерного JS непосредственно в веб-сайты (веб-серверы), — там, где есть активная клиентская генерация разметки, в теневом режиме (т. е. без графики), специально для обращений от поискового робота, чтобы тот “видел” уже подготовленную примерную псевдо-разметку (как будто она сформирована уже для прорисовки браузером)? Нечастые обращения от крáулер-а не будут столь обременительны (мне думается) для сайта, а поисковые системы тогда “увидят” необходимое содержимое. (Робот же, при этом должен передавать в заголовке HTTP соответствующий признак поискового запроса, а так же, желательно, и наименование поисковой системы.) На любом компьютере ведь установлен браузер, а то и не один. Почему бы не оснастить подобным JS-движком веб-сайты, как функция пререндеринг-а от хостер-а, предлагая держателям доменных ресурсов т. н. псевдоклиентскую подготовку страниц для SEO (с использованием мощностей ЦОД)? Такой хостинг с поддержкой SEO для CSR-страниц (для размещения SPA и не только) смотрелся-бы, на мой взгляд, привлекательно.
Подобное, однако, почему-то не используется (либо организуется совсем иначе, нежели приводится выше), и вместе с SPA-фреймворк-ом принято так же, говорят, “подтаскивать” и соответствующий плагин пререндеринг-а для SSR, что, по-видимому, делает сложное ещё сложнее. Пишут ещё, что существует т. н. динамический пререндеринг, с задействованием мощной сторонней системы на соответствующем домене (https://prerender.io/), посредством внедрения в систему сайта т. н. middleware (промежуточного ПО) для обращения к службе предварительной подготовки страниц. (В общем, пути цифрового прогресса загадочны.)
Заключение
Современное состояние веб-технологий на базе HTML/CSS/JS мне видится (со стороны) немного странным, напоминающим нечто переходное (на этапе трансформации). Нетривиальные вещи, зачастую, могут реализовываться достаточно легко; зато, казалось бы простые, естественные мероприятия широкой надобности — осуществляются весьма-таки запутанно.
(А document.write
— хороший метод.)
Комментарии (10)
zorn_v
12.05.2022 06:27Я вообще не понимаю зачем статья НА ТРИ СКРОЛЛА про то что НЕ НУЖНО ИСПОЛЬЗОВАТЬ (и никто не использует давно) ?
Автор хочет вернуться в прошлое и всем рассказать то что они сейчас уже все давно знают ?
eeeMan
12.05.2022 09:56+3автор вышел из криокамеры в которой был заморожен в нулевых, не душите его, пусть чуть разморозится и придет в себя)
p07a1330
Автор, на дворе 2022ой год
Метод write немного устарел, в вебе сейчас чуть-чуть другие подходы.
В остальном - статья неплохая. Была, лет 15 назад.
zkrvndm
Я сам очень часто используя document.write. Допустим надо тебе на сторонний сайт добавить дополнительный функционал, берешь и при помощи document.write сносишь страницу, после чего заливаешь свой интерфейс, который имеет доступ к API сайта. Очень удобно так делать простеньких ботов, которые автоматизируют рутинные задачи на тех или иных сайтах - все делается с минимумом усилий и все благодаря document.write.
sden77
А чем не подходит, к примеру, document.body.innerHTML ?
zkrvndm
Тем что только document.write именно что сносит страницу, вместе со всеми таймерами и обработчиками. Предложенный вами вариант так не умеет.
Alessandro
Что значит сносит? Он просто вписывает фрагмент хтмл...
zkrvndm
Вписывает, если документ еще не закрыт, если документ закрыт, то перезаписывает имеющийся документ и при такой перезаписи скрипты целевого сайта слетают и не мешают работать уже твоему интерфейсу.
Alessandro
Что значит закрыт?
zkrvndm
document.write('Записываем');
document.write('Дописываем');
document.close(); // Закрываем документ
document.write('Перезаписываем - это снесет все, что было записано раньше.');
Когда страница загружается естественным образом, по готовности документа он закрывается и попытка дописать что-то, не допишет данные в конец, а снесет и перезапишет все, что есть.