Главная » Хабрахабр » [Перевод] Разработка React-приложений с использованием ReasonReact

[Перевод] Разработка React-приложений с использованием ReasonReact

Вы применяете React для создания пользовательских интерфейсов? Автор материала, перевод которого мы публикуем, говорит, что он тоже работает с React. Здесь он хочет рассказать о том, почему для написания React-приложений стоит использовать ReasonML.

Можно ли сделать его ещё лучше? React — это очень хороший инструмент для разработки интерфейсов. В частности, проблему, у истоков которой лежит тот факт, что React — это JavaScript-библиотека.
Для того чтобы улучшить работу с React, сначала надо понять его основные проблемы.

React и JavaScript

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

Мутации свойств компонентов или состояния приложения весьма нежелательны, так как подобное может привести к непредсказуемым последствиям. Иммутабельность — это один из базовых принципов React. Структуры данных делают иммутабельными либо придерживаясь неких соглашений, либо используя библиотеки наподобие immutable-js. В JavaScript нет стандартных механизмов для обеспечения иммутабельности.

Хотя в JavaScript имеются некоторые возможности функционального программирования, такие, как функции первого класса, функциональным языком программирования он не является. Библиотека React основана на принципах функционального программирования, так как React-приложения представляют собой композиции функций. Если на JavaScript нужно писать хороший декларативный код, приходится прибегать к сторонним библиотекам вроде Lodash/fp или Ramda.

В React имеется концепция PropTypes. А что не так с системой типов? Для того, чтобы пользоваться в JS выгодами статической типизации, опять же, приходится прибегать к сторонним инструментам, таким, как Flow и TypeScript. Её используют для имитации типов в JavaScript, так как этот язык, сам по себе, не является статически типизированным.

Сравнение React и JavaScript

Как видите, JavaScript не совместим с базовыми принципами React.

Этот язык — ReasonML. Существует ли язык программирования, который лучше JavaScript согласуется с React?
На данный вопрос можно дать положительный ответ.

Так как он основан на OCaml, функциональном языке программирования, соответствующие возможности также оказываются встроенными в Reason. В Reason реализована иммутабельность. В этом языке, кроме того, присутствует собственная система типов, подходящая для React.

Сравнение React, JavaScript и Reason

Получается, что Reason совместим с базовыми принципами React.

Reason

Reason — это не новый язык. Он представляет собой альтернативный, напоминающий JavaScript, синтаксис и набор инструментов для OCaml — функционального языка программирования, который существует уже более 20 лет. Reason был создан разработчиками из Facebook, которые уже использовали OCaml в своих проектах (Flow, Infer).

OCaml

Reason даёт разработчику более качественную, в сравнении с OCaml, документацию, вокруг него сложилось постоянно растущее сообщество энтузиастов. С-подобный синтаксис Reason делает OCaml доступным для программистов, которые знакомы с такими распространёнными языками, как JavaScript или Java. Кроме того, то, что написано на Reason, несложно интегрировать с существующими JS-проектами.

Reason

Reason имеет ту же семантику, что и OCaml, различается лишь синтаксис. Основой Reason является OCaml. В результате в распоряжении программиста оказываются такие замечательные возможности OCaml, как строгая система типов и механизм сопоставления с образцом (pattern matching). Это означает, что Reason даёт возможность писать OCaml-код, используя JavaScript-подобный синтаксис.

Взглянем на фрагмент Reason-кода для того, чтобы ознакомиться с его синтаксисом.

let fizzbuzz = (i) => switch (i mod 3, i mod 5) ;
for (i in 1 to 100) { Js.log(fizzbuzz(i))
};

Хотя в этом фрагменте используется механизм сопоставления с образцом, он остаётся весьма похожим на JavaScript.

Единственным языком, который работает в браузерах, является JavaScript, поэтому, для того, чтобы писать для браузеров на каком бы то ни было языке, нам надо компилировать его в JavaScript.

BuckleScript

Одной из интереснейших возможностей Reason можно назвать компилятор BuckleScript, который берёт код, написанный на Reason и преобразует его в читабельный и производительный JS-код, кроме того, неплохо очищая его от неиспользуемых конструкций.

BuckleScript

