D2 — Создайте высоконадежное и производительное изоморфное решение React

Node.js React.js
D2 — Создайте высоконадежное и производительное изоморфное решение React

Эта статья была опубликована вBeidou изоморфизм github, Пожалуйста, укажите источник

Примечание: эта статья12-й Форум по передовым технологиям D2 «Создание высоконадежных и высокопроизводительных изоморфных решений React»Общий контент подвергся десенсибилизации данных.

предисловие

  • С появлением React в сочетании с преимуществами производительности Node и компонентами React изоморфизм React стал одной из тенденций. Пользуясь техническими преимуществами, столкнитесь лицом к лицу с техническими проблемами и бросьте вызов максимальной оптимизации производительности более чем в 10 раз в сложных сценариях.

Что такое изоморфизм?

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

Почему изоморфизм?

  • Производительность: прямо через Node, упрощая традиционные три последовательных HTTP-запроса в один http-запрос, сокращая время рендеринга первого экрана.
  • SEO: рендеринг на стороне сервера имеет естественные преимущества для сканирования поисковыми системами.Хотя система электронной коммерции Alibaba не предъявляет жестких требований к SEO, с продвижением интернационализации все больше и больше международных компаний присоединяются к семье Alibaba.Бизнес зависит от импорта трафика из поисковых систем, таких как Google, таких как Lazada.
  • Совместимость: некоторые отображаемые страницы могут эффективно избежать проблем совместимости с клиентами, таких как белые экраны.

данные производительности

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

isomorphic

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

isomorphic

Онлайн-кейс

  • За последние два года как в отрасли, так и внутри Alibaba появилось большое количество изоморфных практик.Наиболее влиятельными в отрасли являются Facebook, Quora, Medium, Twitter, Airbnb, Walmart, мобильные QQ и группы интересов QQ. и т.п.
  • Внутри али тоже большое количество приложений, перечислены только некоторые из них.группа разработчиков бэйдоуПроекты технической поддержки
    • Облако Али - Недвижимость больших данных
    • DingTalk — корпоративная домашняя страница
    • DingTalk — рынок журналов и шаблонов утверждений DingTalk
    • Cainiao - Логистический рынок
    • Облачная розничная торговля — Менеджер магазина
    • Lazada - PDP
    • Международное бизнес-подразделение - AGLA
    • AILab - Отраслевые решения
    • AILAB — интеллектуальная аппаратная платформа
    • AILab - Открытая платформа AliGenie
    • AILab — Официальный сайт AR
    • ICBU - Магазин ICBU
    • Бизнес-платформа – оценка магазина
    • Международный UED — Операции с данными
    • Международный UED - Знай
    • Международный УЭД - третий цветок
    • Международный UED - веб-сайт Nuke и управление процессами
    • Международный UED - протокол конференции, прямой перевод
    • Международный UED - Карта данных LBS
    • Международный UED — Обнаружение данных
    • Международный UED - Микро политика
    • Международный UED - шаттл
    • International UEED - FIE портал
    • ...

Экология промышленности

  • react-server: Фреймворк рендеринга React на стороне сервера.
  • next.js: Легкий изоморфный каркас
  • beidou: собственный изоморфный фреймворк Али, основанный на eggjs, позиционируемый как изоморфный фреймворк корпоративного уровня.

В дополнение к опенсорсному фреймворку в React16 рефакторен SSR на нижнем уровне, а react-router предоставляет более дружественную поддержку SSR и т. д. В определенной степени изоморфизм — это тоже тренд, по крайней мере, одно из направлений.

Подумай и осознай

Отправной точкой изоморфизма является не «сделать изоморфизм, как я это сделал», а вернуться к делу, чтобы решить SEO, производительность в верхней части страницы, взаимодействие с пользователем и другие проблемы в бизнес-сценариях, а также подтолкнуть нас к поиску доступных решений. . В таком сценарии помимо самого изоморфизма нам также необходимо учитывать:

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

Короче говоря, нам нужно решение для изоморфного рендеринга корпоративного уровня.

Как мы делаем это?

Добавить подключаемый изоморфизм на основе eggjs

  • beidou-plugin-reactВ качестве замены слоя представления в исходной архитектуре MVC, используя компонент React в качестве шаблона слоя представления, компонент React можно напрямую отображать и выводить клиенту.

  • beidou-plugin-webpackИнтегрируйте Webpack в платформу и предоставьте услуги компиляции кода и упаковки на этапе разработки.

  • beidou-plugin-isomorphicСреда выполнения React на стороне сервера: внедрение полифилла babel-register: переменные среды, спецификация и т. д. Парсинг не-js файлов: css, изображения, шрифты...

  • Сервер поддерживает css-модули.

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

  • ...

