Предлагаю читателям «Хабрахабра» перевод публикации «Is ReactJS really fast?» из блога компании 500Tech.

tl;dr; Нет.

Большинство разработчиков считают само собой разумеющимся, что ReactJS — это супер быстрый движок по сравнению
с другими более тяжеловесными фреймворками, такими как AngularJS и EmberJS.

И даже публикация фэйковых результатов не вызывает подозрений, а ведь если копнуть глубже и проанализировать код тестов, то вы будете сильно удивлены.

image

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)


  1. dangreen
    09.06.2015 19:17
    +2

    В оригинальной статье можно найти ссылку на фреймворк jsblocks. Было бы интересно узнать чем он так быстрее реакта у ангуляра. Так же jsblocks имеет библиотеку которая быстрее underscore'а, здесь тоже интересно узнать в чем причина.


    1. youlose
      09.06.2015 21:23
      +3

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


      1. dangreen
        09.06.2015 21:27

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


        1. youlose
          10.06.2015 07:56

          Ну отпрофилировать эти тесты надо и всё.


        1. nuit
          10.06.2015 10:17

          Если jsblock'овые тесты запустить на IE, реакт должен выиграть ;)

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


    1. scalavod
      10.06.2015 18:20
      +2

      В этом треде автор jsblocks рассказывает за счёт чего происходит прирост в скорости по сравнению с lodash/underscore.


      1. dangreen
        10.06.2015 18:21

        Спасибо!


  1. AlexeyFrolov
    09.06.2015 20:52
    +7

    «Скандалы, интриги, расследования — показать всё, что скрыто» lol

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


    1. vitvad
      09.06.2015 22:23
      -3

      из-за этих жалких миллисекунд и появляются фреймворки с виртуальным DOM.

      >людям, которые во всю юзают Реакт не до холеваров.
      конечно нет, им нужно поддерживать мешанину HTML внутри JS


      1. zw0rk
        09.06.2015 22:29
        +5

        > конечно нет, им нужно поддерживать мешанину HTML внутри JS

        Но это же не правда.


        1. Apx
          10.06.2015 00:09
          -1

          Ну если взглянуть на get started на сайте реакта, то именно html внутри js и виден :)
          В этом плане подход ангуляра проще, поскольку он работает внутри самой html страницы из коробки. И если чисто теоретически какой-то умный человек отключит js то хотя бы на странице останется хоть что-то из html, что будет показано.


          1. grossws
            10.06.2015 00:24

            Ну если взглянуть на get started на сайте реакта, то именно html внутри js и виден :)
            В jsx, строго говоря, никакого html нету. Этот syntaxic sugar транслируется в js (React.createElement(...)), что объясняется, в том числе, и в tutorial'е.

            В этом плане подход ангуляра проще, поскольку он работает внутри самой html страницы из коробки. И если чисто теоретически какой-то умный человек отключит js то хотя бы на странице останется хоть что-то из html, что будет показано.
            Только каркас, без контента. В случае реакта будет то же самое, т. к. он встраивается в существующий каркас (при использовании React.render(...).


            1. Apx
              10.06.2015 00:44

              Ну JSX опять же таки javascript. Да и под него ещё и скрипт надо тянуть отдельный сверху. Но это скажем так скорее вопрос кто как любит склеивать библиотеки, кто-то всё в кучу кто-то отдельно. А синтаксический цукерман почти у всех схож))


              1. grossws
                10.06.2015 00:56

                Напомню, вы написали, что

                именно html внутри js и виден
                Как это коррелирует с
                Ну JSX опять же таки javascript.
                мне не очень понятно.

                Да и под него ещё и скрипт надо тянуть отдельный сверху.
                Можно его преобразовывать jsx в js на сервере, можно на клиенте (тогда подключаются скрипт-транслятор и text/jsx), можно сразу писать js, без использования jsx. Эти три варианта эквивалентны.


  1. Benjaminabel
    10.06.2015 00:05

    Читал статью в оригинале. «Шо то отличный фреймворк, шо это отличный фреймворк». Но, как мне кажется, Angular с лёгкостью выигрывает в удобстве использования в рамках как и больших, так и малых приложений. Интереснее было бы сравнение с Polymer, так как он уже намного больше похож на React.


    1. Apx
      10.06.2015 00:39
      +1

      Ну полимер это как бы всё же «чисто» веб компоненты. Никакого больше волшебства фреймворка в нём не происходит. Ангуляр предоставляет больше в данном случае. Сравнивать скорее надо polymer и директивы ангуляра, но опять таки одним лёгким движением руки директива попадает под полный digest cycle агуляра в большинстве случаев, и жить отдельно без него просто не в состоянии. Так что тоже сравнение с трамвайной ручкой получается.


      1. serf
        10.06.2015 07:19

        в 2.0 обсерверы используются, digest loop уже не проблема


    1. zw0rk
      10.06.2015 03:23
      +1

      В моём проекте ангуляр с лёгкостью проиграл реакту еще на стадии прототипирования.


      1. KIVagant
        11.06.2015 00:53

        Вброс засчитан. Чем проиграл?


        1. zw0rk
          11.06.2015 02:16
          +1

          Битвами с digest-loop-ами, чудовищной многословностью, нагромождением концепций (директива, контроллер, шаблон, резолвы и т.п. и т.д.) и всё это сразу. Когда на странице происходит сразу много всего, ангуляр начинает постоянно мешаться, а не помогать.

          p.s. К тому же, у нас cljs и om был естественным решением :)


    1. serf
      10.06.2015 07:12
      -2

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


      1. sferrka
        10.06.2015 07:52
        +3

        React нужен не для скорости, он нужен из-за компонентов. А вот HTML — пережиток прошлого, когда большая часть интерфейса была простым текстом, сейчас же гораздо больше активных элементов на странице, а данные изменяются локально, а не при перезагрузке страницы. Именно поэтому рождаются web-компоненты, именно поэтому Angular 2.0 их содержит. Поэтому шаблоны Angular содержат JS и различные байндинги, отсюда идея JSX (по сути, отказ от HTML). Да, JS тоже слабо подходит в качестве языка разметки, но зато в нем уже есть объекты ({{user.name}}), вызовы функций, математические, логические операции и т.д., которые давно используются во всех шаблонизаторах (т.е. по сути сообщество признало эти вещи декларативными).
        Возможно, когда (или если) HTML разовьется в более полноценный язык разметки интерфейса, с поддержкой наследования, привязки данных и др., JS для этого станет не нужен, но может быть появится и что-то новое, как JSX, только без смешения парадигм и языков.


        1. serf
          10.06.2015 08:14
          -4

          > JSX (по сути, отказ от HTML)
          Повеселили, по сути наоборот наоборот, возврат к спагетти коду (разметка html в коде, php style фейсбук ведь). Тогда уже и древние фреймворки называйте компонентными, там обычно уйма готовы виджетов (подобие компонентов).


          1. Aetet
            10.06.2015 09:43
            +4

            Хотите готовые компоненты вам сюда:
            react-components.com

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

            <div>{{name}}</div>
            

            это нормально, а в реакте использовать все возможности javascript для построения шаблонов плохо.
            Как правило сами шаблоны не переиспользуются, а вот виджеты которые используют эти шаблоны переиспользуются, так зачем же их разделять?


            1. serf
              10.06.2015 09:46
              -5

              > Подскажите мне, пожалуйста, почему разметка в html-коде это плохо?

              Как раз разметка в html коде это не плохо, но там смесь JS и HTML (этот ваш jsx).

              Что только не придумают лишь бы не использовать ангуляр.


              1. wheercool
                10.06.2015 10:24
                +5

                Что только не придумают лишь бы не использовать ангуляр.

                Можно подумать, что ангуляр пуп земли.
                Обычно такое высказывание свидетельствует об ограниченном кругозоре и скорее знакомство автора с reactJs свелось к беглому просмотру примеров на главной странице


                1. serf
                  10.06.2015 10:27
                  -2

                  Разумеется не пуп, но для типовых задач, которых большиснтво ангуляр хорошо подходит. Просто они сейчас в тренде (ангуляр и реакт), при этом реакт неудобный и громоздкий на мой взгляд, не вижу в нем смысла особого. По опыту с реактом верно, продакшен проектов на реакте у меня не было.


        1. tenbits
          10.06.2015 22:45

          Я, например, уже давно html не использую. MaskJS имеет более лаконичный синтаксис, поддерживает декларацию компонент, наследование, merge шаблонов, модули — импорт/экспорт компонент, scope компонент; загрузка данных, скриптов и стилей; друсторонний байндиг, и много всего другого.


  1. vintage
    10.06.2015 09:23
    +2

    Быстрый фреймворк — не тот, на котором можно сделать быстро, а тот, на котором нельзя сделать медленно :-)
    Тут же я вижу описание костылей, которые нужно вставить, чтобы хотя бы догнать реакт.
    Пример с таймаутом я так и не понял. В чём отличие первого кода от второго? Каким образом ручная реализация поведения $timeout поможет увеличить скорость?


    1. andrewiWD
      10.06.2015 09:54

      Быстрый фреймворк — не тот, на котором можно сделать быстро, а тот, на котором нельзя сделать медленно :-)

      Медленно можно сделать не только на любом фреймворке, но и на любом языке программирования.

      Тут же я вижу описание костылей, которые нужно вставить, чтобы хотя бы догнать реакт.

      Т.е. продуманное и правильное написание кода, вы считаете костылями? С каких пор добавление индекса — костыль?!

      Пример с таймаутом я так и не понял. В чём отличие первого кода от второго? Каким образом ручная реализация поведения $timeout поможет увеличить скорость?

      Тут в $digest() фишка. В данном случае биндинг не нужен.


      1. vintage
        10.06.2015 11:12

        Вопрос в том, насколько сложно сделать медленно :-)

        Фреймворк должен упрощать написание кода, а не заставлять заниматься продумыванием каждой мелочи и не проглатывать исключения.

        Где тут биндинг? $timeout всё, что делает — это вызывает отложенно функцию и запускает после этого $digest


        1. born_to_surf Автор
          10.06.2015 14:21

          Тут фишка в том, что $timeout по умолчанию вызывает $apply, который в свою очередь вызывает $digest для рутового скоупа, что приводит к пересчету всех ячеек

          В представленной демо, функция $timeout вызывается для каждой ячейки, поэтому достаточно вызвать $digest только для текущего скоупа


          1. vintage
            10.06.2015 14:30
            -1

            Теперь ясно. Костыль же :-)


    1. youlose
      10.06.2015 16:34
      +2

      Сделать медленно можно без проблем НА ЛЮБОЙ технологии, если знаете где это не так, буду благодарен узнать.


      1. vintage
        10.06.2015 16:50
        +3

        Ок, раз вы всё так буквально понимаете, ответьте, пожалуйста, на пару вопросов:
        1. Как нужно поправить код на реакте, чтобы он стал столь же медленным, что и ангуляр без костылей?
        2. Зачем может потребовать делать именно так?


  1. TedBeer
    10.06.2015 21:37
    -1

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


    1. zw0rk
      11.06.2015 00:31
      +1

      Прелести реакта совсем не в скорости работы скриптов, а в простоте концепции — они не зря всё время цитату Дийкстры про таймлайн приводят, выстрадали.


  1. nomn
    11.06.2015 16:58

    Начало статьи похоже на рекламу вроде «Шок! Всего 2 капли этого и....»


  1. zim32
    13.06.2015 01:24

    Правильно ли я понимаю что Ember со своими очередями и отложенным обновлением DOM это почти то же что и diff в реакте? Может кто-то растолковать?


    1. nuit
      13.06.2015 07:06

      главное преимущество diff/patch'а в том что не нужно реализовывать никакого шаблонизатора и при этом получить immediate mode api с возможностью сохранять внутреннее состояние.

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


      1. zim32
        13.06.2015 12:04

        Ну реакт это сам по себе один сплошной шаблонизатор )