LINUX.ORG.RU

Зачем нужно генерировать одинаковый DOM на фронте и бэке?

 ,


0

2

Внимание, вопрос очень неоднозначный, потому не стоит сразу отвечать что придёт в голову. Я уже чёрт знает сколько времени пытаюсь найти на него более-менее чёткий ответ.

Пока что у меня варианты ответов находятся где-то между «не нужно почти никогда», «нужно для ленивых фулстэкеров, которые даже embedded будут писать на JS», и «готовые решения определяют задачи».

В каноничной форме решаемая задача выглядит как некий вебсает, часть которого полностью статична; часть статична, но пользователь взаимодействует с ним сверх возможностей HTML, например, бесконечный скроллинг со статичным отдельным описанием товара; часть вебсайта полностью диинамична, то есть, корзина покупателя или админка или мессенжер.

Большинство имеющихся решений исходит из полной динамики в сторону статики, то есть, изначально сайт представляет собой пустую страницу, на которой всё генерирует JS в браузере, но при неободимости часть генерации мы переносим на сервер и даже делаем её однократной. Особой технической причины делать именно так нет — причина скорее социальная, поскольку фулстэкера на JS найти тупо проще, и далее решение формирует проблемы.

★★★★
Ответ на: комментарий от th3m3

Очевидный вариант, но для полной динамики этого недостаточно. Ну типа я-то может быть и задействовал шаблонизатор+HTMX и SolidJS на фронте для островков, но многие справедливо заметят, что это перебор. Даже взять банальные таблички-графики какие-нибудь — без какого-то промежуточного инструмента много динамических сущностей на голом JS сделать можно, но не нужно.

Справедливости ради, большинству вебсайтов, действительно, полная динамика не нужна и они каргокультят SPA «потому что фейсбук так делает». Но а что делать, если динамика реально нужна? Как прокинуть мостик от полной статики к полной динамике?

byko3y ★★★★
() автор топика

Пишу что пришло в голову. То что сайты генеряся динамически, это особенность работы фреймворков, в которых есть jsx и система компонентов и их переиспользования. Очень просто на js сразу в браузере отрендерить всю страницу целиком, а не заниматься какой-то конвертацией js -> html -> браузер. Но тут у тебя начинаются проблемы на уровне SEO, яндекс с гуглом просто не увидят контента у тебя на сайте, поэтому нужно сгененрировать его на беке. А затем, чтобы все работало пердсказуемо одинаково с динамикой и статикой тебе необходимо поддерживать одинаковый дом на сервер и в браузере.

masa ★★★
()

Есть такие понятия как SSR и SPA. SSR нужен (был) для более быстрого ответа бекенда при первом посещении ресурса пользователем и краулеры раньше многого не умели, да и сейчас не все и не всё умеют. А SPA позволяет не гонять полные страницы на каждый запрос-ответ, что тоже положительно.

С точки зрения разработки было бы неплохо иметь некий общий генератор шаблонов для бекенда и фронта — один раз написал и забыл, но зоопарк бекендов и фронтов не позволяет сделать это по простому, хотя попытки имеются.

Одинаковый DOM на бекенде и фронте — значит единая кодовая база, а не какая-то прихоть.

deep-purple ★★★★★
()
Ответ на: комментарий от byko3y

каргокультят SPA «потому что фейсбук так делает»

Нифейхоа — просто взяли либу на случай, если/когда понадобится динамика. Ну и выше сказано, что меньше данных на каждый чих гонять.

deep-purple ★★★★★
()
Ответ на: комментарий от cobold

И что? Верстальщик засунет текст в нужное место, задача сервера - отдать правильный html (ну и js css), а не рефлексировать на тему успешности текущей вёрстки.

firkax ★★★★★
()
Ответ на: комментарий от masa

То что сайты генеряся динамически, это особенность работы фреймворков, в которых есть jsx и система компонентов и их переиспользования.

Во-первых, наверное стоит начать с того, что JSX в своём первородном варианте позаимствовал много... спорных вещей из JS:

