TGViewer
SuperOleg dev notes SuperOleg dev notes @super_oleg_dev · 1.75K subscribers
Post #104 1.26K
Почему я вообще поднял тему lazy hydration.

Сейчас исследую возможность оптимизировать тяжелый футер tinkoff.ru не только на клиенте, но и на сервере.

В теории, его можно кэшировать, и не рендерить для каждой страницы заново - а время его рендеринга занимает 20-30% от общего времени рендера большинства страниц, то есть оптимизация напрямую повлияет на максимальные нагрузки, которые могут обрабатывать приложения.

Отдельная история - это персонализация и динамика, которая пролезла в футер, и от которой надо избавиться перед кэшированием, но тут нас больше интересует техническая часть.

Если искать информацию по кэшированию React компонентов, можно найти несколько устаревших форков рендерера `ReactDOMServer`, например https://github.com/rookLab/react-component-caching

Этот подход сложный в реализации и поддержке, и не удивительно что актуальных решений кажется не существует.

Но оказалось что можно сделать очень простой локальный механизм, который отлично ложится на наш `LazyRender` компонент, настолько простой что до сих пор ищу подвох.

Сразу покажу обновленный код:

```
const LazyRender = ({ children, cacheEnabled, cacheKey, serverCache }) => {
const containerRef = useRef(null);
const isVisible = useObserver(containerRef);

if (cacheEnabled && typeof window === 'undefined') {

let html: string;

if (serverCache.has(cacheKey)) {
html = serverCache.get(cacheKey);
} else {
const reactDomServer = require('react-dom/server');

html = reactDomServer.renderToString(children);

serverCache.set(cacheKey, html);
}

return React.createElement('div', {
dangerouslySetInnerHTML: { __html: html },
});
}

if (isVisible) {

return React.createElement('div', {}, children);
}


return React.createElement('div', {
ref: containerRef,

suppressHydrationWarning: true, dangerouslySetInnerHTML: { __html: '' },
});
};

```

Где `cacheKey` - уникальный ключ для кэширования конкретной вариации children компонента, он должен иметь низкую кардинальность для эффективной работы кэша.

А `serverCache` - любой LRU кэш со стандартными методами has / get / set, и настроенным не слишком высоким временем жизни кэша.

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

В `LazyRender`, если кэш включен, мы вручную рендерим children в HTML строку, и дальше сохраняем результат в кэши и используем при рендере других страниц.

Основной минус подхода - React Context приложения будет недоступен в children компоненте. Мы планируем использовать это для микрофронта (а футер как раз такой микрофронт), где это кажется не проблема, и даже хорошая практика.

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

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

Также, добавил серверную метрику - счетчик с лейблами hit / miss и уникальным ключем кэша, для возможности чекать hit rate и в целом эффективность кэширования.

Обязательно поделюсь результатами, как дело дойдет до интеграции и подключения на продакшене!
GitHub GitHub - rookLab/react-component-caching: Speedier server-side rendering with component caching in React 16 Speedier server-side rendering with component caching in React 16 - rookLab/react-component-caching
  • 🔥 17
  • 👍 4
More from @super_oleg_dev
  1. Sep 10, 2026Посмотреть на работу анимаций и скролла можно в нашей демке, основанной на примере Remix ф…
  2. Sep 10, 2026Далее, про скролл. В принципе для SPA-приложений это база, если при переходах на разные ст…
  3. Sep 10, 2026Раз уж меня прорвало, вспомню ещё один интересный кейс. Решали примерно в одно время две п…
  4. Sep 10, 2026Вместо тысячи слов, пример работы и сразу разметка, которая долетает в HTML - и наш механи…
  5. Sep 10, 2026Когда-то давно рассказывал про интеграцию стриминга и deferred загрузки данных в Tramvai -…
  6. Sep 7, 2026TIL, небольшой, но интересный кейс! Делал кастомный анализ бандла через Claude, пишет мне…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →