Больше, чем React: Почему не следует использовать ReactJS для сложных интерактивных фронтенд-проектов

в 9:59, , рубрики: ReactJS, Блог компании NIX Solutions, Программирование, фронтенд

Перевод статьи, посвящённой использованию ReactJS для создания фронтенда.

React — отличный инструмент для реализации простых интерактивных веб-сайтов. Но насколько он применим в сложных фронтенд-проектах? Работает ли он там столь же хорошо?

В этой статье мы рассмотрим некоторые проблемы, с которыми можно столкнуться при использовании React во время веб-разработки. Также вы узнаете, почему автор статьи решил разработать новый фреймворк на Scala, благодаря которому удалось сократить количество строк кода с 30 тысяч (на React) до одной тысячи.

Ключевые моменты

  • Компоненты React трудно использовать повторно в сложных веб-проектах.
  • Алгоритм Virtual DOM в React медленный и неточный.
  • HTML-шаблоны React не являются ни полными, ни мощными.
  • React требует сложного асинхронного программирования при общении с сервером.
  • Binding.scala содержит меньше концепций, но больше функций. Перспективный Binding.scala решает сложные проблемы, которые React решить не может.

Предпосылки

Многим фреймворк React кажется более простым и удобным по сравнению с AngularJS. Одной из самых полезных его функций является связывание данных (data binding). Оно позволяет сопоставить источники данных с элементами веб-страниц, что предоставляет удобный способ реализации простых интерактивных веб-сайтов.

Однако возможны ситуации, в которых React не может решать запутанные проблемы так же легко, как простые. Если поэкспериментировать с TodoMVC, то окажется, что приложение на фреймворке Binding.scala содержит всего 154 строки кода по сравнению с 488 строками на React.

Больше, чем React: Почему не следует использовать ReactJS для сложных интерактивных фронтенд-проектов - 1

Дальше мы рассмотрим четыре проблемы React и как их решает Binding.scala.

Проблема 1: компоненты React трудно повторно использовать в сложных интерактивных веб-проектах

Минимальным блоком для повторного использования в React является компонент (React.Component). Он более лёгкий, чем Controller и View в AngularJS. От веб-разработчика требуется лишь реализация функции render, которая транслирует свойства (props) и состояние (state) компонента в HTML-элементы.

Такой легкий компонент очень удобен при создании простых веб-страниц. Однако, когда требуется взаимодействие между несколькими компонентами, неизбежна передача функций обратного вызова (callback functions) в качестве параметра. В частности, для веб-страниц со сложными структурами приходится использовать десятки взаимосвязанных компонентов, в которых коллбэки передаются от родителей к потомкам из слоя в слой. Единственным результатом применения фреймворка React в таких сложных интерактивных веб-проектах будет то, что код станет слишком беспорядочным и трудноподдерживаемым.

Проблема 2. Virtual DOM в React является медленным и неточным

Алгоритм рендеринга в React использует Virtual DOM.

Разработчик обязан предоставить функцию render, которая создает виртуальный DOM, используя свойства и состояние компонента. А React на основе этого виртуального DOM конструирует реальный.

При изменении состояния React вновь вызывает функцию render и строит новый Virtual DOM. Затем он анализирует различия между старой и новой версией виртуального DOM и применяет их к реальному DOM.

У этого процесса есть два недостатка:

  1. 1. Независимо от того, что изменилось в состоянии, функции рендеринга всегда будут генерировать новые полные виртуальные DOM. Если функция render сложна, то вычислительные ресурсы тратятся впустую.
  2. 2. Сравнение двух версий DOM медленное и подвержено ошибкам. Например, если вы хотите вставить элемент li в начало ul, то React ошибочно решит, что вы модифицировали все компоненты li в ul и добавили один li в конце.

Поскольку две версии виртуального DOM независимы друг от друга, React не имеет представления о том, что происходит на самом деле. Он случайным образом угадывает произошедшие изменения, основываясь на обоих DOM. Этот алгоритм очень медленный и неточный. Веб-разработчики вынуждены использовать свойство key, а также методы shouldComponentUpdate и componentWillUpdate, чтобы помочь фреймворку угадать правильно.

Проблема 3. HTML-шаблоны React не являются ни полными, ни мощными

Для разработки HTML-шаблонов React поддерживает JSX.

Теоретически, фронтенд-разработчики могут превратить статический HTML в динамическую веб-страницу, просто скопировав HTML в JSX-файлы и добавив немного дополнительного кода. Действительно, React больше подходит для повторного использования HTML-шаблонов по сравнению с другими фреймворками, такими как Cycle.js, Widok и ScalaTags.

К сожалению, поддержка HTML в React является неполной. Разработчик должен вручную заменить class на classname, а for на htmlFor. Кроме того, синтаксис встроенных стилей необходимо поменять с CSS на JSON. И хотя веб-разработчики могут копипастить HTML в код, это всё равно требуется много времени и усилий. Таким образом, нельзя сказать, что React превосходит Cycle.js, Widok или ScalaTags.

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

React также не способен найти ошибки в именах. Например, если написать onclick вместо onClick, то сообщения об ошибке не будет, но программа завершится сбоем. На поиски таких бессмысленных ошибок разработчики обычно тратят очень много времени и энергии.

Проблема 4: React требует сложного асинхронного программирования при общении с сервером

Рассмотрим работу React с сервером в терминах шаблона Model-View-ViewModel. Веб-разработчику нужно реализовать слой доступа к базе данных (Model), state в качестве ViewModel и функцию render в качестве View. Модель обеспечивает доступ к API бэкенда и устанавливает state (ViewModel), используя промисы (Promise and fetch API). Затем render (View) обеспечивает визуализацию ViewModel на веб-страницах.

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

Выводы

Binding.scala в некотором роде кажется похожим на React. Но лежащий в его основе механизм полностью отличается от React и Widok, он проще и универсальнее. Binding.scala гибче и мощнее, чем React. Мы можем использовать Binding.scala для решения сложных проблем, которые React решить не может.

Кроме четырех аспектов, упомянутых выше, есть и довольно значительная проблема управления состоянием в React. Если для управления состоянием использовать стороннюю библиотеку, такую как Redux, то структура приложения станет еще более запутанной, а количество слоев увеличится.

Для сравнения, Binding.scala описывает сложное состояние, используя тот же механизм связывания данных (data-binding), что и для рендеринга веб-страницы. И нет никакой надобности в сторонних библиотеках для обеспечения таких функций, как клиент-серверное взаимодействие, управление состоянием и URL-диспетчеризация.

Различия между Binding.scala и React:

Binding.scala React
Повторное использование Минимальный блок для повторного использования Метод Компонент
Уровень сложности повторного использования Возможность повторного использования независимо от интерактивных или статических компонентов Простота повторного использования в статических компонентах, но трудно использовать в интерактивных компонентах
Алгоритм рендеринга веб-страницы Алгоритм Точная привязка данных Virtual DOM
Производительность Высокая Низкая
Корректируемость Автоматически обеспечивает правильность Необходимо вручную настроить ключевые атрибуты
HTML Синтаксис Scala XML JSX
Поддерживает синтаксис HTML или XHTML? Полностью поддерживает XHTML Частично поддерживает, не может компилировать нормальный XHTML. Разработчики должны вручную заменить атрибуты class и for на className и htmlFor, а также изменить синтаксис стилей с CSS на JSON
Как проверяется синтаксис Проверяется автоматически при компиляции Выполняется через propTypes, но не может найти очевидные орфографические ошибки
Взаимодействие с сервером Механизм Автоматическая удаленная привязка данных MVVM + асинхронное программирование
Уровень трудности реализации Легко Тяжело
Другое URL-диспетчеризация Поддерживает URL-адреса как обычные связанные переменные, не требует сторонней библиотеки Не поддерживает, требуется сторонняя библиотека react-router
Полнота функциональности Полное решение для фронтенд-разработки Содержит только функциональность слоя View. Требует сторонние библиотеки для полной фронтенд- разработки
Кривая обучения API относительно прост. Легок для понимания даже теми, кто никогда не использовал Scala Удобно. Но чрезвычайно трудно изучить стороннюю библиотеку, которая используется для компенсации слабых сторон фреймворка

Ещё недавно среди представителей сообщества Scala.js самым популярным фронтенд-фреймворком был Widok. Но вскоре это место занял Binding.scala. Даже автор Widok Тим Нирадзик (Tim Nieradzik), не смог удержаться от похвалы и назвал Binding.scala наиболее перспективным фрейворком для рендеринга HTML5. Awesome Scala, сравнивая Binding.scala с конкурентами, также приходит к выводу, что этот фреймворк сейчас популярнее, чем Udash и Widok

Больше, чем React: Почему не следует использовать ReactJS для сложных интерактивных фронтенд-проектов - 2

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

Автор: NIX Solutions

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js