{view === 'telegram' && telegramParamsRef.current !== null ? (
  <>
    <div className={clsx('auth-row', styles.row)}>
      ...
    </div>
    <TelegramLink />
  </>
) : view === 'token' ? (
  <>
    <div className={clsx('auth-row', styles.row)}>
      ...
    </div>
    {formFooterJSX}
  </>
) : (
  <>
    {hasOAuthProviders && (
      <>
        <h5 className={clsx('auth-form-title', styles.title)} />
        <OAuth providers={oauthProviders} onOauthClick={handleOauthClick} />
      </>
    )}
    {hasOAuthProviders && hasFormProviders && (
      <div className={clsx('auth-divider', styles.divider)} title={intl.formatMessage(messages.or)} />
    )}
  </>
)}
Просто что это за язык смайликов? Особенно вот этот индеец:
  </>
) : (
  <>

Потому рассказывать, что JSX каким-то образом ценен сам по себе, наверное, не стоит.

Очень просто на js сразу в браузере отрендерить всю страницу целиком, а не заниматься какой-то конвертацией js -> html -> браузер.

Очень просто, если у тебя статичная страница. Правда, почему бы не отрендерить статичную страницу сразу в HTML — загадка.

Но тут у тебя начинаются проблемы на уровне SEO, яндекс с гуглом просто не увидят контента у тебя на сайте, поэтому нужно сгененрировать его на беке.

Гугл точно увидит, но он штрафует неуклюжую динамику и просто медленные сервера.

byko3y ★★★★
() автор топика
Ответ на: комментарий от th3m3

Интересная идея. Всякие там Remix примерно по тому же пути идут, то есть, перенос всей логики на сервер, как оно первоисконно было. Правда, я не уверен, насколько полная зависимость от сервера является хорошей идеей.

byko3y ★★★★
() автор топика
Ответ на: комментарий от firkax

Зачем тебе вообще DOM на сервере? Это чисто браузерная штука.

Очевидно, DOM на сервере представлен в виде HTML. Но во фреймворках оно часто реально как DOM представлено в промежуточном представлении, и потом уже сериализуется в HTML для передачи по сети.

byko3y ★★★★
() автор топика
Ответ на: комментарий от byko3y

Ну нет, HTML это не DOM.

Но во фреймворках оно часто реально как DOM представлено в промежуточном представлении, и потом уже сериализуется в HTML

Это какие-то дефективные фреймворки, не надо их использовать.

Так вопрос про DOM ил про HTML? Если про первое то ответ выше (низачем), если про HTML то странный вопрос, а как иначе ты предлагаешь динамические элементы делать?

firkax ★★★★★
()
Ответ на: комментарий от byko3y

что это за язык смайликов?

Это DSL, позволяющий тебе при генерации вью видеть вместо зиккуратов из createElement(...) что-то похожее на конечный результат.

С виду не сильно отличается от любого другого шаблонизатора на любом другом языке, добавляющего в разметку куски динамического содержимого.

Непривычно? Привыкнешь %)

Nervous ★★★★★
()
Ответ на: комментарий от deep-purple

С точки зрения разработки было бы неплохо иметь некий общий генератор шаблонов для бекенда и фронта — один раз написал и забыл, но зоопарк бекендов и фронтов не позволяет сделать это по простому, хотя попытки имеются.

Вот с этим утверждением я не согласен. Механизм работы с компонентами (не шаблонами!) в браузере отличается от механизма интерпретации шаблонов на сервере. В браузере ты работаешь с живым DOM, часть свойств которого не представимы в простом HTML, вроде всякой реактивной гадости. На сервере ты генерируешь строго текстовое представление HTML, более ничего.

Одинаковый DOM на бекенде и фронте — значит единая кодовая база, а не какая-то прихоть.

Зачем нужна одинаковая кодовая база для совершенно разных функций и окружений? На сервере ты можешь получить доступ к БД, на браузере — нет. На браузере ты можешь обработать клик, но на сервере никаких кликов нет. Это как бы номинация совы на глобусе, а не «единая кодовая база».

byko3y ★★★★
() автор топика
Ответ на: комментарий от Nervous

createElement

Будто что-то плохое. По сути, этим браузер и занимается, после парсинга полученного HTML. То, что всякие вуи-ангуляры взяли это на себя, при получении JSON от бекенда, говорит лишь о недостатках формата/способа передачи данных к клиенту. С другой стороны невозможно сделать иначе, чем сделано — родовые проблемы.

deep-purple ★★★★★
()
Ответ на: комментарий от firkax

