Как стать автором
Обновить

React.js: собираем с нуля изоморфное / универсальное приложение. Часть 3: добавляем авторизацию и обмен данными с API

Время на прочтение17 мин
Количество просмотров61K
Всего голосов 25: ↑22 и ↓3+19
Комментарии37

Комментарии 37

Задаю вопрос повторно:
Объясните, пожалуйста, почему в последнее время стало модно говорить, что DOM тормозит?
Что вы такого с ним делаете? :)

А всякие AngularJS и ReactJS, якобы борясь с DOM тормозами, сами тормозят еще больше :)

Вся эта возня — псевдопрограммирование, когда вместо решения текущей задачи занимаются решением большего количества проблем от ее псевдорешения.

Я, пожалуй, уклонюсь от дискуссии с Вами в этот раз. Вы приглашаете меня попытаться "продать" Вам то, что Вам не нужно, чтобы красиво мне сообщить, что оно Вам в общем-то и не нужно :)


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


Если я не угадал, и этот портрет на Вас не очень похож, то я все же продолжу — ведь это я некоторое время назад. Я смотрел RailsCasts с примерами на Backbone, Angular.JS и т.п. и не понимал, зачем мне дублировать модели в backend и JS, зачем иметь два роутинга, ну и так далее. Если честно, я вообще 5 из 6 лет развития Node.js воспринимал этот стек очень скептически — нет, ну скучно людям, не хотят они кроме JS ничего учить, ладно, но мне тогда это все зачем?


А потом в одном проекте у меня "заболело". Слишком много интерактивности и динамики в интерфейсе — JS код на базе jQuery было очень страшно открывать — не то, что править. И эта не проблема меня, как плохого программиста, просто я использовал не тот инструмент. jQuery и прямая работа с DOM'ом подходит не всем проектам.


Мораль истории такова: если у Вас "не болит" и все хорошо — Вам оно не надо. Но если так случится, что заболит, то надеюсь, что мой цикл окажется Вам полезным. Я сами на практике далеко не везде использую React и Node.js стек, но там где использую — это действительно оправдано

Возможно оно мне и не нужно.

Я просто не понимаю, где же улучшение, а особенно скорости, если все наоборот. :)

>Слишком много интерактивности и динамики в интерфейсе — JS код на базе jQuery было очень страшно открывать — не то, что править.

Это ж не проблема медленного DOM :)
Нужно было просто отрефакторить код на jquery, так как со временем могли действительно навешать кучу событий и все превратилось в мусор.
У меня на проектах тоже достался вермишелеподобный код во некоторых местах.
Но при желании его можно легко отрефакторить и ускорить.

>jQuery и прямая работа с DOM'ом подходит не всем проектам.

А не всегда и нужно работать прямо.
Есть куча оптимизаций. Самые простые:
1. Не дергать 100500 раз $('selector').some_operationsN(), а сохранить $('selector') в переменную и работать с ней.
2. Обновлять DOM не кусочками, а допустим сразу аккумулировать в переменную таблицу и вставить ее в DOM.

У меня тоже бывали тормоза, когда нужно было скрывать/показывать определенные столбцы довольно большой таблицы. Тормоза только в ИЕ (сейчас проверил на меньшем наборе данных (уменьшилось кол-во строк), ИЕ6 не тормозит). Но я не думаю, что React быстрее это сделал бы. :)

Против Node.js ничего не имею, просто не использую.
Это немного другой стиль разработки, более сложный.
Ну и мой весь код на php.
2. Обновлять DOM не кусочками, а допустим сразу аккумулировать в переменную таблицу и вставить ее в DOM.

Собственно это и есть sort of Virtual DOM
То есть вся эта мода расчитана на людей, которые не умеют программировать сами? :)

Таки да.
Большинство знают инструмент поверхностно.
А такие оптимизации нужны крайне редко.

Но при этом зп на фреймворках (особенно модных) выше.
Но программист ни за что не отвечает.
Кивнул в сторону фреймворка и свободен.
Это jquery | DOM | React.js тормозит и свободен.
Печально, что кто-то принимает решение строить приложение на монструозной архитектуре.
Это некомпетентность или что? У меня на прошлой работе начальник хотел, чтобы у него было больше программистов в подчинении, типа он ими руководит и ему положена большая зп. :)

Нельзя все тянуть под одну гребенку.
Универсальный инструмент не даст выигрыш по всем пунктам.
Где-то выиграли, а где-то проиграли.
Нужно с умом использовать текущий инструмент, если есть серое вещество в голове, а не шарахаться с технологии на технологию, потому что так все делают. :)
Перепиши/отрефакторь существующее решение, если с ним есть трудности и будет тебе профит (в подавляющем большинстве случаев, если текущая технология не такой же буллшит :) ).

