Випадок часткової гідратації (з Next і Preact)

Навесні ми несемо відповідальність за підтримку різних веб-сайтів для ЗМІ для нашої материнської компанії Axel Springer. Один з наших останніх випусків, welt.de, - це найшвидший веб-сайт ЗМІ в Німеччині; Однією з наших найбільш затребуваних цілей є постійне досягнення найкращої можливої ​​продуктивності, і причина цього проста: краща продуктивність зазвичай означає кращий досвід роботи користувачів і, таким чином, більш високу утримання користувачів.

тл; д-р

Прокрутіть униз до розділу "Резюме", щоб отримати короткий підсумок з інфографікою. Ключові моменти цього в двох словах:
  • Продуктивність має вирішальне значення для Інтернету
  • щоб досягти високої продуктивності, ми хочемо якомога менше надсилати клієнту
  • ми можемо це зробити, вибравши компоненти, які ми хочемо надіслати та гідратати клієнту
  • ми залишаємо решту сторінки статичною і має кілька кореневих зображень
  • Все це працює з єдиною базою коду
  • Нижче наведена довга стаття про те, як ми реалізували зазначені вище кроки. Ви також знайдете посилання на репортаж цієї програми WIP тут:
  • https://github.com/spring-media/next-super-performance

Продуктивність в Інтернеті

Якщо ви слідуєте за Адді Османі, ви вже знаєте, що він веде, він багато пише про причину та наслідки роботи в Інтернеті. Щоб розпочати, я можу порекомендувати статтю Адді на тему "Вартість JavaScript у 2018 році". Дві дуже важливі речі, про які можна дізнатися з цієї статті, є:

  • Вартість JavaScript - це не лише час, необхідний для завантаження вашого пакету
  • Час для розбору та виконання JavaScript так само важливий

Звичайно, ефективність набагато більше, ніж ця, включаючи стратегії завантаження, критичний шлях рендерінгу, бюджети ефективності тощо. Усі ці речі залежать від того, як оптимізувати все, що ви в кінцевому підсумку надсилаєте своєму клієнту. Те, на чому ми хочемо зосередитись при частковій гідратації, полягає не в тому, як оптимізувати те, що ви надсилаєте, а скільки ви взагалі відправляєте.

Ключовим аспектом цього буде рендеринг на стороні сервера (SSR), оскільки на сервері є багато, що ми можемо зробити, чого не потрібно робити клієнту. Фактично, це суть цієї статті; Все, що можна зробити на сервері, слід робити на сервері, але клієнту слід надсилати лише те, що потрібно виконати на стороні клієнта. Крім того, ви все ще можете застосувати все, що знаєте про ефективність роботи в Інтернеті, але у вас буде набагато менше факторів управління, це буде детально пояснено далі в статті.

ССР і гідратація

Для здійснення нашої мети створення виконавського веб-сайту ми будемо використовувати модифіковану версію Next. Далі поставляється в комплекті з великою кількістю вбудованих функцій для підвищення продуктивності, головне - Далі робить візуалізацію сторони сервера (SSR) поза коробкою. Це означає, що Далі візьме ваш додаток, написане на React та в такому порядку:

  1. Візуалізуйте його як HTML-рядок на сервері
  2. Надішліть виведений рядок HTML своїм користувачам як вихідний код
  3. Надішліть своїм користувачам код React як JavaScript
  4. А потім нарешті “гідрат” свого HTML за допомогою коду React

"Гідрат" у цьому випадку означає, що Далі буде розгортати ваш код React над вашим HTML-кодом, а потім скаже React щось трохи подібне:

Здравствуйте, реагуйте, ось такий HTML, який відповідає саме тому, що ви б показали, якби я сказав вам зробити візуалізацію в порожньому DOM-вузлі, будь ласка, не повторюйте все, натомість, будь ласка, просто використовуйте HTML так, як якщо б ви його зробили і продовжуйте з твій день

Реакція відповість

Гаразд, я просто подивився на вас HTML і, здається, відповідає саме тому, що я б створив. Це круто. Я просто приєднаю декілька обробників подій до вашого DOM, і ваша сторінка зараз виступає як додаток на одній сторінці, як я це робив сам у першу чергу.

Переваги завантаження веб-сайту таким чином прості: ваші користувачі вже побачать повністю відтворену сторінку, коли завантажуватимуть ваш веб-сайт (замість порожньої сторінки), і тоді він стане інтерактивним. Ваш веб-сайт також отримає користь від значного поліпшення продуктивності, оскільки веб-переглядачу не потрібно робити якісь перефарбовування (відновлювати вашу сторінку за допомогою React).

Занадто багато накладних витрат

Цей підхід є фантастичним, коли ви хочете створювати веб-додатки або іншими словами веб-сайти, які повинні повністю контролюватися JavaScript, а також є інтерактивними, де б ви не клацали. Приклади такого підходу у виробництві включають веб-сайти, такі як Facebook, Twitter та веб-клієнти електронної пошти.

Але більшість веб-сайтів не схожі на це, більшість веб-сайтів є своєрідними, а також містять інтерактивні елементи.

Тепер ви в кінцевому підсумку надсилаєте своїм користувачам весь код програми, включаючи компоненти React для кожного заголовка чи тексту в будь-якій точці вашої сторінки. В результаті виходить непотрібно величезний пакет, який потрібно завантажити, проаналізувати та виконати. Це призводить до неоптимальної продуктивності, ваша сторінка буде повільною (ер), особливо для користувачів мобільних пристроїв і без жодних вагомих причин!

І це смокче.

То що ми можемо зробити? Ну, існує багато стратегій і продуктів там. Один з найпомітніших з них - це Гетсбі, генератор статичних сайтів (я впевнений, що ви вже чули про це), який сильно фокусується на оптимізації продуктивності. Проблема з Гетсбі полягає в тому, що він повинен генерувати всі ваші сторінки та підсторінки під час компіляції, що насправді не працює, коли у вас є веб-сайти, пов’язані з CMS, що щодня оновлюються, і на яких розміщені мільйони статей, - це саме те, що нам потрібно для наших сайти новинних ЗМІ Ось чому ми використовуємо Next, а також модифікуємо його відповідно до наших потреб.

Введіть часткову гідратацію

Для вирішення вищезазначених проблем ми придумали щось, що ми любимо називати частковою гідратацією.

Якщо ви розглядали цю тему, ви, мабуть, зіткнулися з такими термінами, як прогресуюча гідратація або ледача гідратація. Всі вони конкретно не означають одне і те саме, але всі вони взаємопов'язані і належать до однієї сфери.

Основна ідея нашої версії часткової гідратації полягає в тому, що замість того, щоб робити SSR, а потім відправляти всю програму своєму клієнту, клієнтові будуть надіслані лише ті частини JavaScript вашої програми для гідратації частин вашого веб-сайту, які спеціально вимагають JavaScript для роботи. . Якби ви створили веб-сайт за допомогою такого способу, на вашому інакше статичному веб-сайті ви мали б декілька крихітних «додатків» React із декількома коренями візуалізації.

Таким чином, ваш веб-сайт повинен підвищити ефективність роботи, оскільки ви отримуєте звичайний HTML, CSS та найменший обсяг JavaScript, необхідний для вашої сторінки. Слід зазначити, що при вимірюванні продуктивності ви повинні не тільки враховувати час завантаження, але й час розбору та часу виконання.

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

Наша реалізація

Наша реалізація складається з 2 пакетів:

  • Бібліотека Preact для часткової гідратації називається відвідувачем басейну-преакцією
  • Плагін Next.js викликав next-super-performance

Остання бібліотека - це лише плагін для Next.js, який використовує пул-супроводжувач басейну, тому давайте зосередимося на відвідуванні пулу-преакції. Я можу написати подальший пост про наступну супер-виставу на якомусь етапі в майбутньому.

відвідувач басейну-прокт

Макет із заголовком, корпусом, бічною панеллю та 2 реагуючими елементами

Зобразіть цей макет і зробимо вигляд, що сірі поля - це елементи, які можуть бути повністю статичними, і ви хочете, щоб ті, які були в фіолетовому кольорі, були інтерактивними. Наприклад, більший може бути каналом Twitter, а менший - крихітним інструментом для голосування. Тому нам потрібно застосувати JavaScript до цих елементів, щоб зробити їх інтерактивними, а решту ми хочемо залишити як статичні елементи.

Приклад реалізації для цього за допомогою методу-відвідувача басейну може виглядати так:

Рядки 3–8 - це всі компоненти, які ми хочемо відобразити, ці компоненти будуть виведені на сервер, а потім відправлені клієнтові як HTML і CSS без будь-якого JavaScript.

Рядки 10 та 11 - це те, що ми відзначаємо компоненти TwitterFeed та Poll для гідратації та отримуємо новий компонент натомість. Рядки 18 та 19 - це те, де ми їх використовуємо.

Рядок 22 має надзвичайно важливе значення. Це компонент, який вводить на сторінку дані гідратації (реквізити та назви компонентів).

Але дозвольте пояснити. Коли ми робимо звичайну гідратацію з реагуванням, ваш код виглядає приблизно так:

Тут ми повинні вирішити дві проблеми, коли робимо часткову гідратацію

  1. ReactDOM.hydrate працює на кореневому вузлі в DOM, вузолі, який він використовує як вихідну точку для гідратації. Цей кореневий вузол повинен містити серверне дерево DOM, яке відповідає компонентам та стану вашої програми. Улов: Вам потрібно чітко назвати вузол DOM, щоб діяти як кореневий вузол. У цьому прикладі це просто: ви можете надати цьому вузлу ідентифікатор, використати document.getElementbyId, а потім перекинути цей вузол у ReactDOM.hydrate і у вас все!
    З іншого боку, часткова гідратація означає, що на вашій статичній сторінці у вас буде кілька елементів DOM, які вам потрібно гідратати. Ви не хотіли б чітко називати їх усім, що було б копіткою роботою для розробника.
  2. Що робити, якщо HydrateTwitterFeed або HydratedPoll потрібні реквізити, які потрібно передати їм? Скажімо, щось на кшталт . Якщо ми хочемо запустити ReactDOM.hydrate (, rootElementOnThePage) звідки ми отримаємо luke_schmuke? Як статична сторінка дізналася б про це? Нам потрібно якось зберігати і відправляти їх клієнту.

Рішення

Те, як ми вирішили цю проблему, можна зрозуміти з впровадження програми «Гідрація»:

Давайте докладніше розглянемо це: з допомогою гідрації працює за допомогою методики компонентів вищого порядку, компонент вищого порядку повертає оригінальний компонент разом із його оригінальними незмінними реквізитами, але також попереджує його тегом