Статьи

Почему я перехожу с React на Cycle.js

Почему я перехожу на Cycle.js - велосипедисты на велосипедах

Я предполагаю, что большинство разработчиков в наши дни используют какую-то платформу для разработки приложений. Фреймворки помогают нам структурировать сложные приложения и экономят наше время. Каждый день мы видим много дискуссий о том, какой фреймворк лучший, какой фреймворк вы должны изучить в первую очередь и т. Д. Итак, сегодня я хотел бы поделиться своим опытом и почему я перехожу на Cycle.js из React.

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

Большинство людей начинают использовать React, не задумываясь о том, что может быть лучший способ создания веб-приложения. Это размышление заставило меня попробовать Cycle.js, новую реактивную среду, которая становится все более популярной с каждым днем. В этой статье я хочу объяснить, что такое реактивное программирование, как работает Cycle.js и почему я думаю, что оно лучше, чем React. Итак, начнем!

Что такое реактивное программирование?

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

Вы, вероятно, думаете: «Зачем мне эта новая штука с реактивным программированием?» Ответ прост: Реактивное программирование поможет вам унифицировать ваш код и сделать его более согласованным. Вам не нужно думать о том, как все должно работать и как правильно их реализовать. Просто напишите код одинаково, независимо от того, над какими данными вы работаете (события кликов, HTTP-вызовы, веб-сокеты …). Все является потоком данных, и у каждого потока есть много функций, которые вы можете использовать для работы с ним, таких как map и filter . Эти функции будут возвращать новые потоки, которые можно использовать, и так далее.

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

реактивные щелкает
Изображение взято с https://gist.github.com/staltz/868e7e9bc2a7b8c1f754

Реактивное программирование в JavaScript

В JavaScript у нас есть несколько замечательных библиотек для работы с потоками данных. Наиболее известным из них является RxJS . Это расширение ReactiveX , API для асинхронного программирования с наблюдаемыми потоками. Вы можете создать Observable (поток данных) и управлять им с помощью различных функций.

Второй — Most.js. Он имеет лучшую производительность, и они могут доказать это несколькими цифрами: Сравнение производительности .

Я также хотел бы упомянуть одну маленькую и быструю библиотеку, созданную создателем Cycle.js и созданную специально для нее. Это называется xstream . В нем всего 26 методов, он занимает примерно 30 КБ и является одной из самых быстрых библиотек для реактивного программирования в JS.

В приведенных ниже примерах я буду использовать библиотеку xstream . Cycle.js сделан как небольшая структура, и я хочу прикрепить к нему наименьшую реактивную библиотеку.

Что такое Cycle.js?

Cycle.js — это функциональный и реактивный JavaScript-фреймворк. Он абстрагирует ваше приложение как чистую функцию main() . В функциональном программировании функции должны иметь только входы и выходы без каких-либо побочных эффектов. В функции main() Cycle.js входы — это эффекты чтения (источники) из внешнего мира, а выходы (приемники) — эффекты записи во внешний мир. Управление побочными эффектами осуществляется с помощью драйверов. Драйверы — это плагины, которые обрабатывают DOM-эффекты, HTTP-эффекты, веб-сокеты и т. Д.

Cycle.js
Изображение взято с сайта Cycle.js

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

Базовый API имеет только одну функцию run .

 run(app, drivers); 

У него есть два аргумента: app и drivers . app является основной чистой функцией, а drivers — это плагины, которые должны обрабатывать побочные эффекты.

Cycle.js разделяет дополнительную функциональность на более мелкие модули. Они есть:

  • @ cycle / dom — коллекция драйверов, работающих с DOM; он имеет драйвер DOM и драйвер HTML, основанный на виртуальной библиотеке DOM snabdom
  • @ cycle / history — драйвер для History API
  • @ cycle / http — драйвер для HTTP-запросов на основе суперагента
  • @ cycle / isolate — функция для создания компонентов потока данных в определенной области
  • @ cycle / jsonp — драйвер для выполнения HTTP-запросов через JSONP
  • @ cycle / most-run — функция run для приложений, созданных с
  • @ cycle / run — функция run для приложений, созданных с помощью xstream
  • @ cycle / rxjs-run — функция run для приложений, созданных с помощью rxjs

Код Cycle.js

Давайте посмотрим код Cycle.js? Мы создадим простое приложение, которое должно продемонстрировать, как оно работает. Я думаю, что старое доброе приложение счетчика должно быть идеальным для этого примера. Мы увидим, как обработка событий DOM и повторная отрисовка DOM работает в Cycle.js.

Давайте создадим два файла, index.html и main.js index.html будет просто обслуживать наш файл main.js , где будет находиться вся наша логика. Мы также собираемся создать новый файл package.json, поэтому запустите:

 npm init -y 

