Zaznamenali jste článek Most Popular JavaScript Frameworks 2015 – 2016? Pracuje se zajímavou infografikou, ze které by se mohlo zdát, že se celý front-end vývoj soustředí kolem Angularu, Emberu a Backbone. Hladina aktuálního front-end vývoje na webu je ale velice bouřlivá s množstvím protichůdných názorů, změn, nástrojů a děje se toho mnohem více, než by se z takových článků o populárních frameworcích mohlo zdát.

Zkusím vám trochu osvětlit aktuální výzvy, kterým front-end vývoj aktuálně čelí a doplnit další zajímavé postupy, knihovny či frameworky, které by neměly ujít vaší pozornosti.

 

Aktuální situace ve světě front-endu

S rozmachem NPM na správu javascriptových závislostí (a všemi přidruženými nástroji typu Grunt, Gulp, Webpack, Browserify, Babel a další) poslední dobou hodně roste komplexita závislostí, buildů a nastavování projektů. Z toho vznikl pojem javascript fatigue. Pro ilustraci komplexity celého ekosystému je zde událost, kdy jeden programátor reálně rozbil tisíce celosvětových projektů jednoduchou změnou, obsaženou pouze v jedenácti řádcích kódu.

S tím souvisí další bod: na front-end jsou kladeny čím dále větší požadavky (složitost, platformy) a už dávno se nejedná o práci typu „tady si vložím jeden jQuery script“. Vzhledem k velikostem projektů není zase tak nepochopitelné strávit jeden celý den nastavením většího projektu pro tým lidí (jak někteří blogeři uvádí v článcích nebo postech jako základní negativum práce).

Vzhledem k oné vzrůstající složitosti front-endových aplikací se čím dále více přibližují reálným aplikacím, které musí rozumně pracovat s aplikačním stavem, oproti původnímu dostačujícímu jQuery data atributu. Začínají se tedy znovuobjevovat a používat různé vzory a postupy známé aplikačním architektům. Srovnejte například Redux s tímto. Hodně podobných postupů se točí kolem FRP, reaktivního programování a immutability, jako například Javascript fatigue nebo State of Union.js.

EcmaScript 6

První věcí, na kterou se vyplatí podívat, je nová specifikace Javascriptu EcmaScript 6. Řeší spoustu nepříjemných vlastností jazyka a přidává zajímavé možnosti. Výsledkem bude čistější, čitelnější kód a spokojenější programátoři (i ti co neměli javascript tolik v lásce).

Jen namátkou:

  • const a let místo var – obě proměnné mají blokový scope, což znamená, že se chovají tak, jak by programátoři čekali z jiných jazyků
  • kratší definice funkce

[1, 2, 3].map(function(n) { return n * 2; }, this);
[1, 2, 3].map(n => n * 2);


// lib/math.js
export function sum (x, y) { return x + y }
export var pi = 3.141593

// someApp.js
import * as math from "lib/math"
console.log("2π = " + math.sum(math.pi, math.pi))

Problémem může být poněkud slabší podpora v prohlížečích, což lze lehce spravit použitím transpilleru při build procesu v různých nástrojích, jako je třeba Babel.

Další zdroje informací:

React

React je knihovna od Facebooku, zajišťující vytváření komponent, respektive jejich vykreslování, na základě jejich stavu. V poslední době prochází rapidním vývojem a získává velkou popularitu. Umí v podstatě jen jednu věc, ale zato zatraceně dobře. Vytváření front-endových komponent je snadné, přehledné a člověk se necítí, jako by framework „znásilňoval“ hned od začátku (například v porovnání k direktivám Angularu a zkoumáním pastí typu $scope.apply()).

Spojeno s ES6 syntaxí a JSX, komponenta vypadá takto:


const NamePreview = ({name}) => (
<div key={name.key}>{name.display}</div>
);

NamePreview.propTypes = {
name: React.PropTypes.object.isRequired,
};

const LatestPostsComponent = ({names}) => (
<section>
<div><h1>Latest posts</h1></div>
<div>
{ names.map(name => <namepreview name={name}></namepreview>) }
</div>
</section>
);

LatestPostsComponent.propTypes = {
names: React.PropTypes.object.array,
};

Všimněme si snadné čitelnosti, skládání, zanořování (tedy znovupoužitelnosti) a transparentního předávání dat. V ukázce je bezstavová komponenta, která všechna data dostává „z vrchu“ pomocí atributů. Spolu s jejich runtime validací (propTypes. – nepovinná vlastnost komponenty, ale užitečná proti opomenutí pří vývoji). Samozřejmě lze udělat komponentu se stavem, která se přerenderuje pokud se stav změní. To jak pracujeme se stavem aplikace nebo komponent React neřeší a je třeba použít některý z návrhových vzorů, pokud má být aplikace.

Další zdroje informací:

Redux

Redux je návrhový vzor pro práci se stavem aplikace, inspirovaný původním facebookovým Fluxem. Stejně, jako on, snaží se řešit problém, se kterým se každý, kdo píše alespoň průměrně složitou front-endovou aplikaci, jednou setkal či setká: „Mám event, kterým reaguji na jiný event, který updatne něco tady a na základě toho se spustí další event…“.

Ve chvíli, kdy nám aplikací začnou létat podobné aktualizace lokálních stavů horem dolem, nastává čas to řešit. Redux nám říká, že stav aplikace je na jednom centralizovaném místě (Store, oproti Flux je jen a pouze jeden), je neměnný (immutable) a jeho aktualizaci lze udělat pouze na základě akcí. Po spuštění (dispatch) akce nastoupí jádro Reduxu, a to „reducer funkce“ (action, oldState) => (newState), která vypočítá nový stav. A celá logika aplikace žije v této funkci, která je samozřejmě komponovatelná z menších funkcí.


const mainReducer (state = 0, action) => {
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
}

let store = createStore(counter)
store.subscribe(() =>
console.log(store.getState());
)

store.dispatch({ type: 'INCREMENT' })
// 1
store.dispatch({ type: 'INCREMENT' })
// 2
store.dispatch({ type: 'DECREMENT' })
// 1

Na store.subscribe pak navážeme naší View část aplikace (React, Mithril, hyperscript, plain old HTML ….), která při změně svojí části stavu patřičně překreslí potřebné části aplikace.

Další zdroje informací:

Immutable.js

Pokud chceme zajistit immutabilitu dat v javascriptu, jeden z nástrojů, jak toho efektivně docílit, je Immutable.js. Jedná se sice o starší nástroj, ale s rozmachem přístupů kladoucích důraz na neměnnost dat a stavu, je dobré ho znát.

Hlavní výhodou immutability je snadnější implementace deep equals díky tomu, že při změně je vždy vrácen nový objekt. Lze se tedy spolehnout na to, že pokud dostaneme jinou referenci, něco se změnilo.


const obj1 = Map({a:5});
const obj2 = obj1.set("a", 6);
obj1 === obj2; //false

Další zdroje informací:

2015-front-end-frameworks

RxJS

Reaktivní programování je dalším evolučním krokem a abstrakcí od Promise. Co takhle myšlenka, že všechny události nejsou jen samostatně existující události, ale součástí nekonečného proudu? Například klik myší není „klik myší“, ale místo, které generuje potenciálně nekonečné pole kliků v čase. A nad tímto nekonečným polem pak lze provádět operace typu .map(), .filter().

Vezměme si za příklad typický našeptávač. Co by měl umět? Našeptávat uživateli (až po 250ms!) když začne psát (až po 3. znaku!) pomocí ajaxu z nějaké adresy na serveru. Samozřejmě, že když uživatel píše rychleji, než odpovídá služba, staré výsledky se zahodí. Pomocí RxJS se dá celá funkce napsat přehledně na pár řádků.


var input = document.getElementById('input');
var dictionarySuggest = Rx.Observable.fromEvent(input, 'keyup')
.map(function () { return input.value; })
.filter(function (text) { return !!text; })
.filter(function (text) { return text.length > 2; })
.distinctUntilChanged()
.debounce(250)
.flatMapLatest(searchWikipedia)
.subscribe(
function (results) {
list = [];
list.concat(results.map(createItem));
},
function (err) {
logError(err);
}
);

Další zdroje informací:

Cycle.js

Cycle.js je rozvedení myšleny reaktivního programování, kdy aplikaci a její okolí chápeme jako dialog mezi počítačem a člověkem – jako smyčku. Uživatel zadává vstupy do programu (klik), a reaguje na výstupy programu (html). Program reaguje na akce uživatele tím, že vygeneruje nové html (nebo použije jiný komunikační port, zvuk apod.).

Cycle.js pak umožňuje program vyjádřit tak, jak v něm „tečou“ data (dataflow), a to vede k čistějšímu kódu. Zatím se jedná o velmi experimentální architekturu, neexistuje moc hotových komponent a mnoho jasných názorů, jak kód strukturovat, ale komunita postupně roste a kdoví, jak moc daleko se Cycle.js bude ubírat.


import Cycle from '@cycle/core';
import {div, label, input, hr, h1, makeDOMDriver} from '@cycle/dom';
function main(sources) {
return {
DOM: sources.DOM.select('.myinput').events('input')
.map(ev => ev.target.value)
.startWith('')
.map(name =>
div([
label('Name:'),
input('.myinput', {attributes: {type: 'text'}}),
hr(),
h1(`Hello ${name}`)
])
)
};
}
Cycle.run(main, {
DOM: makeDOMDriver('#main-container')
});

Další zdroje informací:

Na závěr

Jak sami vidíte, nejen Angular nebo Ember hýbou světem front-endu. Celý náš obor se vyvíjí neuvěřitelně dynamicky a je mnohem pestřejší, než se na první pohled může zdát. Často, jakmile zaměříte své úsilí i na méně známá jména, zjistíte, že existují stovky úžasných možností, jak vyvíjet fantastické aplikace. A o to nám přece jde…


Tomáš Jílek

Tom_smallTomáš je fullstack Senior Developer se zaměřením na front-end a UX. Má rád JavaScript, nové technologie a pěkné, rychlé a dobře použitelné uživatelské rozhraní.

Máš rád front-end stejně jako Tom nebo ho chceš jako on ovládat?

Hledáme do naší party skvělé vývojáře. Podívej se, co nabízíme a dej nám o sobě vědět, bez ohledu na to, zda máš rád front-end nebo back-end, jestli nějakou technologii umíš nebo ne. Pokud budeš ty sám chtít, dostaneš u nás příležitost naučit se, co tě zajímá nebo udělat něco výjimečného.