Оптимизация SSR

FAST Element — это современный фреймворк для создания веб-компонентов на основе стандартов Web Components. Одной из ключевых особенностей является поддержка Server-Side Rendering (SSR), которая позволяет рендерить компоненты на сервере и отправлять уже готовый HTML клиенту. SSR повышает производительность загрузки страниц, улучшает SEO и снижает время до первого рендеринга.

FAST Element использует механизм template-driven rendering. В SSR шаблон компонента компилируется в функцию, которая возвращает строку HTML. При этом сохраняется реактивность: после монтирования на клиенте компонент продолжает отслеживать изменения состояния и обновлять DOM.

import { html, FASTElement } from "@microsoft/fast-element";

class MyComponent extends FASTElement {
  message = "Привет, SSR!";
}

MyComponent.template = html<MyComponent>`
  <div>${x => x.message}</div>
`;

На сервере этот шаблон можно рендерить с помощью функции renderToString, которая возвращает HTML:

import { renderToString } from "@microsoft/fast-element/server";

const htmlString = renderToString(MyComponent);

Оптимизация рендеринга

1. Минимизация шаблонов и вычислений Каждое выражение внутри шаблона выполняется при рендеринге. Для SSR важно вынести сложные вычисления из шаблона в отдельные функции или заранее вычисленные значения:

class ListComponent extends FASTElement {
  items = [];
  get renderedItems() {
    return this.items.map(item => `<li>${item}</li>`).join("");
  }
}

ListComponent.template = html<ListComponent>`
  <ul>${x => x.renderedItems}</ul>
`;

Такой подход снижает нагрузку на сервер и ускоряет формирование HTML.

2. Использование статических частей шаблона Все неизменяемые части DOM должны быть вынесены в статические шаблоны. FAST Element автоматически кэширует эти куски, что сокращает повторные вычисления.

const staticTemplate = html`
  <header>Заголовок страницы</header>
`;

class PageComponent extends FASTElement {}

PageComponent.template = html<PageComponent>`
  ${staticTemplate}
  <main>${x => x.content}</main>
`;

3. Lazy-rendering и отложенная инициализация Для больших компонентов с множеством вложенных элементов можно применять ленивый рендеринг. На сервере рендерятся только критические части страницы, а остальное монтируется на клиенте:

import { html, FASTElement } from "@microsoft/fast-element";

class HeavyComponent extends FASTElement {
  loaded = false;
}

HeavyComponent.template = html<HeavyComponent>`
  ${x => x.loaded ? html`<div>Тяжелый контент</div>` : html``}
`;

Управление состоянием для SSR

При SSR важно передавать состояние компонента с сервера на клиент. FAST Element позволяет сериализовать данные и внедрять их прямо в HTML:

const state = { items: ["a", "b", "c"] };
const htmlString = renderToString(MyComponent, { state });

<!-- В HTML можно встроить JSON -->
<script id="initial-state" type="application/json">
  ${JSON.stringify(state)}
</script>

На клиенте компонент может считывать этот JSON и инициализироваться без лишнего запроса к API.

Асинхронные данные

Частая задача при SSR — работа с асинхронными источниками данных. В FAST Element это реализуется через промисы и async функции перед рендерингом:

async function fetchData() {
  return await fetch("https://api.example.com/data").then(res => res.json());
}

const data = await fetchData();
const htmlString = renderToString(MyComponent, { data });

Для больших страниц стоит использовать параллельное получение данных и объединять промисы с Promise.all для сокращения времени генерации HTML.

Кэширование HTML

Чтобы ускорить SSR, часто применяют кэширование готового HTML. FAST Element позволяет использовать готовые строки HTML для повторного рендеринга одинаковых страниц:

const cache = new Map();

function renderPage(props) {
  const key = JSON.stringify(props);
  if (cache.has(key)) return cache.get(key);

  const htmlString = renderToString(MyComponent, props);
  cache.set(key, htmlString);
  return htmlString;
}

Кэширование особенно эффективно для страниц с небольшим количеством динамических элементов или при CDN-распределении.

Оптимизация повторного рендеринга на клиенте

После SSR компонент монтируется на клиенте. Для минимизации “гигантских патчей” DOM стоит использовать:

  • Incremental hydration — монтировать только измененные элементы.
  • Предварительное вычисление значений — все сложные вычисления лучше делать на сервере, чтобы клиент получал уже готовый DOM.
  • Минимизация наблюдаемых свойств — лишние реактивные свойства замедляют обновления.
class OptimizedComponent extends FASTElement {
  message = "Hello SSR";

  // избегаем ненужной реактивности
  nonReactiveValue = computeHeavyValue();
}

Взаимодействие с роутером

При SSR страницы обычно рендерятся на основе URL. FAST Element не включает роутер по умолчанию, поэтому интеграция с серверным роутером (например, Express или Fastify) осуществляется через промежуточный слой:

app.get("/page/:id", async (req, res) => {
  const data = await getData(req.params.id);
  const html = renderToString(MyComponent, { data });
  res.send(html);
});

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


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