П.С.
Это касается фреймворков не только JS.
П.П.С.
Я также противник мейнстримовых фреймворков PHP. :)
Неожиданно, читаю все ту нелепицу, что вы пишете в 2016 из 2018 и стало интересно, вы все ещё придерживаетесь этих суждений?

Еще один момент, Вы пишите, что "задаете вопрос повторно", но проблема в том, что я не помню от Вас такого вопроса.


Я открыл все свои статьи и его нигде нет. Оказывается, Вы этот вопрос задавали другому человеку и в другой статье.


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

Действительно, я не Вам задавал вопрос раньше, а в других темах. :)
А сейчас тоже не только Вам.

Просто это не первый мой вопрос, на который не было ответов (правильных) в нескольких темах.

Да, стоило бы в конце первого предложения добавить «всем».
DOM тормозит при больших изменениях в дереве прежде всего. Иногда без них не обойтись, но чаще из-за отсутствия времени/желания делать только минимально необходимые изменения. Библиотеки подобные React решают эту проблему путём автоматического вычисления и применения минимально необходимого набора операций по изменению дерева.
Собственно ответ дан в комментах:
https://habrahabr.ru/post/310952/#comment_9832094
https://habrahabr.ru/post/310952/#comment_9832244

Расчитано, грубо говоря, на дебилов, которые не осилили имеющиеся технологии.
За таких программистов скоро будут толченую картошку жевать. :)

Нужно больше абстрактных фабрик по производству фабрик.
Слова ничто, покажите нам ваш искусный и оптимизированный код. Я серьезно.
А смысл?

Если Вы этого не поняли:
«Есть куча оптимизаций. Самые простые:
1. Не дергать 100500 раз $('selector').some_operationsN(), а сохранить $('selector') в переменную и работать с ней.
2. Обновлять DOM не кусочками, а допустим сразу аккумулировать в переменную таблицу и вставить ее в DOM.»

То я Вам ничем больше не помогу.
> Нужно было просто отрефакторить код на jquery, так как со временем могли действительно навешать кучу событий и все превратилось в мусор.

Интересно было посмотреть, каких размеров ваши проекты, какой сложности UI и как вы боретесь со стейтом.
Нет так нет) Ничто так ничто)
>Интересно было посмотреть, каких размеров ваши проекты

Вы сначала хотели код.
Так вот, какие оптимизации возможны для медленного DOM я сказал, причем 2 раза.
У Вас еще другие проблемы есть?

>какой сложности UI

1. Сложность UI не стоит связывать с тормозами DOM.
2. Очень сложный.
Каша на jquery местами. :)
Рефакторить никто не спешит, рефакторинг проводится частично только при внесении изменений, но не не глобальный рефакторинг.
Задумываются над редизайном (но мне старшие коллеги (уволившиеся еще до того, как я пришел :) ) говорят, что это уже давно :) ).

В личном проекте каши нет, там и кода мало, и логика не сильно сложная.
А также нету тормозов DOM (это очень редкие проекты их имеют, но мыши побежали топиться в озеро под сладкую музыку, что React.js (любой другой) решит все их проблемы).

>и как вы боретесь со стейтом.

1. Что это такое?
2. Оно вряд ли связано с тормозами DOM? :)

Например мы используем реакт не за его оптимизации над DOM. А из-за того, что на нём очень просто описывать мутации состояния интерфейса. Если быть точным — их не надо описывать вообще, просто описываешь один раз как рендерится стейт и меняешь его в процессе жизни приложения. На jQuery все такие мутации надо описывать вручную — типа а вот сейчас надо добавить строку в таблицу, для этого надо взять tr, напихать в него td, и так далее, и сделать добавление в конец tbody. В реакте этого делать не нужно.

Так и на jquery можно писать в таком извращенном стиле :)

Конечно можно — можно на каждый чих целиком рендерить страницу и заменять её. Реакт в общем то делает тоже самое, за одним искчлюением — он не заменяет дом-дерево каждый раз на новое, он его точечно обновляет, за счёт чего в общем то и достигается скорость.


Кстати очень хотелось бы послушать аргументы, почему именно такой стиль является "извращённым".

Это не извращённый стиль, а разделение ответственностей: дело представления, как ни странно, — представить пользователю затрагивающий его в настоящий момент срез состояния приложения и обеспечить вызов мутаций этого состояния пользователем. Не дело представления осуществлять мутации или следить за тем какие конкретно мутации произошли.
На сервере вы используете ES6 при помощи require('babel-core/register'); как это ведет себя в продакшене?

В продакшене ведет нормально. Я ленюсь, по-хорошему надо сделать отдельный конфиг webpack и сделать ES5-сборку для node-окружения.


Я не то, чтобы долго искал, но мне кажется, что эта статья может помочь: http://jlongster.com/Backend-Apps-with-Webpack--Part-I


Надо копать в сторону webpack-конфига с target "node"

В своем boilerplate настроил webpack для работы с под node, но теперь не могу разобраться с CI/CD

Давайте такие вопросы в личку :) Я посмотрел Ваш package.json и .travis.yml и не совсем понял, что Вы хотите получить в итоге. Постараюсь помочь. Единственное — отвечать буду с некоторым latency.

по-хорошему надо сделать отдельный конфиг webpack и сделать ES5-сборку для node-окружения.

А зачем? ведь ES2015 почти полностью поддерживается с Node.
И, даже если у вас стоит старая версия, то разве в этом есть проблема производительности? Ведь транспиляция производится всего один раз при запуске. Если нет, поправьте.

Вы все верно пишите, поэтому я и ленюсь. Node поддерживает многое, но не все. Babel может больше :) Да, трансляция производится только при запуске, но этот шаг занимает определенное время, хоть и в пределах 30 секунд для проектов средних размеров, которые можно "убрать"

Огромное спасибо за статьи.
Только начинаю изучать React, и Ваши статьи очень помогли!

Кстати, а почему в этом случае


case TIME_REQUEST_FINISHED:
      return {
        loading: false,
        errors: null,
        time: action.time
      };

не используется Object.assign({}, state, {...}}, как в TIME_REQUEST_ERROR и TIME_REQUEST_STARTED?

Ну, никто нам не запрещает делать все через Object.assign.


Redux требует, чтобы мы вернули новый объект, а не меняли старый. То есть так писать нельзя:


state.time = action.time

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

Странная печаль, по идее это исправили еще в январе, но у меня вот так вот:
Redux DevTools could not render. Did you forget to include DevTools.instrument() in your store enhancer chain before using createStore()
Все сам разобрался в чем была проблема.
Делаю точно так же всё, но redux-dev-tools не работает.

Ваш проект с guthub просто не запускается
Я разобрался с вашим boilerplate, переделав его под себя. Но сейчас возник вопрос.

В файле server.js вы пишите:

.then(() => store.dispatch(timeRequest()))

То есть на каждый запрос делается timeRequest().

А как сделать, чтобы сервер вытаскивал разные данные в зависимости от URI. Ну то есть пришёл запрос на site.com/news — он вытащил новости. Пришёл запрос на site:com/photos — он вытащил все фотографии.

Мы же не можем каждый URI обрабатывать в файле server.js.

Возможно, я в этом скоро разберусь, но буду рад, если поможете с ответом на этот вопрос.

timeRequest() тут исключительно для Proof of Concept, в статье описано, что в реальной жизни так лучше не делать.


Мы же не можем каждый URI обрабатывать в файле server.js.

React Router. В моем бойлерплейте используется очень старая 2я версия, актуальная 4я гораздо лучше решает эту задачу, и также поддерживает динамический роутинг

Скажите, а в чём разница: писать так —
  <Route path='/' component={App} >
    <IndexRoute component={HelloWorldPage} />
    <Route path='counters'  component={CounterPage} />
    <Route path='time' component={TimePage} onEnter={requireAuth} />
  </Route>

или оборачивать это в
<Router history={browserHistory}>
?
Четвёртая версия react-router просто ужасно непонятная! Отстой!
yury-dymov не могу понять с серверной частью приложения.

Вот смотрите. Чтобы получить какие-то данные при переходе на другой раздел сайта, например на site.com/news, react делает ajax-запрос. В ответе приходят новости, скажем, в json. Но в то время при открытии страницы сразу c site:com/news сервер должен вернуть html с готовыми данными. Без какого либо ajax'а. Эти данные (текст новости, заголовок новости) должны идти в теле http-ответа.

Как это достигается?

Мы же не можем проделывать action'ы во время ренденринга страницы на сервере. Даже если можем, то это тупо выходит. Потому что сам сервер делает ещё дополнительно http-запросы… Хотя сервер должен брать данные прямо из БД.

Вот путаница. Непонятно, как её разрешить. Без SSR таких проблем нет — там всё очень просто. И в сети очень мало информации именно о работе с SSR.
Ответ на ваш вопрос очень прост — это не тот сервер, есть другой))
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории