JavaScript 2016, а можна простіше?

Останні півроку багато пишуть про невиправдану складності клієнтського JavaScript. Недавня стаття How it feels to learn JavaScript in 2016 її переклад на хабре викликали багато уваги, критика багато в чому справедлива, але...
Ускладнювати просто, спрощувати складно. (Один із законів Мерфі)
У цій статті я дам практичні поради, як можна просто зробити фронт-енд додаток, використовуючи при цьому сучасні технології. Спочатку практичні деталі реалізації, а в кінці статті буде аналіз вибраного стека.
Як приклад використовується додаток для роботи з колекцією фільмів. Фільми відображаються в списку з посторінковим вибіркою, пошуком, сортуванням, редагуванням і видаленням.
Використаний стек: create-react-app як збирач для клієнта, React, bootstrap, API з json-server або json-заглушки.

Працююче демо тут: Movies List.

У вже згаданій статті, ведеться діалог між досвідченим фронт-енд розробником і бек-енд розробником, який трохи знає фронт-енд і хоче написати просте клієнтське додаток використовуючи сучасні технології. Фронт-енд "гуру" вивалює все різноманіття технологій яке можна використовувати, і так спантеличує свого колегу, що той відмовляється від своєї ідеї взагалі або вирішує писати все по-старому з JQuery.
Я спробую дати більш практичні поради про те як це зробити, більше того покажу код готового програми, щоб можна було використовувати її як приклад.
GitHub репозиторій тут.
Клієнтська збірка з React Scripts
Перша проблема в сучасній фронт-енд розробки — це необхідність клієнтських збірок. Ми будемо використовувати готову build систему, де всі відразу працює "з коробки".
Create-react-app або React Scripts — це молодий проект (перший коміт у червні 2016) створений Деном Абрамовим, творцем Redux, який зараз працює в facebook.
Щоб почати
# встановити create-react-app глобально
npm i -g create-react-app

# створити новий додаток в папці my-app
create-react-app my-app

React-scripts билдит клієнтське додаток, без необхідності додаткової настройки. Підтримуються 2 режими development і production.
В режимі development використовуються клієнтські складання в пам'яті (з WebPack dev-server) відразу працює hot-reload (ви змінюєте код, сторінка перевантажується), код перевіряється лінтером (наприклад, якщо у вас є невживана змінна, буде відповідне попередження) та інше.
Для запуску в development режимі, просто:
#cd my-app
npm start

Якщо потрібно зробити production складання:
npm run build

Це створить складання програми у папці "/build", де буде мінімізована і готова до розгортці версія.
Для імпорту стилів і шляхів до картинок, використовується метод WebPack, просто робіть import для потрібних ресурсів.
//імпорт bootstrap стилі з папки npm пакету
import '../node_modules/bootstrap/dist/css/bootstrap.css';
//імпорт картинки з локальної папки програми, в somePicture шлях до картинки
import somePicture from '../media/picture.png';

Більш докладно про роботу з react-scripts читайте на GitHub сторінці проекту.
React
як JS фреймворку ми вибираємо React. Є інші хороші опції (VueJS, Angular2), але на відміну від них, React має найбільш стабільну екосистему. Це означає стабільність API (не сильно змінюється від версії до версії), підтримку в IDE, усталений набір додаткових бібліотек (Redux, react-router), набір готових компонентів (react-bootstrap, material-ui).
При цьому, сам синтаксис React JSX не простий для початківця і це, напевно, найскладніше з чим доведеться зіткнутися в обраному стеку.
Сам додаток movies-list навмисно написано просто, щоб було легше зрозуміло для початківців (наприклад, в реальному додатку можна було б зробити більш детальне розділення на компоненти).
Існує величезна кількість всіляких підручників з React, для вибраного стека вам потрібно щоб у підручнику використовувався ES6 синтаксис (компоненти оголошуються через class), і вам не потрібно вивчати Redux або React Router. З ними ви можете розібратися пізніше, якщо буде необхідність.
Прикладом такого підручника може бути React Fundamentals on Eggheads, варто також почитати офіційну документацію.
Додаткові модулі
Модулі використовуються як npm пакети.
як CSS фреймовка використовується "bootstrap". Для інтеграції з React використовуються компоненти "reeact-bootstrap" (добре описані на сайті проекту).
Пакет "toastr" використовується для спливаючих повідомлень про помилку або повідомлення про успішної операції (наприклад: фільм був збережений). Цей пакет вимагає включення "jquery" та для реального проекту може мати сенс знайти аналог на React, щоб не включати JQuery і зменшити розмір упакованого програми.
Для вибору декількох значень для жанру фільмів використовується "react-select" — просунута версія компонента для випадаючого списку.
При використанні ES6 класів потрібно робити зв'язування (bind) для функцій. Пакет "react-autobind" спрощує цю задачу, потенційно може вплинути на продуктивність (ви прив'язуєте всі методи, а не тільки ті, де це потрібно), але полегшує розробку. Детальніше про bind в React тут.
//замість: 
constructor() {
super()
this.update = this.update.bind(this);
//... всі інші методи
}

//c autobind
import autoBind from 'react-autobind';
...
constructor() {
super()
autoBind(this);
}

Для більш зручної маніпуляції css класами використовується пакет "classnames".
import classnames from 'classnames';

let oneClass = classnames('foo', 'bar'); //значення "foo bar"

let isActive = true;
let anotherClass = classnames({
'foo': true,
'bar': false,
'active': isActive 
}) // значення "foo active"

API
Якщо у вас немає можливості або бажання використовувати серверну частину для клієнтського додатка, то є кілька альтернативних можливостей:
JSON-заглушки — початкові дані програми зберігаються в JSON файлі, який імпортується як зовнішній ресурс.
import jsonData from '../myJsonFile.json';

В подальшому всі операції відбуваються вже з завантаженими даними. Ви реалізуєте операції пошуку, редагування, видалення самостійно, працюючи з початковими даними з JSON.
movie-list цей підхід використовується за замовчуванням, логіка у файлі 'movieServiceStubs'.
Використання json-server — пакет json-server при запуску дає доступ до набору API на основі структури JSON файлу.
Наприклад, якщо у вас є db.json в якому є масив movies, то автоматично будуть доступні наступні API:
GET /movies
GET /movies/1
POST /movies
PUT /movies/1
PATCH /movies/1
DELETE /movies/1

При цьому, API змінюють початковий db.json файл, для GET запитів підтримується пошук, посторінкова вибірка, сортування.
Крім цього json-server підтримує багато додаткових опцій — кастомні маршрути, авто-генерація тестових даних, підтримка зв'язків між різними елементами.
movie-list є можливість роботи з json-server, потрібно використовувати movieService замість movieServiceStub, крім цього:
#встановити json-server глобально
npm i -g json-server
##запустити json-server через npm-scripts
npm run server