SSR представляет компоненты как DOM, часть представления сериализует в HTML, часть сериализует в свою внутреннюю хрень, всё это скопом передаётся клиенту для последующего восстановления DOM. Так или иначе, объектная модель первична во всём этом цирке. Да и никто уже давно ничего на голом HTML не делает.

byko3y ★★★★
() автор топика
Ответ на: комментарий от byko3y

Зачем нужна одинаковая кодовая база

А зачем описывать одно и то же представление два раза — сначала на сервере, а потом на клиенте, если можно взять общие компоненты и использовать их там и там?

И не только представление — модель предметной области и бизнес-логика тоже могут находиться в единой кодовой базе, и фронту больше не придётся переизобретать их следом за бэком каждый раз заново.

Хотя если ты на почасовой оплате…

Nervous ★★★★★
()
Ответ на: комментарий от byko3y

deep-purple

> С точки зрения разработки было бы неплохо иметь некий общий генератор шаблонов для бекенда и фронта — один раз написал и забыл, но зоопарк бекендов и фронтов не позволяет сделать это по простому, хотя попытки имеются.

Я с точки зрения профана в современном фронтэнде сейчас напишу...

Берём Django, берём Rest API, модели данных... Jinja2 нам отрисует html с пагинацией для поисковиков, Rest API отдаст ВСЁ ТО ЖЕ для любого извращения на фронте. Какие минусы?

Shadow ★★★★★
()
Ответ на: комментарий от byko3y

Механизм работы с компонентами (не шаблонами!) в браузере отличается от механизма интерпретации шаблонов на сервере

Так это проблема недоработки сервера (бекенда). Если он умеет только в текстовое представление DOM.

В браузере ты работаешь с живым DOM, часть свойств которого не представимы в простом HTML

Это ограничения технологии, а не чья-то прихоть «не хочу это делать».

Зачем нужна одинаковая кодовая база для совершенно разных функций и окружений

Чтобы не копипастить и KISS.

На сервере ты можешь получить доступ к БД, на браузере — нет

Посредством асинхронных запросов на бекенд — легко. Не гони.

На браузере ты можешь обработать клик, но на сервере никаких кликов нет

Неужели? Что мешает отправлять ВСЕ клики на бекенд (яндекс счетчики так и поступают, там даже путь движения твоей мышки сохраняют)? Это зависит лишь от твоих хотелок.

Тут мы имеем вынужденый надстройку/адаптер к немного разным, но, тем не менее, «одинаковым» вещам.

deep-purple ★★★★★
()
Ответ на: комментарий от Shadow

Главный минус — твоя Джанга. Она для прототипирования и быстрого старта очень даже хороша. Ну и «спецов» по ней как собак не резаных.

А вот когда у тебя реальных хайлоад, тогда сам же и задумаешься, куда бежать с этой Джанги и вообще как это сделать.

deep-purple ★★★★★
()
Ответ на: комментарий от byko3y

В исходном сообщении никаких «SSR» упомянуто не было. Что это такое и зачем оно ненужно я не знаю, но грузить бэкенд всякими объектными манипуляциями над вёрсткой это однозначно плохая идея - пользы никакой, а дополнительную нагрузку эти бесполезные конвертации туда-сюда создают.

Да и никто уже давно ничего на голом HTML не делает.

Ну это 4.2. Даже если не смотреть не тех, кто пишет прямо html с включениями пхп (они никуда не делись), то уж вариант «есть html-шаблон, заполняем его переменными, полученными из движка и шлём получившееся клиенту» используется прямо-таки повсеместно.

firkax ★★★★★
()
Ответ на: комментарий от deep-purple

Бекэнду незачем обрабатывать html, оно для браузера. Просто некий блоб с пометками «вставить такой-то контент сюда». Контент это например ники и сообщения пользователей, даты сообщений.

firkax ★★★★★
()
Ответ на: комментарий от firkax

Короче я понял, с чего ТС триггерится — он не понимает, почему для интеграции необходимы вот эти вот все адаптеры/прослойки. Ему бы хотелось, чтобы прослоек не было. Но, увы, реальный мир гораздо сложнее и придется мириться с этим, в том числе, писать (да много уже их написано) прослойки для конверсии между протоколами и данными.

deep-purple ★★★★★
()
Ответ на: комментарий от firkax

