Jak jsem zápasil s Reactem

Před rokem jsem potřeboval napsat pro svoji aplikaci klientskou stranu jako SPA. Hodně se mluvilo (a stále mluví) o Reactu, tak jsem ho použil. Po roce, na rozdíl od Ruby, ho stále používám a jsem spokojen. Ale proběhlo několik velkých předělávek. Není vše tak růžové, jak se zdá.

React je totiž pouze V ze zkratky MVC. I když se zdá, že dělá víc, opravdu se jedná jen o view. A tuhle část zvládá naprosto perfektně! Jenže je potřeba taky M a C. Což je problém, protože jsme ve světe JavaScriptu a teď si vyberte mezi Fluxem, Refluxem, Reduxem, … prostě nějakým -uxem.

Podle vybraného uxu se vám při šťastném výběru zodpoví pár dalších otázek, jako například props vs. state či one store vs. many stores. Spíš očekávám, že to je něco, na co stejně narazíte. Sám jsem se držel Fluxu, neb je také od Facebooku. Ze zkušeností s JS světem jsem se raději držel toho, aby byla co největší šance kompatibility a zdrojů na internetu. Což znamená, že zmíněné otázky nejsou vyřešeny.

Krása Reactu či Fluxu spočívá zejména ve volnosti. Ono je to vlastně velice jednoduchý koncept a můžete ho použít kdekoliv. Buď jen koncept nebo celou knihovnu. Například Angular je skutečně plnohodnotný framework a můžete React využívat jen pro šablony. Tak lze teoreticky spojit výhody z obou světů. Prakticky nemám ozkoušené.

Nastupovat do vlaku Angular vs. Angular 2 se mi nechtělo, takže jsem stále zůstal u Reactu s Fluxem a snažil se otázky sám vyřešit. Vyzkoušel jsem mít spoustu malých storů a vše předávat statem. Vyzkoušel jsem mít jeden store a vše předávat propsy. Každý způsob má něco do sebe, ale popravdě čím větší aplikace byla, tím mi největší smysl dávalo najít se někde uprostřed.

Což tak nějak přirozeně sedí i s použitím React Routeru. Vždy jedna stránka má hlavní komponentu, které se předávají data ze storu statem a všem svým podkomponentám se dál data dostávají přes propsy. Funguje krásně, ale je hodně těžké najít tu správnou střední cestu. Každopádně pokud použití není přirozené, našel jsem chybu v architektuře komponent.

Abych však cestu neměl tak jednoduchou, prošel jsem si ještě jedním refaktorem – naverbováním Immutable.js, další knihovna od Facebooku. Bez ní totiž React postrádá jakýchkoliv výhod. To myslím vážně, jakýkoliv. Pomalé odezvy jsou nemyslitelné a zabijí jakoukoliv jinou výhodu. Reactí systém přerenderování pouze v případě potřeby funguje totiž pouze s Immutable.js a napsanými funkcemi shouldComponentUpdate. Bez toho nešlo aplikaci používat.

Což ale lehce komplikuje psaní kódu už tak komplikovanější prostředí. Například className či encType mne neskutečně irituje a těžce se debuguje, kde je chyba. Například chyba při renderování se v některých případech nenareportuje a když ano, traceback není úplně jasný.

Takovou čtvrtou velkou otázkou je, jak vlastně poskládat store? Co dovolit číst z venku, jak si udělat přehledné poslouchání na eventy a další. Opět jsem zkusil mít zveřejněné vše a nic. Jestli mít spíš kód ve storu či dispatcheru. Opět mi vyšla nejlépe střední cesta, od každého trochu dle potřeb.

Ale hej, React je fajn. Prototyp jsem měl hotov za den, pak už jsem jen zápasil s tím, jakým stylem napsat, aby bylo připravené pro mé potřeby. Navíc spoustu věcí jsem dostal zadarmo, například routing (react-router), klávesové zkratky (react-hotkeys) či Bootstrapcké komponenty (i když ty se vyžívají v neustálém předělávání a za čas strávený upgrady jsem mohl mít svoji vymazlenou stabilní verzi).

