Нетрадиційний огляд React

Привіт, Хабр!

Ми в Хекслете любимо свій стек технологій :) Коли розповідаємо іншим   багато заздрять: Rails, Docker, AWS, React JS. Реактив ми використовуємо в першу чергу для створення веб-середовища для розробки Hexlet-IDE, яка дозволяє нашим користувачам виконувати вправу по розробці програм і взаємодії з віртуальною машиною прямо в браузері.

Сьогодні ми публікуємо переклад статті «An Unconventional Review of React» Джеймса Шора, ведучого проекту let's Code: Test-Driven JavaScript.



Він мені сподобався. Я не очікував такого.

Для спеціальних випусків let's Code JavaScript серпні і вересні я вивчав Реактив.

На випадок якщо вам не знаком Реактив: це бібліотека для фронт-енд веб-розробки. З допомогою нього створюються компоненти: короткі, не-зовсім-ХТМЛ-теги, які можна комбінувати для створення інтерфейсу.

Реактив знаменитий своїми нетрадиційними рішеннями: реалізацією віртуального DOM'а, створенням елементів інтерфейсу на JavaScript замість шаблонів, створення суперсета мови JavaScript   JSX, який дозволяє вставляти не-зовсім-ХТМЛ прямо в код JS.

З цими рішеннями розробка йде від схеми маніпуляції DOM'ом   додати цей елемент, приховати ефектом інший елемент, оновити це текстове поле. Замість цього ви описуєте як зараз повинен виглядати DOM. Реактив бере на себе складну роботу по визначення необхідних дій щоб DOM насправді став виглядати так, як ви сказали.

Наприклад, в коді який я написав для огляду є таблиця, яка повинна мінятися кожен раз коли змінюються поля конфігурації. Можна подумати що код буде сповнений страшної логіки маніпуляції DOM, але на насправді ніякого коду для маніпуляції немає взагалі. Ось :

/** @jsx React.DOM */
// Copyright © 2014 Titanium I. T. LLC. All rights reserved. For license, see "README" або "LICENSE" file.
"use strict";

var StockMarketTableCell = require("./stock_market_table_cell.js");

var StockMarketTableRow = module.exports = React.createClass({
render: function render() {
var year = this.props.stockMarketYear;

return <tr>
<StockMarketTableCell value={year.year()} />
<StockMarketTableCell value={year.startingBalance()} />
<StockMarketTableCell value={year.startingCostBasis()} />
<StockMarketTableCell value={year.totalSellOrders().flipSign()} />
<StockMarketTableCell value={year.capitalGainsTaxIncurred().flipSign()} />
<StockMarketTableCell value={year.growth()} />
<StockMarketTableCell value={year.endingBalance()} />
</tr>;
}
});

У цьому суть Реакта, і цим він відрізняється від інших. Єдине питання: хороший він?

Критерії нетрадиційного огляду

Зазвичай, коли ви читаєте огляд фронт-енд фреймворку або бібліотеки, ви дізнаєтеся про його розмір, або про те, які знамениті люди і компанії використовують його, або про його продуктивності. Так, все це важливо. Але найважливіше питання для мене звучить простіше:

 протягом наступних 5-10+ років, коли я буду підтримувати свій продукт, цей код принесе більше користі чи страждань?

Не так важливо скільки часу бібліотека заощадить мені при початковій розробці. О, ні. Набагато важливіше вартість підтримки в протягом життя мого додатка.

Для цього у мене є п'ять критеріїв.

1. Замкнутість (Lock-in). Коли я вирішу перейти на новий або більш кращий фреймворк (або бібліотеки), наскільки складно буде переключитися?

2. Уперта архітектура (Opinionated Architecture). Можу я розв'язувати задачі так, як потрібно моєму додатком, або я повинен коритися певним ідеям, розробленим авторами фреймворку?

3. Побічна складність (Accidental Complexity). Я витрачаю час на рішення своєї проблеми або борюся з фреймворком?

4. Тестування (Testability). Можу я просто тестувати свій код, без зайвої мороки з mock-об'єктами?

5. Сумісність з пошуковими движками (Search Engine Compatibility). Доведеться чи танцювати з бубном, щоб змусити пошуковики індексувати мій сайт?

Я оцінив Реактив у кожної категорії з допомогою a ☺ (ніііт!), ☹ (буеее!), or ⚇ (ні туди, ні сюди).

1. Замкнутість   ⚇ (ні туди, ні сюди)

Давайте начистоту: коли ви вирішите попрощатися з Реактом, вам доведеться переписувати інтерфейс з нуля. Немає нормального способу приховати Реактив за шаром абстракції, і код Реактив-інтерфейсу не схожий ні на що інше. Так що все досить замкнуто.

Але чому Реактив не отримав сумну пику?

Два моменту рятують Реактив. По-перше, Реактив провокує поміщати логіку програми поза UI, так що не доведеться переписувати усі додаток.

По-друге, API Реакта відносно невелике. Не так багато точок дотику (див. пункт 3). Це означає, що менша ймовірність зламати що-то при оновленні Реакта. Також, Реактив легко використовувати ізольовано, для окремої частини сторінки, так що можна поступово мігрувати з Реакта коли з'явиться необхідність.

2.Уперта архітектура   ☺ (ніііт!)