Бекенду надо что-то выплюнуть в ответ. И если этот ответ ожидается в формате HTML, то придется сформировать корректный HTML, т.е. — обрабатывать это HTML, в каком бы промежуточном формате эти данные на бекенде не обрабатывались — выплюнуть придется HTML, если так было укказано в требованиях.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

И если этот ответ ожидается в формате HTML, то придется сформировать корректный HTML, т.е. — обрабатывать это HTML

В том то и дело, что нет. Бекэнду плевать, что там, он должен только подставить данные в заранее приготовленный блоб. Он даже не знает html там или нет. Какой-то поток символов, видит в нём %uid% - заменяет на id юзера, видит в нём %msg_content% - заменяет на сообщение этого юзера. Например, может быть что-то такое:

<div class="avatar"><img src="/avatars/%uid%.jpg" width=100 height=100></div>
<div class="msg_content">
%msg_content%<br>
<a href="/users/%uid%">%username%</a> %msg_date%<br>
<a href="/reply/%msg_id">reply to</a>
<a href="#msg%msg_id%">link</a>
</div>
Браузер это видит так: создать div такого-то класса, в нём картинку с таким урлом, затём её один div, в нём такой-то текст, ссылки итд. Как это должен видеть бекэнд: потом байт, в нём найдены %uid%, %msg_content%, %username%, %msg_date%, %msg_id% - их надо заменить на соответствующие данные, всё остальное передать без изменений. То, что там какие-то div-ы, картинки, ссылки - бекэнду знать совсем не требуется, вся его роль только переправить это браузеру.

Если бекэнд, вместо того чтобы отдать блоб с текстовыми подстановками, будет каждый раз его генерировать их отдельных dom-нод вручную - ничего, кроме дополнительного жора проца, он от этого не получит. Если что, шаблонизация через имена переменных со знаками % тут для примера, есть и другие шаблонизаторы. Но общее у них одно: весь html, который известен заранее - уже заранее вписан в блоб, собирать его из нод не надо, тупые строковые операции проще.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 3)
Ответ на: комментарий от Nervous

С виду не сильно отличается от любого другого шаблонизатора на любом другом языке, добавляющего в разметку куски динамического содержимого.
Непривычно? Привыкнешь %)

Отличается. Это не вопрос привычки — он реально убогий. Например, что делает эта строка?

