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

Теперь же веб-страница может быть полноценным приложением, которое получает данные из различных источников, выполняет манипуляции «на лету» и предоставляет полную интерактивность. Это значительно повысило полезность интернета, но ценой размера, пропускной способности и скорости. За последние 10 лет средний размер веб-страниц для десктопа увеличился с 468 КБ до 2284 КБ, что составляет рост на 388,3%. У мобильных устройств скачок еще более впечатляющий — от 145 КБ до 2010 КБ, то есть больше на 1288,1%.

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

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

Как же нам со всем этим справиться? Ответ — путем возврата на сервер (швейцарский подвал не потребуется).

Краткий экскурс о том, как мы сюда попали

Вначале был PHP, и он был прекрасен — в случае если вам нравились вопросительные знаки.

Интернет начинался как сеть статичного HTML, но CGI скрипты (написанные на Perl или PHP), которые позволяют разработчикам преобразовывать внутренние источники данных в HTML, привнесли идею о том, что веб-сайты могут быть динамическими, основанными на посетителях.

Это означало, что разработчики могли создавать динамические сайты и предоставлять конечному пользователю данные реального времени или данные из БД (при условии, что их ключи #, !, $ и ? работали).

PHP работал на сервере, потому что сервера были мощной частью сети. На сервере можно было получить данные и сгенерировать HTML, а затем отправить всё это браузеру. Задача браузера была ограничена — просто интерпретировать документ и показать страницу. Это хорошо работало, но решение было направлено только на отображение информации, а не на взаимодействие с ней.

Затем JavaScript стал действительно хорош, а браузеры — мощнее. С тех пор можно было делать массу интересных вещей прямо на клиенте. Зачем сначала рисовать всё на сервере и отправлять, если можно просто передать в браузер базовую HTML-страницу вместе с JS и позволить клиенту самому обо всём позаботиться?

Так родились одностраничные приложения (SPA) и рендеринг на стороне клиента (CSR).

Рендеринг на стороне клиента

В CSR (Client-side rendering, рендеринг на клиенте), также известном как динамический рендеринг, код выполняется в основном на стороне клиента, в браузере пользователя. Браузер клиента загружает необходимые HTML, JavaScript и другие ресурсы, а затем запускает код для рендеринга пользовательского интерфейса.

Источник: Walmart

Преимущества такого подхода двояки:

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

  • Кэширование. Поскольку вы не используете сервер, вы можете кэшировать основные пакеты HTML и JS на CDN. Это означает, что пользователи могут быстро получить к ним доступ, и затраты компании останутся низкими.

По мере того, как веб становился все более интерактивным (спасибо JavaScript и браузерам), рендеринг на стороне клиента и SPA стали использоваться по умолчанию. Веб стал очень быстрым... особенно если вы работали на настольном компьютере, используя популярный браузер и проводное подключение к интернету.

Для всех остальных веб замедлялся. По мере своего развития он стал доступен на большем количестве устройств и при различных подключениях. Управлять SPA для стабильного пользовательского опыта стало сложнее. Разработчикам приходилось не только следить за тем, чтобы сайт отображался одинаково как в IE, так и в Chrome, но и учитывать, как он будет отображаться на смартфоне пользователя, который находится в центре оживленного города в автобусе. Если соединение не могло загрузить этот пакет JS из кэша, посетить сайт не удавалось.

Как можно легко обеспечить согласованность в широком диапазоне устройств и пропускной способности? Ответ: вернуться на сервер.

Рендеринг на стороне сервера

Существует множество преимуществ переноса работы браузера по рендерингу веб-сайта на сервер:

  • При использовании сервера выше производительность, поскольку HTML уже сгенерирован и готов к отображению при загрузке страницы.

  • При рендеринге на стороне сервера выше совместимость, поскольку, опять же, HTML генерируется на сервере и не зависит от конечного браузера.

  • Сложность ниже, потому что сервер выполняет большую часть работы по генерации HTML, поэтому часто может быть реализован с более простой и меньшей кодовой базой.

С SSR мы делаем все на сервере:

Источник: Walmart

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

Некоторые из этих фреймворков, такие как NextJS и Remix, построены на React. Коробочный React — это фреймворк для рендеринга на стороне клиента, но у него есть возможности SSR — если использовать renderToString и другие рекомендуемые версии, такие как renderToPipeableStream, renderToReadableStream и прочие. NextJS и Remix предлагают более высокие абстракции над renderToString, что упрощает создание SSR сайтов.

SSR сопровождается некоторыми компромиссами. Мы можем контролировать больше и поставлять быстрее, но ограничение SSR заключается в том, что для интерактивных сайтов все еще нужно отправлять JS, который объединяется со статическим HTML в процессе, называемом «гидратация» (добавить пояснение: Процесс добавления сценария JavaScript обратно в скомпилированный HTML-код страницы во время рендеринга HTML-кода в браузере).

Отправка JS для гидратации приводит к некоторым усложнениям:

  • Отправлять ли весь JS при каждом запросе? Или мы основываемся на пути?

  • Делается ли гидратация сверху вниз, и насколько это дорого?

  • Как разработчику организовать кодовую базу?

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

Один из подходов, который нам нравится в Deno, это архитектура островов — подразумевается, что в море статичного SSR'd HTML есть острова интерактивности. Вероятно, вы слышали, что острова использует современный веб-фреймворк Fresh, который по умолчанию отправляет клиенту ноль JavaScript.

Что вы хотите получить с помощью SSR, так это то, чтобы HTML обслуживался и отображался быстро, а затем каждый из отдельных компонентов обслуживался и отображался независимо. Таким образом, вы посылаете меньшие чанки JavaScript и выполняете меньшие чанки рендеринга на клиенте.

Именно так и работают острова.

Острова рендерятся не постепенно, а отдельно. Рендеринг острова не зависит от рендеринга предыдущего компонента, а обновления других частей виртуального DOM не приводят к повторному рендерингу отдельного острова.

Острова сохраняют преимущества общего SSR, но без ущерба в виде больших блоков для  гидратации. Большой успех.

Как выполнять рендеринг с сервера

Не все серверные рендеринги одинаковы. Есть рендеринг на стороне сервера, а есть рендеринг на стороне сервера с большой буквы.

Здесь мы рассмотрим несколько различных примеров рендеринга с сервера в Deno. Мы перенесем замечательное введение Джонаса Гальвеса в серверный рендеринг на Deno, Oak и Handlebars, используя три варианта одного и того же приложения:

  1. Прямой, шаблонный, серверный HTML-пример без какого-либо взаимодействия с клиентом (источник).

  2. Первоначально отрендеренный на стороне сервера пример, который затем обновляется на стороне клиента (источник).

  3. Полностью серверная версия с изоморфным JS и общей моделью данных (источник).

Посмотреть исходники всех примеров можно здесь.

Именно третья версия является SSR в истинном смысле. У нас будет один JavaScript файл, который будет использоваться как сервером, так и клиентом, а любые обновления списка будут производиться путем обновления модели данных.

Но сначала давайте сделаем несколько шаблонов. В этом первом примере мы будем только рендерить список. Вот основной файл server.ts:

import { Application, Router } from "https://deno.land/x/oak@v11.1.0/mod.ts";
import { Handlebars } from "https://deno.land/x/handlebars@v0.9.0/mod.ts";

const dinos = ["Allosaur", "T-Rex", "Deno"];
const handle = new Handlebars();
const router = new Router();

router.get("/", async (context) => {
  context.response.body = await handle.renderView("index", { dinos: dinos });
});

const app = new Application();

app.use(router.routes());
app.use(router.allowedMethods());

await app.listen({ port: 8000 });

Обратите внимание, что нам не нужен файл client.html. Вместо этого с помощью Handlebars создадим следующую структуру файлов:

|--Views
|    |--Layouts
|    |     |
|    |     |--main.hbs
|    |
|    |--Partials
|    |
|    |--index.hbs

main.hbs содержит основной HTML-макет с заполнителем для {{{body}}}:

<html lang="en">
 <head>
   <meta charset="UTF-8" />
   <meta name="viewport" content="width=device-width, initial-scale=1.0" />
   <title>Dinosaurs</title>
 </head>
 <body>
   <div>
     <!--content-->
     {{{body}}}
   </div>
 </body>
</html>

{{{body}}} происходит из index.hbs. В данном случае он использует синтаксис Handlebars для итерации по списку:

<ul>
 {{#each dinos}}
   <li>{{this}}</li>
 {{/each}}
</ul>

Итак, что происходит:

  • Клиент выполняет запрос.

  • Сервер передает список dinos рендереру Handlebars.

  • Каждый элемент этого списка рендерится в списке в файле index.hbs

  • Весь список из index.hbs отображается в main.hbs

  • Весь этот HTML отправляется в теле ответа клиенту.

Рендеринг на стороне сервера! Ну, типа того. Хотя рендеринг действительно осуществляется на сервере, он не интерактивен.

Давайте добавим в список немного интерактивности — возможность добавить элемент. Это классический случай использования рендеринга на стороне клиента, по сути, SPA. Сервер практически не меняется, за исключением добавления эндпоинта /add, чтобы добавить элемент в список:

import { Application, Router } from "https://deno.land/x/oak@v11.1.0/mod.ts";
import { Handlebars } from "https://deno.land/x/handlebars@v0.9.0/mod.ts";

const dinos = ["Allosaur", "T-Rex", "Deno"];
const handle = new Handlebars();
const router = new Router();

router.get("/", async (context) => {
  context.response.body = await handle.renderView("index", { dinos: dinos });
});

router.post("/add", async (context) => {
  const { value } = await context.request.body({ type: "json" });
  const { item } = await value;
  dinos.push(item);
  context.response.status = 200;
});

const app = new Application();

app.use(router.routes());
app.use(router.allowedMethods());

await app.listen({ port: 8000 });

На этот раз код Handlebars существенно изменился. У нас по-прежнему есть шаблон Handlebars для генерации HTML-списка, но main.hbs  включает свой собственный JavaScript для работы с кнопкой Add: событие EventListener, привязанное к кнопке, которое будет:

  • выполнять POST с новым элементом списка в эндоинт /add ,

  • добавлять элемент в список HTML.

[...]
  <input />
  <button>Add</button>
 </body>
</html>

<script>
 document.querySelector("button").addEventListener("click", async () => {
   const item = document.querySelector("input").value;
   const response = await fetch("/add", {
     method: "POST",
     headers: {
       "Content-Type": "application/json",
     },
     body: JSON.stringify({ item }),
   });
   const status = await response.status;
   if (status === 200) {
     const li = document.createElement("li");
     li.innerText = item;
     document.querySelector("ul").appendChild(li);
     document.querySelector("input").value = "";
   }
 });
</script>

Но это не рендеринг на стороне сервера в истинном смысле. В SSR вы запускаете один и тот же изоморфный JS на стороне клиента и сервера, и он просто действует по-разному в зависимости от того, где он запущен. В приведенных выше примерах JS запущен на сервере и клиенте, но они работают независимо друг от друга.

Итак, перейдем к настоящему SSR. Мы откажемся от Handlebars и шаблонизаторов и вместо этого создадим DOM, который мы будем обновлять с помощью Dinosaurs. У нас будет три файла. Первый — server.ts:

import { Application } from "https://deno.land/x/oak@v11.1.0/mod.ts";
import { Router } from "https://deno.land/x/oak@v11.1.0/mod.ts";
import { DOMParser } from "https://deno.land/x/deno_dom@v0.1.36-alpha/deno-dom-wasm.ts";
import { render } from "./client.js";

const html = await Deno.readTextFile("./client.html");
const dinos = ["Allosaur", "T-Rex", "Deno"];
const router = new Router();

router.get("/client.js", async (context) => {
  await context.send({
    root: Deno.cwd(),
    index: "client.js",
  });
});

router.get("/", (context) => {
  const document = new DOMParser().parseFromString(
    "<!DOCTYPE html>",
    "text/html",
  );
  render(document, { dinos });
  context.response.type = "text/html";
  context.response.body = `${document.body.innerHTML}${html}`;
});

router.get("/data", (context) => {
  context.response.body = dinos;
});

router.post("/add", async (context) => {
  const { value } = await context.request.body({ type: "json" });
  const { item } = await value;
  dinos.push(item);
  context.response.status = 200;
});

const app = new Application();

app.use(router.routes());
app.use(router.allowedMethods());

await app.listen({ port: 8000 });

На этот раз многое изменилось. Во-первых, у нас снова есть несколько новых эндпоинтов:

  • эндпоинт GET, который будет обслуживать файл client.js,

  • эндпоинт GET, который будет обслуживать данные.

Но существенное изменение также произошло в корневом эндпоинте. Теперь мы создаем объект документа DOM с помощью DOMParser из deno_dom. Модуль DOMParser работает подобно ReactDOM, позволяя воссоздать DOM на сервере. Затем мы используем созданный документ для рендеринга списка заметок, но вместо того, чтобы использовать шаблонизацию handlebars, мы получаем эту функцию рендеринга из нового файла.

let isFirstRender = true;

// Simple HTML sanitization to prevent XSS vulnerabilities.
function sanitizeHtml(text) {
  return text
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#039;");
}

export async function render(document, dinos) {
  if (isFirstRender) {
    const jsonResponse = await fetch("http://localhost:8000/data");
    if (jsonResponse.ok) {
      const jsonData = await jsonResponse.json();
      const dinos = jsonData;
      let html = "<html><ul>";
      for (const item of dinos) {
        html += `<li>${sanitizeHtml(item)}</li>`;
      }
      html += "</ul><input>";
      html += "<button>Add</button></html>";
      document.body.innerHTML = html;
      isFirstRender = false;
    } else {
      document.body.innerHTML = "<html><p>Something went wrong.</p></html>";
    }
  } else {
    let html = "<ul>";
    for (const item of dinos) {
      html += `<li>${sanitizeHtml(item)}</li>`;
    }
    html += "</ul>";
    document.querySelector("ul").outerHTML = html;
  }
}

export function addEventListeners() {
  document.querySelector("button").addEventListener("click", async () => {
    const item = document.querySelector("input").value;
    const dinos = Array.from(
      document.querySelectorAll("li"),
      (e) => e.innerText,
    );
    dinos.push(item);
    const response = await fetch("/add", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ item }),
    });
    if (response.ok) {
      render(document, dinos);
    } else {
      // In a real app, you'd want better error handling.
      console.error("Something went wrong.");
    }
  });
}