Реактив це бібліотека, а не фреймворк, і це помітно. Реактив не диктує архітектуру програми. У мене не було ніяких проблем з підключення мого існуючого і завідомо дивного коду до Реакту.

Деякі люди вважають вперту архітектуру доброю ознакою. «Це дозволяє мені зрозуміти як структурувати код». Я волію зворотне. Структура програми повинна диктуватися вимогами додатка. Фреймворк не може передбачити ці вимоги, і вони будуть змінюватися з розвитком програми.

Реактив містить архітектурний патерн під назвою Flux, але він повністю опційний. Це просто спосіб розмірковувати про структурі коду, а не вбудований у Реактив механізм. Так і повинно бути.

3. Побічна складність   ⚇ (ні туди, ні сюди)

Про Реакте необхідно знати дуже мало, і він мені видався простим і зрозумілим. Є лише пара моментів (різниця між «props» і «state»), лише пара концепцій (як керувати станом; иммутабельные рендер-методи) і кілька методів для реалізації типового компонента. Мій самий складний компонент містить аж три Реактив-методу. У більшості випадків вистачає одного render().

Ложка дьогтю це віртуальний DOM. Це вражаюче досягнення, ключова штука в Реакте… але він може виявитися дірявий абстракцією. Як тільки ви бачите нову або просунуту фічу DOM, ви ризикуєте напоротися на бійку з Реактом. Наприклад, CSS-анімації деякий час викликали проблеми, і управління фокусом все ще шаліт.

Зараз, здається, команда Реакта встигає все правити. Але що буде через п'ять або десять років, коли Реактив вже не сама модна штука? Браузера продовжують розвиватися, і перед тим як вибрати Реактив для свого проекту, запитайте себе: впевнений я, що Реактив буде встигати за усіма нововведеннями, необхідними мою додатком?

4. Тестування   ☺ (ніііт!)

Історія з тестуванням Реакта виглядає трохи незрілої. Вона ледве-ледве дотягла до усміхненої пики.

На перший погляд Реактив дає простий API для тестування, і здається, там є все що потрібно. Можна рендери компонент і шукати в дереві DOM допомогою гарного набору функцій. Можна симулювати події. Можна робити mock-компоненти, але я був задоволений тим, що вони мені ні разу не знадобилися.

Документації не дуже багато, не вистачає прикладів і рекомендацій по дизайну, особливо якщо порівняти з іншими частинами документації Реакта. Це тільки підтримує відчуття незрілості. Але головна проблема в те, що я не зміг знайти способу порівнювати компоненти. Навіть у порівняно простому додатку, ваші компоненти будуть містити компоненти, і  не хочете щоб тести знали щось про деталях реалізації додаткових компонентів.

Наприклад, компонент ApplicationUi містить компонент StockMarketTable. Я хочу перевірити оновлюється чи таблиця при зміні конфігурації. Для цього я хотів перевірити таблицю з готовим хард-кодом:

it("updates stock market table when user configuration changes", function() {
config.setStartingBalance(...);

var expectedTable = <StockMarketTable stockMarketProjection={projectionFor(config)} />;
var actualTable = TestUtils.findRenderedComponentWithType(app, StockMarketTable);

// але як робити порівняння?
});


У я обійшов проблему, закопавшись в приватні деталі реалізації Реката, рендерил компоненти статичний ХТМЛ і порівнював результат. Ось код.

function checkComponent(actual, expected) {
var actualRendering = React.renderComponentToStaticMarkup(actual._descriptor);
var expectedRendering = React.renderComponentToStaticMarkup(expected);

expect(actualRendering).to.equal(expectedRendering);
}


Він працює, але в у разі падіння генерує страшне повідомлення про помилку, і цей код залежить від деталей реалізації Реакта. Довелося візуалізувати об'єктний граф рантайма!) Можливо є спосіб краще   і повинен бути спосіб краще   а я не знайшов.

Крім цієї не такий вже дрібної проблеми, тестувати Реактив одне задоволення. Зацініть тести ApplicationUi. Вони чудові в своїй простоті, зрозумілі і не містити mock'ів. Ні один тест не містить більше двох рядків, і це самий складний компонент всього програми.

5. Сумісність з пошуковими движками   ☺ (ніііт!)

Реакту вдалося зробити невелике диво: вони зробили фронт-енд фреймворк, не має проблем у пошуковими системами.

Завдяки віртуальному DOM'у, Реактив-додатки можуть рендеритись на стороні сервера з допомогою Node.js. Це означає, що потрібен лише один канал рендера і для пошукачів і для реальних користувачів. Це також означає, що сторінки показуються відразу після їх подання. Ніякого очікування document ready подій або завантаження всього JS. Реактив можна використовувати для подачі статичною розмітки, без клієнтського коду взагалі.

Круто.

Підсумок: рекомендую.

Реактив на напрочуд добре зібрана бібліотека. Мені він здався простим, інтуїтивно зрозумілим і легким у використанні. Якщо ви шукаєте фронт-енд бібліотеку для складних додатків або навіть для складних віджетів для існуючої сторінки, варто звернути увагу на Реактив. Він не ідеальний, і варто задуматися про потенційні проблеми з дірявим абстракцією DOM'а, але він дуже хороший. Рекомендую.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.