Эти люди, по крайней мере, смогут читать результирующий JS-код. Читабельность результатов работы BuckleScript придётся кстати в том случае, если вы работаете в команде, в которой не все знакомы с Reason.

Благодаря такому положению дел можно наслаждаться благами статической типизации Reason и писать код, выглядящий так, будто он написан на JavaScript. Код на Reason иногда так похож на JS-код, что компилятору вовсе не нужно его преобразовывать.

Вот пример кода, который будет работать и в Reason и в JavaScript:

let add = (a, b) => a + b;
add(6, 9);

BuckleScript поставляется с четырьмя библиотеками. Это — стандартная библиотека, называемая Belt (стандартной библиотеки OCaml тут недостаточно), и привязки для JavaScript, Node.js и для API DOM.

Так как BuckleScript основан на компиляторе OCaml, компиляция оказывается очень быстрой — гораздо быстрее чем у Babel и в несколько раз быстрее чем у TypeScript.

Скомпилируем с помощью BuckleScript вышеприведённый фрагмент Reason-кода, содержащий функцию fizzbuzz(), в JavaScript.

Компиляция Reason-кода в JavaScript с помощью BuckleScript

Выглядит он так, как будто написан человеком. Как видите, JS-код оказался вполне читаемым.

В результате, например, можно написать приложение на Reason и запустить его в браузере, на MacOS, на смартфонах, работающих под управлением Android и iOS. Программы, написанные на Reason, компилируются не только в JavaScript, но и в нативный код, и в байт-код. Её можно запускать на всех вышеупомянутых платформах. Существует игра Gravitron, написанная Джаредом Форсайтом на Reason.

Организация взаимодействия с JavaScript

BuckleScript даёт возможность организации взаимодействия Reason и JavaScript. Это означает не только возможность использования рабочего JS-кода в кодовой базе Reason, но и возможность взаимодействия кода, написанного на Reason, с этим JavaScript-кодом. Как результате, код, написанный на Reason, легко поддаётся интеграции в существующие JS-проекты. Более того, в Reason-коде можно использовать JavaScript-пакеты из NPM. Например, можно создать проект, в котором совместно используются Flow, TypeScript и Reason.

Для того чтобы использовать JavaScript-код или библиотеки в Reason, их сначала надо портировать с использованием привязок (биндингов) Reason. Однако всё не так уж и просто. Другими словами, нам, для того, чтобы воспользоваться строгой системой типов Reason, нужны типы для обычного JavaScript-кода.

Проект Redex представляет собой каталог библиотек и инструментов, написанных на Reason и JavaScript-библиотек с Reason-привязками. Если вам нужно воспользоваться какой-нибудь JavaScript-библиотекой в Reason-коде, сначала стоит обратиться к Reason Package Index (Redex) и узнать, была ли эта библиотека уже портирована в Reason. Если вам удалось найти в этом каталоге нужную библиотеку, её можно установить как зависимость и использовать в Reason-приложении.

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

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

ReasonReact

В начале материала мы говорили о том, что он посвящён разработке React-приложений с использованием Reason. Заниматься этим можно благодаря библиотеке ReasonReact.

Однако мы уже обсудили основную причину использования связки React и Reason, которая заключается в том, что React лучше совместим с Reason чем с JavaScript. Возможно, сейчас вы думаете: «Мне всё ещё непонятно — почему надо писать React-приложения на Reason». Всё дело в том, что React был создан в расчёте на Reason, или, точнее, в расчёте на OCaml. Почему это так?

Путь к ReasonReact

Первый прототип React был разработан Facebook и был написан на Standard Meta Language (StandardML), на языке, который является родственником OCaml. Затем React перевели на OCaml, кроме того, React перенесли на JavaScript. Сделано это было из-за того, что весь веб использовал JavaScript и, вероятно, неразумным было бы делать заявления вроде: «А теперь мы будем писать UI на OCaml». Перевод React на JavaScript себя оправдал и привёл к широкому распространению этой библиотеки.

React, а также другие библиотеки и языки, такие как Elm, Redux, Recompose, Ramda, и PureScript, способствовали популяризации функционального стиля программирования в JavaScript. Как результат, все привыкли воспринимать React в виде JS-библиотеки. В итоге парадигма функционального программирования с использованием статических типов стала главенствующей в мире разработки фронтенда. А благодаря распространению Flow и TypeScript в JavaScript стала популярна и статическая типизация.

Это позволило им писать более качественный и безопасный фронтенд-код, используя строгую систему типов OCaml. В 2006 году компания Bloomberg создала и перевела в разряд опенсорсных проектов компилятор BuckleScript, который преобразует OCaml в JavaScript. Они взяли оптимизированный и очень быстрый компилятор OCaml и заставили его генерировать код на JavaScript.

Популярность функционального программирования и выпуск BuckleScript создали идеальный климат, который позволил Facebook вернуться к исходной идее React — библиотеки, которая изначальна была написана на StandardML.

ReasonReact

Кроме того, они создали Reason-обёртку для React, представленную в виде библиотеки ReasonReact, которая обладает дополнительными функциями, такими, как инкапсуляция принципов Redux в компонентах с состоянием. Они смешали семантику OCaml с синтаксисом JavaScript и создали Reason. Сделав это, они вернули React к его истокам.

О возможностях React в Reason

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

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

Зависимости типичного React-приложения

Вот какие задачи решают эти зависимости:

  • Статическая типизация — Flow/TypeScript.
  • Иммутабельность — ImmutableJS.
  • Маршрутизация — ReactRouter.
  • Форматирование кода — Prettier.
  • Линтинг — ESLint.
  • Вспомогательные функции — Ramda/Lodash.

Теперь воспользуемся, вместо React для JavaScript, библиотекой ReasonReact. Нужны ли нам, при таком подходе, все эти зависимости?

Переход на ReasonReact

Подробности о них вы можете почитать здесь. Проанализировав тот же список задач, которые раньше решались с помощью дополнительных средств, мы выясним, что все их можно решить с помощью встроенных средств ReasonReact.

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

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

Что дальше?

Если вы родом из мира JavaScript, вам будет несложно начать работу с Reason благодаря тому, что синтаксис этого языка похож на JavaScript. Если вы раньше писали React-приложения, перейти на Reason вам будет ещё легче, так как вы можете, при работе с ReasonReact использовать все свои познания в области React. В основе ReasonReact лежит та же модель мышления, что и в основе React, процесс работы с ними так же очень схож. Это означает, что при переходе на Reason вам не придётся начинать с нуля. Вы разберётесь с Reason в процессе работы.

Как уже было сказано, Reason-код можно использовать в JS-проектах, равно как и JS-код в Reason-проектах. Лучший способ начать использовать Reason в своих проектах заключается в том, чтобы постепенно вводить в них фрагменты, написанные на Reason. Можно взять ReasonReact-компонент и использовать его в традиционном React-приложении, написанном на JavaScript. Этот подход применим и при использовании ReasonReact.

Именно такой вот инкрементальный подход был выбран разработчиками Facebook, которые широко использовали Reason при разработке мессенджера Facebook.

Если вы хотите написать React-приложение с использованием Reason и на практике изучить основы этого языка, взгляните на этот материал, где пошагово разбирается разработка игры «Крестики-нолики».

Итоги

У создателей Reason было два варианта действий. Первый заключался в том, чтобы взять JavaScript и как-то его улучшить. Если бы они избрали этот путь — им пришлось бы иметь дело с историческими недостатками JS.

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

Именно поэтому писать React-приложения гораздо легче и приятнее с использованием Reason. React тоже основан на принципах OCaml. Работа с React в Reason предлагает более стабильный и безопасный подход к созданию React-компонентов, так как строгая система типов страхует разработчика и ему не приходится сталкиваться с большинством исторических проблем JavaScript.

Уважаемые читатели! А вы пробовали ReasonReact?


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

Маленькие создания, большие деяния: роль листорезов в парниковом эффекте неотропики

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

[Перевод] JavaScript: вопросы и ответы

Недавно в компании SmartSpate решили собрать вопросы, касающиеся JavaScript, и на них ответить. В материале, перевод которого мы публикуем, приведены чуть больше двух десятков вопросов о JavaScript и ответов на них. Спектр затрагиваемых здесь тем достаточно широк. В частности — ...