Я не буду вдаваться в детали того, как это реализовать здесь, заинтересованные читатели могут прочитать наш изоморфный фреймворк с открытым исходным кодом.beidou -- GitHub.com/Alibaba/Be…

Горячие вопросы

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

  • утечка памяти
  • узкое место производительности
  • ...

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

Экстремальная оптимизация производительности

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

react15 performance

Приведенное выше изображение основано на Node v8.9.1 и React@15.5.4, данные собраны путем запуска 4 процессов, по оси X указано конечное количество сгенерированных узлов страницы, красная линия по оси Y представляет RT (включая время рендеринга и время сети), зеленый Столбцы представляют QPS. Видно, что:

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

Кстати, автор сэмплировалГлавная Таобаоа такжеTaobao подробная страницатак же какПодробная страница Lazada, количество узлов страницы составляет 2620, 2467 и 3701 соответственно. В большинстве случаев количество узлов страницы меньше 1000, напримерЛогистический рынок ЦайняоНа домашней странице кажется много контента, но на самом деле количество узлов составляет 775.

Что мы должны делать для страниц с более чем 3000 узлов? Автор суммирует следующие стратегии и выделяет одну или две из них:

  • Использование скомпилированной версии React: Согласно блогу Саши Айкина, React15 под Node4, Node6 и Node8, производительность скомпилированной версии улучшена в 2,36 раза, 3 раза и 3,85 раза соответственно по сравнению с некомпилированной версией.
  • Разделение модулей: разделение модулей способствует одновременному рендерингу, который в настоящее время используется в оформлении магазина ICBU.
  • Кэширование на уровне модулей: некоторые модули на странице на самом деле очень подходят для кэширования.Например, хотя количество узлов на странице сведений Lazada достигает 3701, на самом деле на заголовок приходится 55,5%, на нижний колонтитул страницы. составляет 3,5 %, а верхний и нижний колонтитулы — 3,5 % и остаются постоянными круглый год.
  • Кэш на уровне компонентов: наименьшая степень детализации единицы кэша. Повышение производительности зависит от диапазона и частоты попаданий в кэш. При правильном использовании это может привести к очень значительному повышению производительности. Ссылаться наwalmartlabs
  • Используйте hsf вместо http для предоставления внешних сервисов: сетевое потребление hsf намного ниже, чем у http.В практике изоморфизма хранилища вместо него используется hsf, а время, необходимое java-стороне для вызова Node-стороны, сокращается. наполовину.
  • Часть рендеринга модуля на стороне клиента (часть, которая бесполезна для SEO): напрямую уменьшите сложность части SSR.
  • Интеллектуальная деградация: когда трафик резко возрастает, приближаясь к порогу или превышая его, это напрямую приведет к быстрому увеличению RT услуги. Он может отслеживать использование ЦП и памяти в режиме реального времени и автоматически переключаться на рендеринг на стороне клиента, когда он превышает определенный коэффициент, уменьшая нагрузку на стороне сервера.Когда ЦП и память возвращаются к норме, он автоматически переключается обратно на сервер- боковой рендеринг.
  • Использование Node8: Также в магазине при использовании Node8 по сравнению с Node6 время рендеринга сокращается с 28 мс до 18 мс, что на 36% больше.
  • Используя последнюю версию React16:официальные данные фейсбука, Под Node8 React16 по-прежнему в 3,8 раза лучше скомпилированного React15, что на порядок лучше по сравнению с нескомпилированным React15.

Кэш уровня компонентов

Если есть «универсальный» ход для оптимизации производительности, то это должен быть кеш, от кеша Nigix до кеша на уровне модуля и кеша на уровне компонента, наиболее интересным из которых является кеш на уровне компонента, давайте посмотрим, как этого добиться. Это

  • Есть три основных способа перехватить логику рендеринга React.
    • Разветвите копию React, насильственно добавьте логику кэширования, репрезентативная библиотекаreact-dom-stream, хотя популярность этой библиотеки очень высока, автор все же против такой реализации.
    • Перехватить загрузку экземпляра ReactComponent через хук require и внедрить логику кеша, см.react-ssr-optimization
    • Расширьте метод mountComponent ReactCompositeComponent, см.electrode-react-ssr-cachin
  • Введите логику кеша, код выглядит следующим образом
const ReactCompositeComponent = require("react/lib/ReactCompositeComponent");

ReactCompositeComponent.Mixin._mountComponent = ReactCompositeComponent.Mixin.mountComponent;
ReactCompositeComponent.Mixin.mountComponent = function(rootID, transaction, context) {
  
  const hashKey = generateHashKey(this._currentElement.props);
  if (cacheStorage.hasEntry(hashKey)) {
    // 命中缓存则直接返回缓存结果
    return cacheStorage.getEntry(hashKey);
  } else {
    // 若未命中,则调用react的mountComponent渲染组件,并缓存结果
    const html = this._mountComponent(rootID, transaction, context);
    cacheStorage.addEntry(hashKey, html);
    return html;
  }
};
  • Установить максимальный кеш и политику обновления кеша
lruCacheSettings: {
      max: 500,  // The maximum size of the cache
      maxAge: 1000 * 5 // The maximum age in milliseconds
  }

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

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

template

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

  • Создайте промежуточную структуру:
    • с компонентами<Price>${price}</Price>Например, поместите переменную цену в качестве заполнителя.${price}заменятьset(price, "${price}"), а затем вызовите собственный метод mountComponent реакции для создания промежуточной структуры.<div>${price}</div
  • промежуточная структура кэша
  • Создание конечных компонентов

Выше приведена реализация кэширования на уровне компонентов.Напоминаем, что кэширование — палка о двух концах.Неправильное использование может привести к утечкам памяти и несогласованности данных.

React16 SSR

  • FB выпустил официальную версию React16 9.26, долгожданную версиюУлучшение производительности SSRНе разочаровал всех, процитировав сравнительную таблицу основного разработчика React Саши Айкина.react16

Автор обновил предыдущее приложение до React 16. По сравнению с 3909 узлами, RT уменьшился с 295 мс до 51 мс, а QPS увеличился с 9 до 44. Улучшение очень очевидное.

react16

реальный бой

Далее в примере показано, как шаг за шагом повышать производительность.репозиторий кода -- GitHub.com/Alibaba/Be…

Повышение производительности более чем в 10 раз

  • Сначала создайте очень сложную страницу, количество узлов страницы 3342, в отличие отГлавная ТаобаоКоличество узлов страницы на первом экране — 831. После полной асинхронной загрузки (завершение ленивой загрузки) количество узлов на всей странице — 3049. Примечание. Страница Taobao — это динамическая страница, и каждая выборка может быть разной.

复杂页面

淘宝首屏

淘宝全屏

  • Начальное среднее время рендеринга составляет295.75ms(Node6.92, React15.6.2), Примечание: есть296.50ms,317.25ms,297.25ms,295.75msЧетыре средних значения связаны с тем, что четыре процесса открыты, и последний из них выбирается, то же самое ниже.

初始渲染时间

babel性能加速插件

  • Среднее время рендеринга с использованием Node8.9.1 (или новее) составляет207ms

Node8

  • использоватьproductionСреднее время рендеринга в режиме81.75ms

production mode

  • Рендеринг некоторого контента на стороне клиента, среднее время рендеринга составляет44.63ms

part csr

  • Часть кеша уровня компонента контента, среднее время рендеринга22.65ms

part cache

  • В React16 (или новее) среднее время рендеринга составляет5.17ms

react16

  • При сочетании React16 и частичного рендеринга на стороне клиента среднее время рендеринга составляет2.68ms

react16+csr

На данный момент время рендеринга на стороне сервера было295.75msсокращено до2.68ms, увеличившись более чем в 100 раз.

Дополнительные стратегии повышения эффективности

На самом деле, помимо вышеупомянутых стратегий, существуют и другие стратегии, такие как

  • использоватьAsync, По некоторым данным, производительность улучшается на 30%.Автор пробовал и существенного улучшения не увидел. Его должен был скомпилировать babel, но в итоге он не воспроизвелся.Asyncпреимущество, потому чтобейдо кадрподдержка на сервереimportОжидание написания ES6 и поддержка ReactJSX语法. На самом деле, это очень просто, непосредственно уменьшитьbabelОбласть компиляции , вбейдо кадрможно определить самостоятельно.
  • Понизьте уровень вложенности компонентов React. Тестовые данные, одинаковое количество узлов страницы, время рендеринга на стороне сервера и уровень вложенности компонентов имеют линейную положительную корреляцию.
  • Кэш точки доступа...

постоянно меняющийся

Позаимствовать классическую строчку из "Кунг-фу"天下武功,无坚不破,唯快不破, опять же, со временем вышеописанные стратегии рано или поздно被破, например, после рефакторинга react16 ssr предыдущая логика кэширования на уровне компонентов больше не действует. Кроме того, может быть так, что архитектурного проектирования/технического подбора просто недостаточно.Например, react16 был официально выпущен 26 сентября этого года, и многие сторонние компоненты не успели обновиться.Если некоторые компоненты в приложении сильно зависит от реакции 15 или более ранней версии, вы вообще не сможете воспользоваться преимуществами производительности реакции 16.

Так есть ли万能的办法, сможет сделать唯快不破Шерстяная ткань?

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

Для конкретной методологии, пожалуйста, обратитесь к моей другой статье"Только fast не ломается, пусть nodejs будет быстрее"

Категории