Далее давайте установим наши основные зависимости:

 npm install @cycle/dom @cycle/run xstream --save 

Это установит @cycle/dom , @cycle/xstream-run и xstream . Нам также понадобятся babel , browserify и mkdirp поэтому давайте установим их:

 npm install babel-cli babel-preset-es2015 babel-register babelify browserify mkdirp --save-dev 

Для работы с Babel создайте файл .babelrc со следующим содержимым:

 { "presets": ["es2015"] } 

Нам также нужно добавить сценарии в наш package.json для запуска нашего приложения:

 "scripts": { "prebrowserify": "mkdirp dist", "browserify": "browserify main.js -t babelify --outfile dist/main.js", "start": "npm install && npm run browserify && echo 'OPEN index.html IN YOUR BROWSER'" } 

Для запуска нашего приложения Cycle.js мы будем использовать npm run start .

Это все. Наша настройка завершена, и мы можем начать писать некоторый код. Давайте добавим немного HTML-кода в index.html :

 < !DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"/> <title>Cycle.js counter</title> </head> <body> <div id="main"></div> <script src="./dist/main.js"></script> </body> </html> 

Мы создали div с идентификатором main . Cycle.js подключится к этому div и отобразит все приложение в нем. Мы также включили файл dist/main.js Это перенесенный и связанный JS-файл, который будет создан из main.js

Пришло время написать код Cycle.js. Откройте файл main.js и импортируйте все необходимые нам зависимости:

 import xs from 'xstream'; import { run } from '@cycle/run'; import { div, button, p, makeDOMDriver } from '@cycle/dom'; 

Мы xstream , run , makeDOMDriver и функции, которые помогут нам работать с Virtual DOM ( div , button и p ).

Давайте напишем нашу main функцию. Это должно выглядеть так:

 function main(sources) { const action$ = xs.merge( sources.DOM.select('.decrement').events('click').map(ev => -1), sources.DOM.select('.increment').events('click').map(ev => +1) ); const count$ = action$.fold((acc, x) => acc + x, 0); const vdom$ = count$.map(count => div([ button('.decrement', 'Decrement'), button('.increment', 'Increment'), p('Counter: ' + count) ]) ); return { DOM: vdom$, }; } run(main, { DOM: makeDOMDriver('#main') }); 

Это наша main функция. Он получает sources и возвращает sinks . Источниками являются потоки DOM, а приемниками — виртуальный DOM. Давайте начнем с объяснения по частям.

 const action$ = xs.merge( sources.DOM.select('.decrement').events('click').map(ev => -1), sources.DOM.select('.increment').events('click').map(ev => +1) ); 

Здесь мы объединяем два потока в один поток, называемый action$ (условно суффиксить имя переменных, которые содержат потоки с $ ). Один — это поток кликов по decrement а другой — по кнопке increment . Мы сопоставляем эти два события с числами -1 и +1 соответственно. В конце слияния action$ stream должно выглядеть так:

 ----(-1)-----(+1)------(-1)------(-1)------ 

Следующий поток — count$ . Он создан так:

 const count$ = action$.fold((acc, x) => acc + x, 0); 

Функция fold отлично подходит для этой цели. Он принимает два аргумента: accumulate и seed . seed сначала испускается, пока не наступит событие. Следующее событие объединяется с seed числом на основе функции accumulate . Это в основном, reduce() для потоков.

Наш count$ stream получает 0 в качестве начального значения, затем для каждого нового значения из action$ stream мы суммируем его с текущим значением в count$ stream.

В конце, чтобы весь круг заработал, нам нужно вызвать функцию run ниже main .

Последнее, что нужно создать виртуальный DOM. Вот код, который делает это:

 const vdom$ = count$.map(count => div([ button('.decrement', 'Decrement'), button('.increment', 'Increment'), p('Counter: ' + count) ]) ); 

Мы отображаем данные в count$ stream и возвращаем виртуальный DOM для каждого элемента в потоке. Виртуальный DOM содержит одну основную оболочку div, две кнопки и абзац. Как видите, Cycle.js использует функции JavaScript для работы с DOM, но JSX также может быть реализован .

В конце main функции мы возвращаем наш Virtual DOM:

 return { DOM: vdom$, }; 

Мы передаем нашу main функцию и драйвер DOM, который подключен к div с идентификатором main и получаем поток событий из этого div. Мы закрываем наш круг и делаем идеальное приложение Cycle.js.

Вот как это работает:

Анимированный GIF демонстрирует увеличение и уменьшение счетчика