Этот файл client.js доступен как серверу, так и клиенту — это изоморфный JavaScript, необходимый для истинного SSR. Мы используем функцию render на сервере для первоначального рендеринга HTML, но затем мы также используем render на клиенте для рендеринга обновлений.

Кроме того, при каждом вызове данные берутся напрямую с сервера. Данные добавляются в модель данных с помощью эндпоинта /add . По сравнению со вторым примером, где клиент добавляет элемент в список непосредственно в HTML, в этом примере все данные передаются через сервер.

JS из client.js также используется непосредственно на клиенте, в client.html:

<script type="module">
  import { render, addEventListeners } from "./client.js";
  await render(document);
  addEventListeners();
</script>

Когда клиент вызывает client.js в первый раз, HTML становится гидратированным, где client.js вызывает эндпоинт /data, чтобы получить данные, необходимые для будущих рендеров. Гидратация может стать медленной и сложной для больших страниц SSR; и здесь острова могут быть действительно полезными.

Вот как работает SSR. Дано:

  • DOM, воссозданный на сервере.

  • Изоморфный JS, доступный как на сервере, так и на клиенте для рендеринга данных на любом из них, и гидратация, установленная при начальной загрузке на клиенте для захвата всех данных, необходимых для того, чтобы сделать приложение полностью интерактивным для пользователя.

Упрощение сложного веба с помощью SSR

Мы создаем сложные приложения для любого размера экрана и любой пропускной способности. Этими сайтами можно пользоваться, находясь в поезде в тоннеле. Лучший способ обеспечить согласованность работы во всех этих сценариях, сохраняя при этом небольшую базу кода и легкость в рассуждениях — это SSR.

Высокопроизводительные фреймворки, которые заботятся о пользовательском опыте, будут отправлять клиенту только необходимое и ничего больше. Чтобы минимизировать задержки еще больше, разверните SSR приложения рядом с пользователями. Все это можно сделать уже сегодня с помощью Fresh и Deno Deploy.

Застряли? Приходите за ответами в наш Discord.


Как создать сайт в блокноте html за час? Получите пошаговую инструкцию на открытом уроке в OTUS. 21 марта на бесплатном вебинаре сверстаем одностраничный сайт о компании или персоне, который вы сможете использовать далее. Разберём современные подходы к созданию HTML-страниц, их оформлению и расположению элементов на экране. Урок подойдет тем, кто только начинает знакомиться с миром веб-разработки. Записаться можно на странице специализации "Fullstack Developer".

Комментарии (21)


  1. gmtd
    00.00.0000 00:00
    +7

    При использовании сервера выше производительность, поскольку HTML уже сгенерирован и готов к отображению при загрузке страницы.

    Производительность ниже, так как каждому клиенту надо отрисовку делать на сервере. Нагрузка на сервер. Нет адаптивности и отзывчивости, которую может дать javascript.

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

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

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

    Сложность невообразимо выше. По сути пишешь сайт два раза двумя способами. Первым - нормальным (клиент-сервер, фронт-апи бэк), и вторым через одно место

    Так и не дан ответ - зачем он нужен, этот ваш SSR. Ради чего все эти мучения?


    1. Sap_ru
      00.00.0000 00:00
      +9

      Утверждения о том, что SSR что-то там упрощает являются однозначным и 100% признаком развешиваемой по ушам лапши. Каждый, кто хотя бы издалека это щупал, знает, что SSR намного медленнее, сложнее и дороже в разработке и обслуживании чем классические динамические страницы. И р этом ещё и менее гибкий, так как сложнее сделать что-то брузеро- или плафтормо-зависимое уж, если захочется. И всякие чудеса вроде адаптивной верстки в зависимости от конкретной платформы, если вашу вдруг возможностей CSS не хватает или хочется чего-то совсем необычного, сложнее сделать. Есть кто-то говорит иначе - смейтесь над ним и гоните прочь.

      У SSR был ровно один плюс, ради которого он был создан - он хорошо индексируется. Всё остальное было минусами и компромиссами. Именно ради этой фичи бизнес во главе с SEO пошёл на дополнительные затраты на разработку и серверные мощности. Никаких иных плюсов там нет и быть не может, только минусы, которые в некоторых случаях уравновешиваются одним единственным вышеупомянутым плюсом.

      Но с тех пор поисковики научились в динамические страницы, а программисты научились уменьшать время до первого рендеринга DOM. Правилом хорошего тона уже считается выдать предварительную вёрстку сразу после события окончания загрузки DOM, поисковики умеют пропускать ненужные этапы загрузки страницы, а разработчики умеют делать страницы, которые грузятся без шрифтов, лишних стилей, таймеров и прочих излишеств и умеют подгружать необязательный функционал в фоне. В результате SSR в его современном виде оказался ненужен чуть более чем полностью. А в тех редких случаях, когда он действительно нужен, на самом деле нужен не модный SSR, а старые добрые серверные шаблоны.

      Но процесс оказался запущен. Выросло поколение специалистов по SSR, которые творят его везде и рассказывают от непомерной крутости. Но на вопрос "зачем?" они ответь не могут, так как они освоили SSR позже момента, когда поисковики освоили индексирование динамики, и не видели запроса от SEO на индексируемые динамические сайты, и потому не принимают, что это уже лютое легаси и вынужденный временный костыль.

      Я с ужасом жду, когда они повторно изобретут карты сайтов и специализированные шаблоны для поисковиков, которыми обходились до "изобретения" SSR. И будут писать умные книжки, бегать по интернетам и рассказывать, что SSR это очень сложно и дорого и, оказывается, можно обойтись без него. Причём, произойти это должно очень скоро, так как бизнес не дурак и быстро понимает, что SSR это дорого, а плюсов уже практически никаких не приносит.


      1. gmtd
        00.00.0000 00:00
        +3

        На самом деле для любителей СЕО есть очень простой вариант - сделать статический дубль сайта на сервере специально для поисковиков. Простые сгенерированные кэшируемые страницы только для ботов и спайдеров. Прекрасно работает и требует минимального времени на разработку.


        1. MountainGoat
          00.00.0000 00:00
          +3

          Поисковики за такое банить должны. Потому что следующим шагом непременно будет разное содержимое у этих страниц и у пользовательских.


          1. Sap_ru
            00.00.0000 00:00
            +1

            Тем не менее именно так индексировался интернет почти 10 лет и до сих именно так индексируется на некоторых тяжёлых сайтах.

            А содержимое и так немного разное получается, так как поисковики для индексации используют модифицированные браузерные движки, которые достаточно сильно отличаются от обычных. Ну, и вообще, поисковики честно сползают о своих ботах, в том числе и через API браузера.

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


      1. paamayim
        00.00.0000 00:00
        +1

        А так ли нужен SEO сейчас? Есть миллион других способов раскрутки сайтов, приложений


  1. Sap_ru
    00.00.0000 00:00
    +4

    Статья - полная неправда, и противоречит сама себе. SSR сложнее, дороже и не быстрее чем динамические страницы. Зачем и какие реальные плюсы?

    Без SSR нельзя сделать маленькую страницу, которая сразу отображать минимальную верстку, а все свистелки и функционал подгружать позже? Можно, и это сильно проще чем городить и поддерживать SSR.

    Без SSR нельзя сделать быструю страницу? Очевидно, что можно, и это снова будет проще и дешевле чем SSR.

    SSR - гибче и отзывчевей? Муа-ха-ха! Сделайте на нем вёрстку, где DOM (именно DOM, а не стили) зависит от размера/пропорций экрана пользователя и/или наличия тачскрина, и посмотритм, где среди получившихся костылей будут гибкость с отзывчивостью.

    Так какую именно задачу решает SSR, чтобы идти на усложнение приложения и инфраструктуры?


    1. pingo
      00.00.0000 00:00

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

      а ssr современный да, та еще, медленная, геморная, закастыленная хрень


  1. LeshiyUrban
    00.00.0000 00:00
    +3

    Клиентов много, каждый клиент представляет собой независимое вычислительное устройство. Гораздо дешевле поставить дешёвый сервер и переложить весь рендер на клиента тем самым массово и бесплатно распараллеливая обработку.

    Во-вторых, при использовании SPA вы практически автоматом получаете и UI и API. Если точное - UI становится просто обёрткой над стандартным API. Не нужно дублировать работу и клиентам максимально удобно интегрироваться.

    Последнее - backend становится полностью независимым от UI, может разрабатываться разными командами и на разных языках (в отличие от SSR с гидрацией, который обычно требует одной платформы - node, позволяя делать универсальный код и для сервера и для клиента).

    Более того, хорошо написанный фронт будет работать быстро и потреблять мало место (chunk, lazy load, etc...). И полировать и релизить его можно не меняя сервер


    1. Kahelman
      00.00.0000 00:00

      Вам же user-case описали. Если у вас оптика от компа, то да, все работает. Что делать если у вас канал слабый. Решили из самолета на сайт зайти - удачи вам с lazy load и т.д.


      1. Zenitchik
        00.00.0000 00:00

        Так наоборот же всё. Чем больше делает клиент, тем меньше объём обмена с сервером.


  1. kpmy
    00.00.0000 00:00
    +3

    У автора с самого начала во главу угла поставлена "веб-страница", а не "веб-приложение". Конечно, как и 20 лет назад, самый логичный путь развития от статической страницы это шаблон статической страницы, слегка модифицируемый на сервере.


  1. BigDflz
    00.00.0000 00:00
    +3

    рендеринг и прочая херня типа гидротации - это переливаниие из пустого в порожнее. зачем стрjить что-то (типа json), это ведь в чистом виде строка. а потом из строки строить новую строку под названием HTML? ведь можно сразу построить HTML-строку и отдать её клиенту. к примеру серверу на java - "примитивные" jsp-страницы, всё находится в памяти, обращения к диску в основном это обращение к базе (если есть необходимость) так можно сразу строить вычисляемые элементы dom (таблицы, как вариант). исключается куча лишних действий.
    если разработчику не хватает мозгов по построению строки HTML, то это проблема руководства этого разработчика, нанявшего такого "знатока".
    ssr "медленный", конечно, если рассматривать его как преобразование из одной строки в другую. надо построить одну строку, потом её распарсить, преобразовать и построить уже отдаваемую в виде html.....
    "каждому клиенту надо отрисовку делать на сервере. Нагрузка на сервер.".... ага , а построить для каждого клиента json не нужно?
    у меня веб-приложения, страницы которых полностью строятся на сервере без рендеринга, и данные выводимые по запросам с этих страниц (таблицы и прочее) также строятся на сервере в виде html, и работает быстро. и на сервер нет нагрузки.
    "жухаться" не будет. проверено многократно, что построить json, что построить html для него однорангово


    1. Sap_ru
      00.00.0000 00:00

      Только к этой "строке", "которая HTML", всё равно нужно прикручивать кучу динамики: таблицы с подгрузкой данных, всплывающие окна, вёрстку, зависящую от устройства пользователя и прочее. Сделать адаптированный под весь спектр устройств сайт без динамики только это бэкэнде это даже не смешно. А как только вы прикручиваете динамику к сайту, то оказывается проще полностью отделить фронт об бэка и перенести форматирование и отображение данных полностью на фронт.


    1. ibnteo
      00.00.0000 00:00

      В htmx.org того же мнения, ещё и меньше кода получается в сумме.


  1. Travisw
    00.00.0000 00:00
    -1

    сервер ваш от нагрузки будет жухаться часто


  1. Gariks
    00.00.0000 00:00

    Немного не понятен выбор технологий в статье. Есть же SSR frameworks типа next.js например... В практике я пробовал SSR и делали мы это исключительно для SEO, пришлось повозиться и это не так просто, как кажется. В коде появилось куча if-ов, что исполнять на стороне сервера, а что исполнять на стороне клиента, возможно дело было в нашей структуре проекта. В общем, если хочется SSR, лучше подумать 100 раз и сделать статикой, через тот же gatsby, а если нужен backend for frontend (BFF), то SSR это не про это.


  1. noodles
    00.00.0000 00:00
    +1

    архитектура островов — подразумевается, что в море статичного SSR'd HTML есть острова интерактивности. 

    Виджеты что-ли?)

    помню делали нормальные сайты на симфони с серверными twig-шаблонами, и там где по дизайну было много интерактива - выделял div и рисовал в него реактом на клиенте. При чём за счёт порталов можно делать несколько разных таких div-обёрток, и они могли общаться между собой и знать состояние друг-друга.
    Оказывается это "архитектура островов"..)))


  1. headliner1985
    00.00.0000 00:00

    В статье всё верно описано, одна страница будет работать и грузиться быстрее при сингл пэйдж рендеринге. При использовании фреймворков и теплейт энджинов разработка UI происходит в разы быстрее, где не надо делать каждый компонент с нуля и к нему ещё и рест делать. Что опять же тупо по деньгам на разработку окупается, где лишние пару UI девов будут кушать денег как 20 мощных серверов на года, куда можно запихнуть рендер сервера. В общем если вы не фэйсбук нахрен это не окупается. А потом ещё весь этот зоопарк рест микросервисов поддерживать на бэке, и ещё отдельно поддерживать версии UI, вместо распределенного монолита в кластере как пример.


  1. Hheimerd
    00.00.0000 00:00

    Про вес странный аргумент довольно странный, учитывая вес любой картинки на сайте. На некоторых сайтах favicon больше весит, чем сам сайт (js бандл)


  1. MrRewolwer
    00.00.0000 00:00
    +2

    Зуммеры открыли PHP. О том что SSR нужен был только для поисковиков, потому что они не могли в JS - зуммеры уже даже не в курсе.

    Next и Nest - это костыли, которые нужны были для SEO. Они, буквально, создавались, чтобы умереть. Как и создатели Бабеля предполагали что скоро все браузеры будут вечнозелёными и подтфилы устареют.

    Знаете, что я вижу в этом посте? Самый настоящий карго-культ. Технологии стали инструментом сегрегации. Будто техно-жрецы из Вархаммер, такие люди развивают и повторяют обряды, вообще не понимая их цели.