О бравом React'е замолвите слово

Здравствуйте, уважаемые читатели!

Спешим вас порадовать — мы уже вовсю переводим книгу небезызвестного Стояна Стефанова о библиотеке React

dae9b42d584746abb6d0d6c831dbc077.jpg

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

React уже стал одним из самых перспективных протагонистов среди фреймворков JavaScript. Этот инструмент прост и удобен в работе, но, тем не менее, исключительно сложно четко сформулировать его достоинства, доказывая целесообразность React как такового. Даже сами авторы проекта признавали, что, приступая к его разработке, не вполне могли ответить на такие вопросы.

Два основных возражения в пику React таковы:

  1. Его неполнота — React не является «полностековым» фреймворском в отличие от Meteor или Angular. В нем нет маршрутизатора, системы моделей и многих других возможностей, которые положено иметь фреймворку. Говорят, что он реализует всего лишь «V» из MVC, но это далеко не так, о чем я и собираюсь поговорить.
  2. Его синтаксис — здесь смешаны HTML и Javascript. Программист смотрит на JSX и вопрошает: «но… зачем?». А некоторые даже выступают за подмешивание CSS.

Я постараюсь осветить обе эти проблемы, а также заострю внимание на некоторых сильных сторонах React. Итак, поехали!

Итак, что же такое React?

React — это javascript-библиотека для создания компонентов. Каждый компонент обладает «внешним видом», который задается методом render и некоторыми состояниями, определяемыми в getInitialState. Внешний вид зависит от текущего состояния. Вот, в сущности, и все. И вот почему бывает так сложно объяснить React — у многих он вызывает именно такое ощущение «неполноты».

Пример:

Counter = React.createClass
  getInitialState: ->
    count: 0
  
  increment: ->
    @setState(count: @state.count + 1)

  render: ->
    
{ @state.count }

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

Метод setState вновь отображает компонент. Это делается настолько оригинально, что именно в этом React и его клоны отличаются от аналогичных инструментов. В сущности, React хранит в памяти объектную модель документа, именуемую «виртуальной DOM» («теневая DOM» — немного другой феномен), а затем вычисляет разницу между этой DOM и той, что отображена в браузере. На основании этой разницы составляется список изменений, которые необходимо внести — представьте себе createElement –, а затем эти изменения применяются.
Разумеется, в React придется познакомиться и со многими другими концепциями —например, свойства (props), различные атрибуты тегов –, но наиболее важна именно DOM.

В чем упрекают React

Неполнота. Плохо или хорошо?

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

Насколько мне известно, первой из альтернатив стал Camping от Why — микрофреймворк, состоявший из считанных строк кода. За ним последовали Sinatra, CherryPy, Flask, Express и многие другие. Но дело в том, что все они продолжают эмулировать концепцию фреймворка, просто получаются немного тоньше, а также написаны менее предвзято. А продаются эти инструменты благодаря тому, что с ними не так много возни и, соответственно, они более удобны для разработки сравнительно мелких приложений.

Та неполнота, которой отличается React, принципиально иная. React — не просто облегченный Angular, а нечто принципиально иное. Он очень хорошо справляется с конкретной задачей: работает с веб-компонентами. Итак, неверно рассуждать о том, какого размера должен быть наш проект. Кстати, React делался с упором на производительность, именно на нем работает система комментариев в Facebook — следовательно, он вне всяких сомнений способен работать в колоссальных масштабах.

Вот о чем стоит задуматься:, а нужен ли вам полновесный фреймворк и, кроме того, сможете ли вы организовать все необходимые компоненты на базе React. Во-первых, следует отметить, что размер машинного интерфейса, в сущности, не важен. Если вам приходится загружать фреймворк размером 1ГБ, но на выходе получается гибкое и быстрое приложение, то это не проблема. С другой стороны, размер фронтенда очень важен. Любая дополнительная нагрузка от вашего фреймворка сразу повлияет на конечный результат.

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

Правда ли, что React — всего лишь V из аббревиатуры MVC?

Как отмечает Андрэ Медейрос в своей великолепной презентации, возможности React далеко не ограничиваются V. Дело в том, что у компонентов React есть состояние, поэтому такой компонент — в некотором смысле Модель. Он обеспечивает отображение ввода на изменение состояния, поэтому, в то же время, имеет черты Контроллера, или даже Представления, подчеркивает Медейрос. Компонент также обменивается информацией с другими компонентами и зависит от них. Итак, вам не придется искать подходящие библиотеки для модели и контроллера — подобное мнение попросту ошибочно.

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

Медейрос предлагает решать эти проблемы, взяв на вооружение принцип MVI — Модель-Вид-Намерение — то есть, пропагандирует довольно своеобразный подход к веб-разработке. Одна из реализаций этого подхода называется Цикл.

Зачем смешивать HTML и JS? …Что? И CSS тоже???

Десять лет назад в веб-разработке была своя священная корова — разделение HTML, JS и CSS. Все три технологии должны были существовать сами по себе, в отдельных файлах и каталогах. Эти файлы могли только ссылаться друг на друга, что делалось при помощи включений.

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

Все это может вызывать отторжение, которое, на мой взгляд, объясняется чистейшими необоснованными предрассудками. Всего через несколько часов привыкаешь. Все мнения о React, которые я нашел в Интернете, в сущности, одинаковые. Вдруг избавляешься от необходимости держать два открытых файла в соседних вкладках — и продуктивность работы резко возрастает.
Некоторые даже выступают за то, чтобы полностью перенести CSS в область компонента. Прежде, чем клеймить меня, посмотрите интересную презентацию на эту тему от Кристофера Чедау.

Аргументы в защиту React

Здесь есть экосистема

Я пишу эту статью, а React только что обошел Ember по рейтингу на GitHub. Он уступает Backbone и, естественно, Angular, но растет гораздо быстрее «конкурентов».

React — это проект Facebook, именно на нем реализована система комментирования в Facebook и большинство проектов этой компании. Кроме того, React широко применяется в Pinterest, AirBnB, Khan Academy и на массе других стартапов. На основе React выстроен редактор Atom, более того, и Microsoft поддерживает React.

Тем самым я пытаюсь доказать, что React — уже мейнстрим, насколько вообще можно говорить о мейнстриме в технологическом ландшафте инструментов JavaScript. Это означает, что вам не придется особо беспокоиться о поддержке проекта, о том, обрастет ли он экосистемой. Уже можно убедиться, что существует туча библиотек для React — хотя, пока мне и сложно судить об их качестве.

Проще судить о коде

Один из основных аргументов в пользу React связан с его логичностью. Это предельно верное утверждение, и нельзя недооценивать его весомость и важность.

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

Интересная вещь: задумываясь о качестве программы, нужно обращать внимание не только на количество багов — у нас в Agile вообще проповедуется идея, что «никаких багов быть не должно» —, но и на то, сколько времени потребуется на устранение бага. Усвоив эту идею, я вспомнил баг, который удалось изжить только через год. Он учинял чудовищные утечки памяти и значительно тормозил всю программу, особенно при пиковых нагрузках. Если исходить лишь из количества багов, то, вполне возможно, у вас будет всего горстка таких изъянов, но само решение при этом все равно окажется очень плохим.

Итак, длительность устранения бага свидетельствует о том, сложно ли судить о коде. Если на устранение бага уходит много времени, это означает, что разработчикам приходится изрядно покорпеть над проблемой, прежде, чем она обнаружится — и наоборот.
React упрощает рассуждение о коде, причем сразу по нескольким причинам. Основная –DOM без сохранения состояния. Для примера рассмотрим, как в традиционной jQuery реализуется переключение:

// html
HERE I AM
// coffescript $('.toggler').on 'click', -> $('.toggled').toggle()

На первый взгляд, все просто. Но вот в чем загвоздка:, а как вы узнаете, отобразился ли div? Да, можно сказать: «Если нажать на кнопку button любое четное количество раз, то он отобразится, а если нет — не отобразится».

Toggler = React.createClass
  getInitialState: ->
    visible: true
  
  toggle: ->
    @setState(visible: !@state.visible)
    
  render: ->
    
{ @state.visible &&
HERE I AM
}

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

Переиспользование

Это волшебное слово. В мире бэкенда переиспользование фрагментов кода — реальность. Речь может идти, например, о самоцветах или яйцах. Но в клиентской части может показаться, что для каждого нового проекта все приходится пересобирать заново. Действительно, такие вещи, как инструмент обхода DOM или URL-парсер переиспользовать легко, но когда дело доходит до контента как такового, каждый проект начинает выглядеть по-своему, а каждый элемент макета — сама оригинальность, которая не лезет «под одну гребенку».

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

Было бы интересно увидеть многократное использование одних и тех же разработок в разных компаниях, посмотреть, как люди будут писать свободные библиотеки с реализованными компонентами. Хороший пример — MaterialUI.

Выращивание проекта

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

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

ed557c7361f0428fb486dd6055b95f80.png

Комментарии (0)

© Habrahabr.ru