Это оно! Вот как вы работаете с потоками DOM. Если вы хотите увидеть, как HTTP-потоки работают в Cycle.js, я написал об этом статью (в своем блоге) [http://ivanjov.com/working-with-http-streams-with-cycle-js/]

Я отправил весь код в репозиторий Github . Проверьте это и попробуйте запустить его на локальном компьютере.

Почему я переключаюсь с React на Cycle.js?

Теперь, когда вы понимаете основные концепции реактивного программирования и видите простой пример в Cycle.js, давайте поговорим о том, почему я буду использовать его для моего следующего проекта.

Самая большая проблема, с которой я столкнулся при разработке веб-приложений, заключается в том, как обрабатывать большие кодовые базы и большие объемы данных, поступающих из разных источников. Я фанат React и использовал его во многих проектах, но React не решил мои проблемы.

Когда дело доходит до рендеринга некоторых данных и изменения состояния приложения, React работает очень хорошо. Фактически, методология всего компонента удивительна, и она действительно помогла мне написать лучший, тестируемый и обслуживаемый код. Но чего-то там всегда не хватало.

Давайте посмотрим некоторые плюсы и минусы использования Cycle.js над React.

Pros

1. Большие кодовые базы

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

Cycle.js помогает нам здесь. Он предназначен для обработки больших кодовых баз путем разделения проекта на независимые компоненты, которые могут быть изолированы и протестированы без побочных эффектов. Нет Redux, нет побочных эффектов, все это чистый поток данных.

2. Поток данных

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

С Cycle.js создатель хотел создать среду, которая будет заботиться о потоке данных, потому что вам не нужно об этом думать. Вам просто нужно написать функции, которые выполняют некоторые операции с данными, а Cycle.js будет обрабатывать все остальное.

3. Побочные эффекты

У React есть проблемы с обработкой побочных эффектов. В приложениях React не существует стандартного способа работы с побочными эффектами. Есть много инструментов, которые помогут вам справиться с этим, но это также займет некоторое время, чтобы настроить и научиться их использовать. Наиболее популярными из них являются « Редукс-сага» , « Редукс-эффекты» , « Редукс-побочные эффекты» и « Редукс-петля» . Вы понимаете, о чем я? Их много … Вам нужно выбрать библиотеку и реализовать ее в своей кодовой базе.

Cycle.js этого не требует. Просто включите нужный драйвер (DOM, HTTP или другой) и используйте его. Драйвер отправит данные в вашу чистую функцию, вы можете изменить их и отправить обратно драйверу, который будет обрабатывать их или делать что-то еще. Самое главное, это стандартизировано; это то, что поставляется с Cycle.js, и вам не нужно зависеть от сторонней библиотеки. Так просто!

4. Функциональное программирование

И последнее, но не менее важное, функциональное программирование. Создатели React утверждают, что React использует функциональное программирование, но это не совсем так. Существует множество ООП, классов, использование ключевого слова this которое может вызвать головную боль, если не используется должным образом … Cycle.js построен с учетом парадигмы функционального программирования. Все это функция, которая не зависит от какого-либо внешнего состояния. Кроме того, нет никаких классов или что-то подобное. Это проще для тестирования и обслуживания.

Cons

1. Сообщество

В настоящее время React является самым популярным фреймворком и используется повсеместно. Cycle.js нет. Это все еще не очень популярно, и это может быть проблемой, когда вы сталкиваетесь с незапланированной ситуацией и не можете найти решение проблемы в своем коде. Иногда вы не можете найти ответ в Интернете, и вы остаетесь один. Это не проблема, когда вы работаете над каким-то сторонним проектом и у вас много свободного времени, но что происходит, когда вы работаете в компании с жестким сроком? Вы потеряете время на отладку своего кода.

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

2. Изучение новой парадигмы

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

3. Некоторые приложения не должны быть реактивными

Да, некоторые приложения действительно не должны быть реактивными. Блоги, маркетинговые сайты, целевые страницы и другие статические сайты с ограниченной интерактивностью не должны реагировать. Нет данных, которые проходят через приложение в режиме реального времени, не так много форм и кнопок. Использование реактивной структуры, вероятно, замедлит нас на этих сайтах. Вы должны быть в состоянии оценить, действительно ли веб-приложение должно использовать Cycle.js.

Вывод

Идеальная структура должна помочь вам сосредоточиться на создании и предоставлении функций и не должна заставлять вас писать шаблонный код. Я думаю, что Cycle.js показал нам, что это действительно возможно, и заставляет нас искать лучшие способы написания нашего кода и предоставления функций. Но помните, что нет ничего идеального, и всегда есть возможности для улучшения.

Вы пробовали реактивное программирование или Cycle.js? Я убедил вас попробовать? Дайте мне знать, что вы думаете в комментариях!

Эта статья была рецензирована Майклом Ванёйке . Спасибо всем рецензентам SitePoint за то, что сделали контент SitePoint как можно лучше!