Závěrem: v práci jsem si vyzkoušel i Angular a díval se detailněji na Redux. Pokud bych psal další SPA, znovu bych sáhl po Reactu s Fluxem, Immutable.js a Routerem a šel cestou střední cesty, co se hlavních otázek týče. Nakonec je to jednoduché na použití a přehledný flow aplikace. Každopádně to neznamená React použít. Weby renderované na serveru mají stále své kouzlo. Vlastně je to, řekl bych, pro většinu webových aplikací ta lepší varianta.

Roztříštěnost JavaScriptích knihoven

JavaScript mám docela rád. Kór dnes s ES6, ES7 a Reactem je psaní SPAček radost. Dokud není potřeba využít nějakou knihovnu. To pak přestává být sranda. Původně jsem chtěl napsat do nadpisu nepoužitelnost, ale nakonec lze knihovny nějak použít. Je s tím však spousta trápení.

Jeden z příkladů může být samotný React a známé a používané knihovny. Vyšel nový React 0.14, který přinesl zajímavé featury. Především stateless komponenty. Samozřejmě, že po pár týdnech jsem se rozhodl novinek využít. Jenže problém – používám taky react-bootstrap a podpora je až od verze 0.27. O pět čísel větší než s kterou jsem web napsal. Za tu dobu samozřejmě stihli sáhnout přesně na ty komponenty, které používám. Takže jsem šel upravovat čerstvě napsaný kód…

Což ještě není to nejhorší, horší je závislost na knihovnu, která na kompatibilitu kašle. Pak jen koukáte do konzole, jak React warninguje, a doufáte, že autor knihovny to také upraví. Nejpozději do vydání nové verze, která warningy transformuje na errory. S takovou zkušeností mi přijde, že se vyplatí záviset jen na populární knihovny a zbytek si udělat sám.

Má to ještě jeden ironický důvod. Možnost výběru je zlo. Pro různé úlohy existuje bambilion různých balíků. Každý si napsal něco a řekl si „to se bude někomu hodit, zveřejním to“. Taková blbost! Nyní je těžké se v nepřeberném množství zorientovat. S absencí dokumentací (pahýly mezi dokumentace nepočítám) je pak těžké najít, co vlastně řeší můj problém. A hlavně aby taková knihovna byla udržovaná a stabilní, tedy neprefixovaná nulou.

Další extrémní příklad je pořádná výzva: ES6 a pár ES7 featur, React, JSX. Zkuste s takovou kombinací rozchodit testy. A to ještě není nejhorší varianta! S takovými AMD moduly to je ještě větší sranda. V práci jsme narazili na bug v testovací knihovně. Možnosti jsou dvě – buď se o verzi vrátit. Nebo ve světě JS je naopak vždy dostupná novější verze, takže upgradovat. To nám ale zařvalo z důvodu absence nejnovějšího Nodu. Čerstvého Node 4. Na Debianu samozřejmě není dostupný, ale ne protože to je Debian, kde jsou balíky se zpožděním, ale protože to chce nový gcc dostupný až pod Jessie. Tedy: chceš testovat JavaScript? Upgradni si operační systém. Jo a taky si to zkompiluj…


Lehce to zveličuji. JavaScript se mi líbí. Občas ale dokáže vytočit. Proto chci spíš šířit následující zprávu, která se nemusí nutně vztahovat na JavaScriptí svět (jen to pro něj patří z důvodu spoustu edge novinek dvojnásob):

Chápu, každý chce být autorem populární knihovny. Populární knihovna ale nevznikne rychlým nabastlením, zveřejněním a doufat v open source boha. Už na začátku je potřeba se ke kódu chovat jako bych ho měl maintenovat do konce života. Což znamená si dobře promyslet API hned při prvním návrhu, aby se později měnilo minimálně. Také to znamená být připraven řešit všechny use-casy. Jak by se asi používalo request-get, request-post, request-json, … pokaždé od jiného autora? V neposlední řadě řádně zdokumentovat, co vlastně moje knihovna řeší a popsat jak s ukázkami.

JavaScriptové zákeřnosti

Určitě všichni znáte Watmana. Pokud si nepamatujete, určitě jste aspoň slyšeli o lightning talk Wat. A jestli ne, určitě se nejprve podívejte. Osobně mi to přijde zábavné, ale nikdy mě to nějak netrápilo (snad krom sčítání polí), protože kdo by v JavaScriptu chtěl sčítat pole s objektem nebo dva objekty? Nenapadá mě žádný rozumný příklad, kde toho využít.