{hasOAuthProviders && (
Проверяет булевую переменную hasOAuthProviders? А если она не булева? А если булевым является последующее выражение в скобках? Я-то знаю, что будет, но какого чёрта это вообще должно быть вопросом? Потому что createElement(...) ещё хуже? Так-себе утешение.

Тройной оператор JS был сделан для var b = a ? 1 : 2. Если люди пишут многострочные тройные условия, то зачем они вообще используют линтеры? Пусть каждый пишет со своими отступами, идентификаторы с маленькой и большой буквы по настроению, snake case, camel case — это всё валидный JavaScript же ж. Но если мы начинаем говорить про стиль, то в первую очередь стоит договориться, что хорошим стилем является неиспользование многострочного тройного оператора. Особенно учитывая тот факт, что простых скобочек недостаточно для определения рамок выражения в JSX — нужно писать (<> </>).
Я понимаю, что в JS нет альтернативы тройному оператору, но я напоминаю, что JSX — это не JS. Сравнить с диалектом JSX у ReScript:

      <input
        type_=inputType
        value={if count != 0 {
                   username
               } else {
                   ""
               }}
      />
Или какой-нибудь Vue, который делает вот так:
<div v-if="type === 'A'">
  A
</div>
<div v-else-if="type === 'B'">
  B
</div>
<div v-else>
  Not A/B
</div>

byko3y ★★★★
() автор топика
Ответ на: комментарий от deep-purple

createElement

Будто что-то плохое. По сути, этим браузер и занимается, после парсинга полученного HTML

React.createElement — это не document.createElement, это совершенно разные вещи создающие разные объекты. Иногда React.createElement приводит к вызову document.createElement, но не всегда.

byko3y ★★★★
() автор топика
Ответ на: комментарий от byko3y

что делает эта строка?

{hasOAuthProviders && (

Это выражение «логическое И». Если левая часть (hasOAuthProviders) имеет истинное значение, будет вычислена следующая (в данном случае последняя) часть, иначе результатом выражения будет ложное значение левой части (обычно false/null/undefined/пустая строка), которые React просто пропускает при рендеринге.

Есть небольшая засада — 0 тоже ложное значение в булевом контексте, но его React не пропустит, а отрендерит как есть. Мораль сей басни такова — старайтесь использовать в булевом контексте только булевы значения. Если память подводит — используйте TypeScript, он поможет.

Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 1)

Зачем нужно генерировать одинаковый DOM на фронте и бэке?

Тут весь вопрос: нужен ли тебе динамический фронтенд и нужна ли тебе индексация поисковиком.

Пишешь какое-то сложное веб-приложение: индексация скорее всего нафиг не нужна. Значит сам фронтенд приложения пишется как SPA, сервер только даёт API для данных.

Пишешь классический сайт с текстовым контентом и минимумом скриптов — берёшь готовую CMS типа Wordpress / Drupal / Joomla / … или пишешь сам на основе типичного фреймворка типа Laravel / Django / Rails / Spring / … и тупо верстаешь под него шаблоны.

Пишешь какой-нибудь хитрый сайт с кучей динамического контента, но которому нужна индексация — проще всего написать его на том же фронтендном фреймворке и затем использовать этот же фреймворк в качестве генератора шаблонов на бекенде. Собственно это и есть SSR.

Так что по сути ответ на вопрос: нужно отдавать HTML с бекенда, для чего переиспользуем код фронтенда. Иначе всё равно эти шаблоны кто-то должен будет верстать. Не бекендеры же.

static_lab ★★★★★
()
Ответ на: комментарий от byko3y

простых скобочек недостаточно для определения рамок выражения в JSX — нужно писать (<> </>).

Что поделаешь, в JS (и во многих других популярных языках) выражение вычисляется в какое-то одно значение. Если тебе нужно получить из выражения несколько значений — ты должен обернуть их в какую-то структуру данных, например, массив.

Nervous ★★★★★
()
Ответ на: комментарий от firkax

Он даже не знает html там или нет

Тогда твой бекенд не отвечает конвенциям, которые были определены ДО реализации бекенда.

Он даже не знает html

И это ключевое )) Пусть он отдает JSON. Значит, не по делу отдает — переписывай.

видит в нём %uid% - заменяет на id юзера, видит в нём %msg_content%

Но зачем? В GET/POST/cookies/etc идентифицировал запрос, от кого, сформировал тело ответа (что бы оно из себя не представляло) и ответил.

Конечно, нет смысла отвечать кусками HTML (хотя много, кто так делает), потому и написаны прослойки в виде вуев и ангуляров, чтобы жсоны гонять, даже асинхронно.

Браузер это видит так: создать div такого-то класса

Это хорошо, что ты думаешь так низкоуровнево, но обычному «формошлёпу» можно об этом не думать. Он просто кидает HTML/JSON (как условились) и «на этом наши полномочия — всё».

То, что там какие-то div-ы, картинки, ссылки - бекэнду знать совсем не требуется

Если ты реализуешь прозрачную конверсию между протоколами/форматами — требуется и обязательно. Просто это происходит на «более высоком» уровне.

Если бекэнд, вместо того чтобы отдать блоб с текстовыми подстановками, будет каждый раз его генерировать их отдельных dom-нод вручную - ничего, кроме дополнительного жора проца, он от этого не получит

Если дебил будет зажигать зажигалку каждые 10 секунд, то зажигалка очень быстро кончится.

deep-purple ★★★★★
()
Ответ на: комментарий от Nervous

А зачем описывать одно и то же представление два раза — сначала на сервере, а потом на клиенте, если можно взять общие компоненты и использовать их там и там?

Ещё раз вопрос: что в них общего? Зачем мне обработчик клика кнопки использовать на сервере? Как мне переиспользовать на клиенте соединение к Redis? Или мы тащим JS на сервер только для того, чтобы по одному и тому же шаблону везде сделать рамочки у div-ов?

Если взять ту же Figma, то внезапно выясняется, что на сервере они рендерятся C++, а в браузере они использовали Asm.js/WASM через Emscripten.

Я как бы счастлив увидеть пример «вот же ж, переиспользовали кодовую базу, фронт и бэк работают на одном коде» — не я не вижу таких примеров.

byko3y ★★★★
() автор топика
Ответ на: комментарий от byko3y

Зачем мне обработчик клика кнопки использовать на сервере? Как мне переиспользовать на клиенте соединение к Redis?

Разумеется, всегда будет какое-то количество кода, специфичного для конкретного окружения, который в других окружениях не пригодится. И что? Общая кодовая база, содержащая неспецифичный код, всё ещё может принести немало пользы.

Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 1)
Ответ на: комментарий от byko3y

Я понимаю, что в JS нет альтернативы тройному оператору, но я напоминаю, что JSX — это не JS.

Так ты сейчас критикуешь конкретно React — далеко не самую удачную реализацию фронтендного компонентного фреймворка. Сравнить хотя бы с тем же SolidJS. Там JSX не перемешан ни с циклами .map, ни с условиями в виде && или тернарников.

static_lab ★★★★★
()

Нужно хорошее SEO - лучше чтобы бекенд отдавал статику и минимум рисовалось JS. Это улучшает метрики открытия страницы, которые влияют на поведенческие факторы.

На SEO пофиг и нужно много динамики - JS в помощь.

Norgat ★★★★★
()
Ответ на: комментарий от byko3y

JSX — это не JS. Сравнить с диалектом JSX у ReScript

JSX — это просто тонкий слой сахарка над выражениями нижележащего языка (JS, ReScript, что угодно). В JS if/switch — это не выражение и не возвращает значения, поэтому его нельзя использовать вместо тернарного оператора, не изобретая специально для JSX новый синтаксис языка или новую семантику для старого синтаксиса — но тогда слой сахарка становится гораздо толще.

В ReScript, судя по всему, условные конструкции являются выражениями, вот и всё. JSX тут ни при чём.

Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 3)
Ответ на: комментарий от deep-purple

Чтобы не копипастить и KISS.

Копипастить что? Что я конкретно должен захотеть копипастить?

На сервере ты можешь получить доступ к БД, на браузере — нет

Посредством асинхронных запросов на бекенд — легко. Не гони.

Да, и всё не-дублирование сводится к тому, что у нас веб-бэкенд — это тонкая прокладка, которая транслирует данные с общего сервера бизнес-логики в HTML. То есть, веб-бэкенд и браузер имеют одинаковые права доступа. Потом оказывается, что данных этих нужно очень много и начинается не-дублирование через GraphQL, чтобы сэмулировать как бы прямой доступ к БД, но как бы немножко ограниченный. В общем, адаптируем проблемы к решениям.

Что мешает отправлять ВСЕ клики на бекенд (яндекс счетчики так и поступают, там даже путь движения твоей мышки сохраняют)? Это зависит лишь от твоих хотелок.
Тут мы имеем вынужденый надстройку/адаптер к немного разным, но, тем не менее, «одинаковым» вещам.

На сервере обрабатываются не клики, на сервере обрабатывается сжатое промежуточное представление, в которое эти клики засунуты. И они вообще никак не одинаковы.

byko3y ★★★★
() автор топика
Ответ на: комментарий от deep-purple

Главный минус — твоя Джанга. Она для прототипирования и быстрого старта очень даже хороша. Ну и «спецов» по ней как собак не резаных.
А вот когда у тебя реальных хайлоад, тогда сам же и задумаешься, куда бежать с этой Джанги и вообще как это сделать.

На самом деле в той же Европе спецов по джанге мало. Джанга по большей части стала популярна потому, что на ней можно было сделать очень быстро фуфло-админку для демонстрации инвесторам. Но даже сейчас это уже не работает.

Так-то шаблонизаторы аля Jinja или даже Spitfire могут очень быстро работать на этих ваших питонах.

byko3y ★★★★
() автор топика
Ответ на: комментарий от firkax

Бекэнду плевать, что там, он должен только подставить данные в заранее приготовленный блоб.

Не совсем, все норм темплейтеры для щитимеле делают хотя бы эскейп по умолчанию. И для этого ему нужно знать формат выхлопа (HTML, XML, JSON).

Я согласен с тем, что это всё равно быстрее, чем полноценный DOM, как в SSR. SSR оправдан, если у тебя React.js и нужно ту же страницу показывать и там, и тут. Но это всё разные архитектурные модели систем, веб-сервер тут только одна из переменных, не самая большая.

byko3y ★★★★
() автор топика