SUPER_OLEG_DEV Telegram 104
Почему я вообще поднял тему 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 и в целом эффективность кэширования.

Обязательно поделюсь результатами, как дело дойдет до интеграции и подключения на продакшене!
🔥17👍4



tgoop.com/super_oleg_dev/104
Create:
Last Update:

Почему я вообще поднял тему 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 и в целом эффективность кэширования.

Обязательно поделюсь результатами, как дело дойдет до интеграции и подключения на продакшене!

BY SuperOleg dev notes


Share with your friend now:
tgoop.com/super_oleg_dev/104

View MORE
Open in Telegram


Telegram News

Date: |

The group’s featured image is of a Pepe frog yelling, often referred to as the “REEEEEEE” meme. Pepe the Frog was created back in 2005 by Matt Furie and has since become an internet symbol for meme culture and “degen” culture. In handing down the sentence yesterday, deputy judge Peter Hui Shiu-keung of the district court said that even if Ng did not post the messages, he cannot shirk responsibility as the owner and administrator of such a big group for allowing these messages that incite illegal behaviors to exist. Each account can create up to 10 public channels The channel also called on people to turn out for illegal assemblies and listed the things that participants should bring along with them, showing prior planning was in the works for riots. The messages also incited people to hurl toxic gas bombs at police and MTR stations, he added. ZDNET RECOMMENDS
from us


Telegram SuperOleg dev notes
FROM American