Nedávno jsem na Twitteru narazil na podobnou srandičku:

Ano, může to vést k chybám, ale rozhodně to nemá nic společného s náhodou. Vysvětlení jak z videa, tak k tomuto, můžete najít na Stackoverflow tady. JavaScript se snaží nejprve přetypovat proměnné do podoby, kterou pravděpodobně potřebujeme. Vše je logicky odůvodnitelné.

Ono se dá takovéto chování pochopit, přihlédne-li se k tomu, pro co byl JavaScript stvořen – pro web. A na webu se komunikuje s uživatelem v řetězcích. Pokud vstupem je číslo, datum či cokoliv jiného, nikoliv text, musíme si to ohlídat sami. To samé se děje na backendu, kde musíme řešit stejnou věc – z requestu také dostaneme jen řetězce a kontrolu a převod do správných typů si musíme ošetřit. Teď už jen záleží, co je každému z nás bližší – zda je lepší nechat aplikaci spadnout či nějakými pravidly zkusit odhadnout, co dělat, a pokračovat.

Ať tak či onak, v obou případech si musíme nějak pomoct a nedoufat na automatiku daného jazyka. Osobně si myslím, že na klientské straně je toto chování asi i lepší. Při chybě je možnost, že aplikace poběží bez problémů dál (nebo taky může spadnou o kousek dál a pak je sranda najít, kde chyba vznikla).

Každopádně jsem ve stejný den narazil ještě na jeden tweet:

To mě docela překvapilo. Vysvětlení dává zase smysl. Tady ale už srandičky končí.

JavaScript se mi líbí, ale některé jeho nástrahy jsou zákeřné. Nejen ty výše zmíněné, další za zmínění stojí třeba porovnání polí  ([1,2,3] == [1,2,3] // false), či že null je object (typeof null // "object")… Z toho důvodu rád používám CoffeeScript s Closure Library. Některé zákeřnosti si tak odfiltruji, ale přitom se nijak nevzdávám žádných vlastností jazyka. A vám doporučuji udělat to samé. Ne nutně to samé, co používám já, ani co opěvuje někdo jiný. Sáhněte po něčem, co vám sedne. Možností je dost: CoffeeScript, TypeScript, Dart, Closure Library, … (pozor – jQuery zde není řešením) Důležité je něco si vybrat a používat.

Mor zvaný jQuery

V poslední době píšu více a více JavaScriptu a čím dál více zjišťuju, že jQuery je zlo, které akorát moří internet. Dříve jsem ho občas použil, když bylo potřeba, abych web trochu rozhýbal (pamatuju si i různé kung-fu s DOMem; jó, to byly časy). Později, to když jsem si začal psát složitější věci, jsem se mu začal vyhýbat. A nyní bych byl raději, kdyby jQuery neexistovalo.

Ano, jQuery je super, když je potřeba na malé prezentační stránce umístit například uživatelsky příjemný formulářík (výběrak datumů atp.). Tím to však začíná a zároveň i končí.

Je nutné si uvědomit, že jQuery je hnusný spaghetti code, poskládaný v jednom namespace, snažící se to napravit bambiliony pluginů řešící jednu a tu samou věc, zabírající nezanedbatelnou velikost pro mobilní připojení a tak dále. Nechci vás od jQuery tímto však odrazovat, praste si klidně dál (někde může být opravdu dobrá volba jQuery použít).

Jen chci, aby se jQuery nepoužívalo jako správná odpověď na internetu na JavaScriptové otázky. Opravdu mě nemálo štve, když si nejsem jist či opravdu nevím, jak něco v JavaScriptu správně řešit, jdu guglit a naleznu odpovědi „use jQuery“ s ukázkou na pár znaků nevysvětlující absolutně nic.

Jeden příklad za všechny:

Sakra, já nechci kvůli prkotině tahat celých dalších 100 kB dat zbytečného kódu, který nepotřebuju! Natož uživatel mé aplikace.

Takže si řekneme hezky nahlas: nikdy nebudu odpovídat na otázku jak něco udělat v JavaScriptu „use jQuery“, pokud o to nebudu požádán!

Mimochodem osobně používám na všechno Closure Library a neměnil bych.