Для AJAX-запитів в React Scripts пропонується використовувати fetch API. Це новий браузерний стандарт, які більш зручний, ніж XMLHttpRequest. Для підтримки старих браузерів в React Scripts використовується полифил.
На відміну від JQuery, axios та інших клієнтських бібліотек, Fetch це стандарт, який можна використовувати вже зараз і який буде всерйоз і надовго.
Мовні функції
Щоб не ускладнювати код додатковими бібліотеками, movie-list я використовую тільки ES6 фічі (без lodash)
Крім стрілочних функцій ((x) => ...) варто звернути увагу на такі, як:
Шаблонні рядка
Ітерація з колекції for… of ...
Клонування об'єкта c Object.assign
Методи масивів map, filter, reduce
Завдяки новим функціям ES6, в Lodash і подібних бібліотеках вже немає такої гострої необхідності, хоча їх використання все одно може бути корисно.
У проекті не використовуються ES2016+ фічі, вони підтримуються React Scripts, але API менш надійні і гірше підтримуються (документація, приклади, підтримка IDE і ін). Якщо вам все-таки цікаво, можете спробувати використання async/await замість Promise і static властивості React компонентах.
Опублікувати
Є багато сайтів, на яких ви можете викласти статичні ресурси (HTML/CSS/JS). React Scripts пропонує використовувати для цього GitHub pages, документації описано як це зробити і після 5-хвилинної налаштування ви можете опублікувати демо-версію свого додатка. При цьому, необхідно використовувати json-заглушки, а це значить додаток втратить свій стан після повної перевантаження сторінки, що для демо навіть краще.
Аналіз вибраного стека
У вже згаданій статті наводяться кілька проблем сучасного фронт-енду:
Необхідність клієнтських білдів
По-перше, навіщо вони взагалі потрібні? Чому не можна як раніше просто включати скрипт в HTML сторінки і просто починати писати код.
В основному, із-за того, що деякі браузери дуже повільно імплементують нові стандарти (не будемо показувати пальцем, але в основному це стосується IE). Поки ці браузери не підуть в історію (а це як мінімум пару років), буде існувати необхідність у клієнтських збірках, хоча б для того, щоб використовувати нові функції мови ES6. Крім цього, якщо у вас велике додаток, то вам варто минифицировать ваш код, і якщо він розбитий на багато файлів об'єднувати їх в одну збірку з урахуванням зв'язків (якщо модуль A використовує модуль Б, то модуль Б повинен бути включений перед модулем A).
Самостійно налаштовувати клієнтський білд складно. Потрібно підключити webpack, babel, з десяток webpack loaders, підтримувати dev/prod складання. На це може піти купа часу і нервових переживань, навіть при використанні boilerplate вам буде не просто його вибрати, а потім підтримувати. На щастя, з'явилися збирачі (поки не багато) для клієнтського додатка, в яких все це приховано всередині окремого пакета і все що вам потрібно-це підключити цей збирач і писати свою програму з урахуванням певних особливостей.
Вже існують аналоги React Scripts, для VueJS це vbuild, для Angular2 альтернативи я поки не бачив, але є білд система для Ionic2 який побудований на Angular2. Ці проекти поки ще не так обкатані, але поява подібних інструментів лише питання часу.
Деякі сумніваються, що це підходить для серйозних додатків. Це цілком можливо, але при використанні готової системи клієнтської збірки ви повинні дотримуватися деякі угоди, наприклад, точка входу в один і знаходиться в src/index.js не використовуються CSS препроцессоры, код перевіряється певним набором правил линтера. При цьому, сама програма може бути як простим "hello world" так і складним клієнтом на багато сторінок. Приміром, у проекті Contoso Express react scripts використовуються для набагато більш складного додатка.
зрештою, якщо через кілька місяців вам знадобиться щось чого не можна домогтися готовим складальником, ви можете зробити своє кастомное рішення, але вам не доведеться займатися цим самому початку.
Проблема швидкого старіння технологій
Ви вивчаєте нову технологію, витрачаєте багато часу, а вона старіє через півроку або в новій версії API кардинально змінюються і доводиться розбиратися заново.
Це справедливо для багатьох технологій, ціна прогресу, але не для всіх. Якщо не хочеться зіткнутися з подібною ситуацією, потрібно просто правильно вибирати стек. У нашому стеку більшість технологій давно існують, працюють надійно і не будуть змінюватися надалі.
не Можна з повною впевненістю говорити про React (хоча після переходу на ES6 синтаксис, для компонентів ніяких значних змін у базовому синтаксисі не було). Але що стосується ES6, Fetch, Promises — це те, що вже є стандартом JS і буде актуально багато років, і вже підтримується більшістю браузерів.
Проблема занадто великого вибору
Уміння правильно підбирати інструменти важливо не тільки в програмуванні. Проблема в JS, що немає основного (mainstream) підходу, для більшості випадків, як наприклад в .NET. І вибір сильно ускладнюється. В цьому плані екосистема React досить сталою, наприклад, якщо спочатку для React існувало безліч Flux імплементацій, то зараз більшість додатків використовує Redux, є тільки одна популярна версія для клієнтської маршрутизації React Router, і т. д.
При цьому важливо не використовувати зайві інструменти, використовуючи прогресивний процес розробки. Почати з необхідного мінімуму, додаючи нові компоненти тільки за реальної необхідності. Наприклад, у вже неодноразово згаданій статті, для простого односторінкового прокладання, пропонувалися деякі технології, в яких зовсім не було сенсу:
  • ES2016+ — приємне доповнення, але особливої необхідності немає.
  • TypeScript/Flow — дає переваги суворої типізації, але вимагає додаткових зусиль при налаштуванні і використанні, для початківців буде лише додатковою морокою (в React Scripts можна підключати Flow).
  • Functional programming — для простого додатка, необхідності в цьому немає взагалі, а для складного додатка без цього цілком можна обійтися.
  • Lodash/Rumbda — з використанням ES6 багато корисні функції стали доступні на рівні мови, можна почати без них.
  • Flux(Redux) — для складного додатка необхідний спосіб спільного використання стану (даних) програми для різних компонентів, для простого додатка відмова від них полегшить початкову розробку.
  • Тестування UI — для простого додатка без них можна обійтися (в React Scripts є підтримка Jest для тестування React компонентів).
Дякую, тим хто дочитав до кінця.
Happy coding! Stay tuned.
Джерело: Хабрахабр

0 коментарів

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