tl;dr; Нет.
Большинство разработчиков считают само собой разумеющимся, что ReactJS — это супер быстрый движок по сравнению
с другими более тяжеловесными фреймворками, такими как AngularJS и EmberJS.
И даже публикация фэйковых результатов не вызывает подозрений, а ведь если копнуть глубже и проанализировать код тестов, то вы будете сильно удивлены.
Virtual-DOM
Все мы понимаем, что манипуляции с DOM достаточно медленные. На этом и выехал ReactJS, представив новую идею виртуального DOM, позволяющего производить все манипуляции на виртуальных объектах, а в реальное дерево объектов браузера аффектить только разницу, таким образом минимизируя количество запросов к DOM модели и тем самым ускоряя приложение.
Интуитивно такой подход воспринимается как возможность серьёзного улучшение производительности, но никто не задумывается о том, насколько на производительность повлияет исполнение достаточно ресурсоёмкого javascript кода для исполнения этой задумки.
И так же странно отсутствие каких-либо примеров улучшения производительности при использовании Virtual-DOM, кроме примеров сравнения с другими фреймворками.
Мы все видели эти демо, предлагаю рассмотреть их более внимательно.
React.js Conf 2015
Это наиболее популярное видео произвело «вау» эффект на публику, разница в скорости в самом деле поразительная. Ниже ссылки на оригинальные примеры, используемые в видео:
— Ссылка на видео
— ReactJS demo
— AngujarJS demo
Но если глянуть в код, мы обнаружим, что автор не подумал использовать базовую фичу для улучшения производительности в Angular: "track by"
Если подправить всего лишь одну строчку в исходнике:
ng-repeat="(key, db) in databases"
На:
ng-repeat="(key, db) in databases track by key"
То получаем следующий результат:
ссылка
Удивлены?
К сожалению, в Angular большинство рекомендаций по улучшению производительности плохо документированы и не поддерживаются автоматически. Однако даже это небольшое изменение кардинально исправит производительность
в 95% тестах сравнения reactJS против AngularJS.
Разберем еще одну популярную презентацию
Эта презентация тоже вызвала «вау» эффект. Советую посмотреть окончание презентации, там где показывается феноменальная производительность Angular 2.0 и последующие извинения докладчика:
Вот пример из этой презентации: смотреть
Здесь была обнаружена другая проблема, уже не в прорисовке, а в обработке данных. В примере с ReactJS было явно указано, какая колонка изменилась, в то время как AngularJS примере было сказано «что-то изменилось», что приводило к перепроверке всего.
Отключив вызов перерисовки всех данных и оставив только проверку изменений следующим образом:
$timeout(function() {
$scope.status.isSearching = false;
$scope.status.searchResults = ...
Updated to:
setTimeout(function() {
$scope.status.isSearching = false;
$scope.status.searchResults = ...
$scope.$digest();
Получаем следующий результат:
смотреть
В последних версиях Angular это делается следующим образом: $timeout([func], [timeout], false);
Что же в итоге?
Получается, что основанные на Virtual-DOM фреймворки не имеют тех демонстрируемых преимуществ по скорости перед обычными фреймворками типа AngularJS or EmberJS. Утверждение, что добавление примесей ReactJS к AngularJS приложению магическим образом исправит производительность, основано не на фактических данных, а на ошибках
в разработке.
Плох ли ReactJS?
Нет. ReactJS отличный фреймворк, который мы в 500Tech используем и любим. Есть много преимуществ в использовании reactJS в вашем следующем проекте, но скорость — не одна из них.
Комментарии (41)
AlexeyFrolov
09.06.2015 20:52+7«Скандалы, интриги, расследования — показать всё, что скрыто» lol
Ну сколько можно уже мотаться с этой статьей? Не думаю, что неоспоримые преимущества перебиваются этими жалкими миллисекундами, если даже не брать в рассчет, что людям, которые во всю юзают Реакт не до холеваров.vitvad
09.06.2015 22:23-3из-за этих жалких миллисекунд и появляются фреймворки с виртуальным DOM.
>людям, которые во всю юзают Реакт не до холеваров.
конечно нет, им нужно поддерживать мешанину HTML внутри JSzw0rk
09.06.2015 22:29+5> конечно нет, им нужно поддерживать мешанину HTML внутри JS
Но это же не правда.Apx
10.06.2015 00:09-1Ну если взглянуть на get started на сайте реакта, то именно html внутри js и виден :)
В этом плане подход ангуляра проще, поскольку он работает внутри самой html страницы из коробки. И если чисто теоретически какой-то умный человек отключит js то хотя бы на странице останется хоть что-то из html, что будет показано.grossws
10.06.2015 00:24Ну если взглянуть на get started на сайте реакта, то именно html внутри js и виден :)
В jsx, строго говоря, никакого html нету. Этот syntaxic sugar транслируется в js (React.createElement(...)
), что объясняется, в том числе, и в tutorial'е.
В этом плане подход ангуляра проще, поскольку он работает внутри самой html страницы из коробки. И если чисто теоретически какой-то умный человек отключит js то хотя бы на странице останется хоть что-то из html, что будет показано.
Только каркас, без контента. В случае реакта будет то же самое, т. к. он встраивается в существующий каркас (при использованииReact.render(...)
.Apx
10.06.2015 00:44Ну JSX опять же таки javascript. Да и под него ещё и скрипт надо тянуть отдельный сверху. Но это скажем так скорее вопрос кто как любит склеивать библиотеки, кто-то всё в кучу кто-то отдельно. А синтаксический цукерман почти у всех схож))
grossws
10.06.2015 00:56Напомню, вы написали, что
именно html внутри js и виден
Как это коррелирует сНу JSX опять же таки javascript.
мне не очень понятно.
Да и под него ещё и скрипт надо тянуть отдельный сверху.
Можно его преобразовывать jsx в js на сервере, можно на клиенте (тогда подключаются скрипт-транслятор и text/jsx), можно сразу писать js, без использования jsx. Эти три варианта эквивалентны.
Benjaminabel
10.06.2015 00:05Читал статью в оригинале. «Шо то отличный фреймворк, шо это отличный фреймворк». Но, как мне кажется, Angular с лёгкостью выигрывает в удобстве использования в рамках как и больших, так и малых приложений. Интереснее было бы сравнение с Polymer, так как он уже намного больше похож на React.
Apx
10.06.2015 00:39+1Ну полимер это как бы всё же «чисто» веб компоненты. Никакого больше волшебства фреймворка в нём не происходит. Ангуляр предоставляет больше в данном случае. Сравнивать скорее надо polymer и директивы ангуляра, но опять таки одним лёгким движением руки директива попадает под полный digest cycle агуляра в большинстве случаев, и жить отдельно без него просто не в состоянии. Так что тоже сравнение с трамвайной ручкой получается.
zw0rk
10.06.2015 03:23+1В моём проекте ангуляр с лёгкостью проиграл реакту еще на стадии прототипирования.
KIVagant
11.06.2015 00:53Вброс засчитан. Чем проиграл?
zw0rk
11.06.2015 02:16+1Битвами с digest-loop-ами, чудовищной многословностью, нагромождением концепций (директива, контроллер, шаблон, резолвы и т.п. и т.д.) и всё это сразу. Когда на странице происходит сразу много всего, ангуляр начинает постоянно мешаться, а не помогать.
p.s. К тому же, у нас cljs и om был естественным решением :)
serf
10.06.2015 07:12-2Вот именно, ангуляр полностью замодостаточен, дает все что нужно и при этом использовать его достаточно удобно (что бы не писали начинающие о некой его сложности), а теперь еще мифы о скорости развенчаны. Реакт не нужен, разве что для каких-то специфических вещей.
sferrka
10.06.2015 07:52+3React нужен не для скорости, он нужен из-за компонентов. А вот HTML — пережиток прошлого, когда большая часть интерфейса была простым текстом, сейчас же гораздо больше активных элементов на странице, а данные изменяются локально, а не при перезагрузке страницы. Именно поэтому рождаются web-компоненты, именно поэтому Angular 2.0 их содержит. Поэтому шаблоны Angular содержат JS и различные байндинги, отсюда идея JSX (по сути, отказ от HTML). Да, JS тоже слабо подходит в качестве языка разметки, но зато в нем уже есть объекты ({{user.name}}), вызовы функций, математические, логические операции и т.д., которые давно используются во всех шаблонизаторах (т.е. по сути сообщество признало эти вещи декларативными).
Возможно, когда (или если) HTML разовьется в более полноценный язык разметки интерфейса, с поддержкой наследования, привязки данных и др., JS для этого станет не нужен, но может быть появится и что-то новое, как JSX, только без смешения парадигм и языков.serf
10.06.2015 08:14-4> JSX (по сути, отказ от HTML)
Повеселили, по сути наоборот наоборот, возврат к спагетти коду (разметка html в коде, php style фейсбук ведь). Тогда уже и древние фреймворки называйте компонентными, там обычно уйма готовы виджетов (подобие компонентов).Aetet
10.06.2015 09:43+4Хотите готовые компоненты вам сюда:
react-components.com
Подскажите мне, пожалуйста, почему разметка в html-коде это плохо? Вот только не надо заливать про разделение ответственности. html-код в jsx это шаблоны, которые динамически изменяются в зависимости от поданных переменных. По сути каждый реактовый виджет это просто чистая функция, которой на вход подаешь данные, она тебе возвращает верстку. Так почему это плохо? Почему
<div>{{name}}</div>
это нормально, а в реакте использовать все возможности javascript для построения шаблонов плохо.
Как правило сами шаблоны не переиспользуются, а вот виджеты которые используют эти шаблоны переиспользуются, так зачем же их разделять?serf
10.06.2015 09:46-5> Подскажите мне, пожалуйста, почему разметка в html-коде это плохо?
Как раз разметка в html коде это не плохо, но там смесь JS и HTML (этот ваш jsx).
Что только не придумают лишь бы не использовать ангуляр.wheercool
10.06.2015 10:24+5Что только не придумают лишь бы не использовать ангуляр.
Можно подумать, что ангуляр пуп земли.
Обычно такое высказывание свидетельствует об ограниченном кругозоре и скорее знакомство автора с reactJs свелось к беглому просмотру примеров на главной страницеserf
10.06.2015 10:27-2Разумеется не пуп, но для типовых задач, которых большиснтво ангуляр хорошо подходит. Просто они сейчас в тренде (ангуляр и реакт), при этом реакт неудобный и громоздкий на мой взгляд, не вижу в нем смысла особого. По опыту с реактом верно, продакшен проектов на реакте у меня не было.
tenbits
10.06.2015 22:45Я, например, уже давно html не использую. MaskJS имеет более лаконичный синтаксис, поддерживает декларацию компонент, наследование, merge шаблонов, модули — импорт/экспорт компонент, scope компонент; загрузка данных, скриптов и стилей; друсторонний байндиг, и много всего другого.
vintage
10.06.2015 09:23+2Быстрый фреймворк — не тот, на котором можно сделать быстро, а тот, на котором нельзя сделать медленно :-)
Тут же я вижу описание костылей, которые нужно вставить, чтобы хотя бы догнать реакт.
Пример с таймаутом я так и не понял. В чём отличие первого кода от второго? Каким образом ручная реализация поведения $timeout поможет увеличить скорость?andrewiWD
10.06.2015 09:54Быстрый фреймворк — не тот, на котором можно сделать быстро, а тот, на котором нельзя сделать медленно :-)
Медленно можно сделать не только на любом фреймворке, но и на любом языке программирования.
Тут же я вижу описание костылей, которые нужно вставить, чтобы хотя бы догнать реакт.
Т.е. продуманное и правильное написание кода, вы считаете костылями? С каких пор добавление индекса — костыль?!
Пример с таймаутом я так и не понял. В чём отличие первого кода от второго? Каким образом ручная реализация поведения $timeout поможет увеличить скорость?
Тут в $digest() фишка. В данном случае биндинг не нужен.vintage
10.06.2015 11:12Вопрос в том, насколько сложно сделать медленно :-)
Фреймворк должен упрощать написание кода, а не заставлять заниматься продумыванием каждой мелочи и не проглатывать исключения.
Где тут биндинг? $timeout всё, что делает — это вызывает отложенно функцию и запускает после этого $digestborn_to_surf Автор
10.06.2015 14:21Тут фишка в том, что $timeout по умолчанию вызывает $apply, который в свою очередь вызывает $digest для рутового скоупа, что приводит к пересчету всех ячеек
В представленной демо, функция $timeout вызывается для каждой ячейки, поэтому достаточно вызвать $digest только для текущего скоупа
youlose
10.06.2015 16:34+2Сделать медленно можно без проблем НА ЛЮБОЙ технологии, если знаете где это не так, буду благодарен узнать.
vintage
10.06.2015 16:50+3Ок, раз вы всё так буквально понимаете, ответьте, пожалуйста, на пару вопросов:
1. Как нужно поправить код на реакте, чтобы он стал столь же медленным, что и ангуляр без костылей?
2. Зачем может потребовать делать именно так?
TedBeer
10.06.2015 21:37-1У меня были подозрения на то, что прелести реакт преувеличены. Было лень копаться, пока не назрело и всегда получалось простым анализом кода улучшить производительность приложения на ангулар до нужного уровня.
Я вижу здравое зерно в идее виртуального дома — тяжелые операции можно производить используя workers, т.е. паралельно основному потоку. Но насколько эта идея работает надо проверять.zw0rk
11.06.2015 00:31+1Прелести реакта совсем не в скорости работы скриптов, а в простоте концепции — они не зря всё время цитату Дийкстры про таймлайн приводят, выстрадали.
zim32
13.06.2015 01:24Правильно ли я понимаю что Ember со своими очередями и отложенным обновлением DOM это почти то же что и diff в реакте? Может кто-то растолковать?
nuit
13.06.2015 07:06главное преимущество diff/patch'а в том что не нужно реализовывать никакого шаблонизатора и при этом получить immediate mode api с возможностью сохранять внутреннее состояние.
апдэйты теоретически возможно сделать быстрее с техникой, которая используются в глиммере(на практике пока у них это как-то не особо получается), рендеринг новых компонентов будет медленее. Например в фэйсбуке гораздо важнее скорость рендеринга, тк основная операция — это переход между страницами, и при переходе нужно быстро удалить почти всю деревяшку и вставить новую.
dangreen
В оригинальной статье можно найти ссылку на фреймворк jsblocks. Было бы интересно узнать чем он так быстрее реакта у ангуляра. Так же jsblocks имеет библиотеку которая быстрее underscore'а, здесь тоже интересно узнать в чем причина.
youlose
Как ни странно, чем меньше функционала и «синтаксического сахара», тем быстрее работают различные фреймворки или языки программирования, так что причина вполне очевидна.
dangreen
Это безусловно так. Но все же… хотелось бы на примере увидеть в чем заключается такой прирост. Может из-за того что в реакте используется своя реализация классов, что замедляет работу кода, может из-за еще чего то… не хочется гадать, хочется знать наверняка.
youlose
Ну отпрофилировать эти тесты надо и всё.
nuit
Если jsblock'овые тесты запустить на IE, реакт должен выиграть ;)
Вообще очень сложно сравнивать производительность различных подходов для датабайндинга, как например реакт и ангулар. Зная о том как внутри устроены оба фрэймворка, можно с лёгкостью сделать тест кэйсы на которых один фрэймворк будет очень сильно отставать по производительности от другого и наоборот.
scalavod
В этом треде автор jsblocks рассказывает за счёт чего происходит прирост в скорости по сравнению с lodash/underscore.
dangreen
Спасибо!