
Návrhové vzory v praxi. Kedy pomáhajú a kedy komplikujú kód
Strategy, Adapter a Factory riešia odlišné druhy zmien. Zistite, kedy si každý vzor zaslúži miesto v kóde a kedy je lepšia priama funkcia.
Porovnajte Next.js s Axum, Askama a htmx podľa stavu v prehliadači, kontraktov, cache, nasadenia, bezpečnosti, mobilných klientov a odovzdania.

Rozhodnutie medzi Next.js a kombináciou Axum, Askama a htmx nie je súboj moderného JavaScriptu proti rýchlemu Rustu, hoci sa takto zvyčajne prezentuje. Ide o voľbu vlastníka používateľského rozhrania.
Next.js dáva veľkú časť zodpovednosti komponentovému modelu Reactu a podľa potreby prehliadaču. htmx to robí naopak. O výslednom HTML rozhoduje server a v prehliadači sa vymieňa presne ten fragment, ktorý si odpoveď vypýtala, pričom prípadný lokálny stav treba navrhnúť osobitne.
Náš verdikt je krátky. Next.js je dobrý štandard pre klientské produkty a rozhrania s bohatým lokálnym stavom. Axum, Askama a htmx sú silná voľba pre serverové CRUD, pre administráciu a pre workflow aplikácie, ktoré niekto krok po kroku schvaľuje. Rust API s Next.js má zmysel až vtedy, keď produkt preukázateľne potrebuje bohatý klient a zároveň osobitne výkonný alebo bezpečnostne citlivý backend, čo býva zriedkavejšie, než sa zdá.
Tri výsledky architektonického rozhodnutia
Vyberte výsledok podľa dominantnej práce rozhrania a preukázaných potrieb backendu.
Next.js
Bohatý lokálny stav, editor, mapa alebo čokoľvek, čo musí reagovať hneď v prehliadači.
Axum + htmx
Formuláre, tabuľky a postupné workflow, ktorých pravdu vlastní server.
Rust API + Next.js
Bohaté UI spolu s preukázanou výpočtovou, paralelnou alebo viac-klientskou backendovou potrebou.
Príklady ilustrujú architektúru, nie zoznam aktuálne bezpečných verzií. Pred realizáciou uzamknite konkrétne vydania a prečítajte ich poznámky aj bezpečnostné oznamy.
Rust tu znamená Axum pre HTTP a Askama pre šablóny, doplnené o htmx v prehliadači. Leptos, Yew a Rust SPA používajú iný model a do tohto porovnania nepatria.
React Server Component sa vykoná na serveri a jeho výsledok tvorí RSC payload. Pri prvom načítaní Next.js posiela aj predvykreslené HTML. Prehliadač pomocou payloadu zosúladí strom a JavaScript hydratuje Client Components. Dokumentácia Next.js odlišuje tento krok od ďalších navigácií.
Interaktivita si však vypýta hranicu Client Component a s ňou hydratáciu aj klientsky stav všade tam, kde sa rozhranie správa ako aplikácia.
HTML fragment v htmx je serverová odpoveď s časťou stránky. Tlačidlo určí požiadavku cez hx-post, cieľ cez hx-target a spôsob výmeny cez hx-swap. Server spracuje pravidlo, Askama vykreslí nový riadok alebo panel a htmx ho vloží do stránky.
Verejným kontraktom nie je strom Reactu ani JSON objekt. Je ním HTTP požiadavka a HTML, ktorého štruktúra musí sedieť na cieľ.
Ani jeden model nie je automaticky jednoduchší. Next.js centralizuje skladanie zložitého UI v komponentoch, htmx rieši ten istý problém na serveri, takže komplexita sa nestratí, iba sa presunie tam, kde ju ponesie tím, ktorý systém udrží ďalšie roky.
Dva spôsoby, ako sa z požiadavky stane rozhranie
Next.js prenáša výsledok komponentového stromu. htmx vymieňa HTML fragment pripravený serverom.
Next.js
Next.js požiadavka
Prehliadač žiada trasu alebo spustí Server Action.
Komponentový výsledok
Server vyrenderuje komponenty a klient zlúči prenesený výsledok so svojím stavom.
Axum + htmx
htmx udalosť
Kliknutie alebo formulár odošle bežnú HTTP požiadavku z atribútu v HTML.
HTML fragment
Axum overí pravidlá, Askama vyrenderuje výsledok a htmx nahradí určenú časť stránky.
Predstavme si zoznam faktúr. Oprávnený používateľ stlačí Schváliť. Server overí organizáciu aj stav dokladu, zapíše zmenu a používateľovi ukáže nový stav, pričom celý ten reťazec musí prejsť aj vtedy, keď dvaja ľudia stlačia tlačidlo naraz. V Next.js môže formulár zavolať Server Action.
'use server';
import { revalidatePath } from 'next/cache';
export async function approveInvoice(formData: FormData) {
const invoiceId = String(formData.get('invoiceId') ?? '');
const user = await requireUser();
await invoices.approve({
invoiceId,
organizationId: user.organizationId,
});
revalidatePath('/invoices');
}
Reálny handler ešte potrebuje validáciu identifikátora, autorizáciu konkrétnej operácie, ochranu proti opakovaniu, auditnú stopu. Server Action treba chápať ako verejne dosiahnuteľný serverový vstup, nie ako dôveryhodné interné volanie.
Po úspechu môže Next.js obnoviť trasu alebo konkrétny cache tag. Klient môže medzitým zobraziť optimistický stav a po chybe ho vrátiť.
Silnou stránkou je plynulé používateľské správanie. Ten istý zoznam môže mať lokálne filtre, hromadný výber, klávesové skratky, bočný detail aj okamžité prepočty, a pri takej koordinácii sa hydratácia aj JavaScript navyše oplatia.
Cena vzniká v hraniciach medzi serverovým a klientskym komponentom, v invalidácii cache a hlavne v tom, či niekto stráži, koľko JavaScriptu naozaj odchádza do prehliadača.
V serverovom variante odošle tlačidlo POST /invoices/{id}/approve. Axum získa prihláseného používateľa. Aplikačná služba overí organizáciu aj prechod stavu a Askama vráti aktualizovaný riadok tabuľky, teda presne ten kus dokumentu, ktorý sa práve zmenil, a nič viac ako to.
use askama::Template;
use axum::{extract::{Path, State}, response::Html};
use uuid::Uuid;
async fn approve_invoice(
State(state): State<AppState>,
user: AuthenticatedUser,
Path(invoice_id): Path<Uuid>,
) -> Result<Html<String>, AppError> {
let invoice = state
.invoices
.approve(invoice_id, user.organization_id)
.await?;
let html = InvoiceRowTemplate { invoice }.render()?;
Ok(Html(html))
}
Riadok môže používať hx-post, k nemu hx-target="closest tr", a výmenu popisuje hx-swap="outerHTML". Po odpovedi sa vymení iba tento prvok, pričom AppError musí previesť aj chybu šablóny a chybová odpoveď má vrátiť použiteľný fragment, nie prázdne miesto po riadku.
Doménové pravidlo patrí do služby, nie do šablóny ani atribútu htmx.
Tento prístup je priamy pri formulároch a tabuľkách. Server po každom kroku vlastní pravdu aj prezentáciu. Pri hromadnom výbere, práci bez siete, náročnom drag and drop či viacerých súbežných paneloch však začne DOM niesť skrytý stav, o ktorom nikto nenapísal ani riadok dokumentácie.
Vtedy treba buď pridať malú ostrovnú JavaScript vrstvu, alebo priznať, že rozhranie už zodpovedá klientskému aplikačnému modelu.
Zoznam s filtrom v URL a jedným otvoreným dialógom zvládnu oba stacky. Rozdiel sa ukáže až pri stave, ktorý musí reagovať okamžite, bez čakania na server.
Editor s históriou krokov, mapa s tisíckami prvkov, plánovač s presúvaním položiek, konfigurátor s priebežným výpočtom. Každé z nich má prirodzený klientsky model a Next.js dokáže serverové načítanie skombinovať s izolovanými klientskymi ostrovmi.
htmx je silný vtedy, keď stav bezpečne drží databáza, URL, odoslaný formulár, aktuálne HTML na obrazovke. Server po každej mutácii pošle nový pohľad na pravdu, takže nevznikajú dve kópie toho istého údaju, ktoré by sa mohli rozísť, a s duplicitou zmizne celá trieda chýb.
Ak však začneme ukladať významné dáta do data-* atribútov, ak si napíšeme vlastný event bus a ručne koordinujeme päť fragmentov naraz, pôvodná výhoda mizne.

Rozhranie s viacerými previazanými panelmi potrebuje okamžité reakcie a spoločný stav v prehliadači. To je prirodzené prostredie pre Next.js.
Foto od Neila Fernandeza na UnsplashServerom renderované HTML nie je nedostatok, ak je web jediný klient. Pre interný schvaľovací systém môže byť najhodnotnejším kontraktom.
Formulár, chyba validácie a riadok, ktorý sa po nej prekreslí, tvoria jeden výsledok bez paralelného mapovania medzi DTO a šablónou, ktoré by bolo treba držať v súlade.
Situácia sa mení, keď tú istú schopnosť potrebuje mobilná aplikácia, partner, prípadne verejné API. HTML fragment nie je vhodný doménový kontrakt, a hoci JSON endpointy môžu žiť vedľa HTML handlerov, skopírovanie pravidiel do dvoch ciest znamená dva systémy, ktoré sa zhodujú iba náhodou.
Obe majú volať rovnakú aplikačnú službu a mať kontraktové testy.
Next.js tiež automaticky nevyrieši API dizajn. Server Action je pohodlný kontrakt pre konkrétne React rozhranie, nie stabilné partnerské API, takže produkt s viacerými klientmi potrebuje explicitný kontrakt bez ohľadu na to, čo renderuje web.
Next.js poskytuje viac vrstiev cache a invalidácie, čo je výhoda pre obsahové trasy, ale tím musí vedieť, čo je statické, čo sa znovu validuje, čo patrí konkrétnemu človeku. Chyba nevznikne preto, že cache nefunguje, ale preto, že dve časti tímu predpokladajú odlišnú životnosť dát.
htmx samo cache politiku neurčuje. Používa HTTP. Plné stránky a bezpečné GET fragmenty vedia využiť hlavičky, reverzný proxy server, CDN, čiže presne tie mechanizmy, ktoré web používal dávno predtým, než ktokoľvek riešil invalidáciu v aplikačnom frameworku.
Personalizované fragmenty musia mať správne Cache-Control a Vary. Mutácia má vrátiť čerstvý pohľad alebo spustiť následné načítanie, inak používateľ uvidí starý riadok a bude presvedčený, že tlačidlo nefunguje, čo vyzerá ako neúspešná operácia. Jednoduchší model neodpúšťa nesprávne HTTP pravidlá.
Pre oba stacky platí rovnaká zásada. Najprv pomenujte vlastníka čerstvosti dát a to, ako staré dáta sú ešte prípustné, a až potom sa bavte o tom, ktorý mechanizmus to v oboch stackoch zabezpečí. Cache nie je výkonová dekorácia. Je to súčasť konzistencie produktu.
Next.js sa dá prevádzkovať na spravovanej platforme aj vo vlastnom Node.js alebo kontajnerovom prostredí. Vlastný hosting potrebuje riešiť kompatibilný reverse proxy, statické aktíva, viac inštancií, cache koordináciu, konzistentné build identifikátory.
Framework zjednodušuje veľa vecí, no produkčný model treba stále navrhnúť.
Axum aplikácia môže byť jeden Rust binárny súbor so šablónami vloženými pri kompilácii a so statickými aktívami vedľa neho, čo je na prevádzku veľmi príjemný tvar. Kompilácia, cross build, správa migrácií, telemetry, pohotovostné postupy však zostávajú.
Menší počet runtime vrstiev neznamená nulovú prevádzku.
Rust vie priniesť predvídateľnú spotrebu zdrojov a dobrú kontrolu nad paralelnou prácou. Lacnejší produkt z toho ešte nevyplýva. Bez reálnych meraní to nikto nevie a latencii najčastejšie dominuje databáza, externé API, obrázky a jeden zle napísaný dotaz, nie jazyk, v ktorom je server napísaný.
Preto tu neuvádzame syntetické RPS čísla z neporovnateľných aplikácií.

Jeden Rust binárny súbor zjednoduší runtime, nie prevádzku. Proxy, migrácie, telemetria a reakcia na incidenty zostávajú súčasťou systému.
Foto od Kevina Acheho na UnsplashNext.js aj htmx používajú bežné webové bezpečnostné hranice. Server musí po každej mutácii overiť identitu, organizáciu, oprávnenie, aktuálny stav objektu, a musí to urobiť aj vtedy, keď to isté už raz overil pri načítaní stránky. Skrytý input, React prop ani DOM atribút nie sú dôveryhodné.
Výstup treba bezpečne escapovať a pri vedomom vkladaní HTML musí existovať presná sanitizácia.
Pri cookie autentifikácii treba posúdiť CSRF podľa metódy, podľa pôvodu požiadavky a podľa toho, ako sú nastavené cookies. htmx hlavička ani Server Action samy osebe nenahrádzajú autorizačné pravidlo.
Rust ownership chráni veľkú triedu pamäťových problémov, nie chyby prístupu medzi tenantmi, chybné SQL ani únik citlivých údajov v logoch.
Bezpečnejší stack je ten, v ktorom tím dokáže udržať jednu autoritatívnu doménovú cestu, kontrolované závislosti, pravidelné aktualizácie, pozorovateľnosť. Framework môže poskytnúť bezpečné predvolené správanie, ale nevie domyslieť firemné pravidlá za nás.
Next.js má veľký trh React vývojárov a klient si preto ľahšie zostaví tím na ďalší rozvoj, čo je pri odovzdávaní projektu argument, ktorý sa naozaj ťažko vyvracia. To ešte neznamená, že každý React vývojár rozumie Server Components, cache alebo tomu, ako sa taká aplikácia prevádzkuje. Handover potrebuje dokumentované hranice, zapísané rozhodnutia, merateľné kontrolné postupy.
Rust tím býva menší a nábor náročnejší. Na druhej strane typový systém, explicitné chybové cesty a kompilátor, ktorý nepustí ďalej, zužujú priestor pre niektoré neúmyselné zmeny. Ak budúci vlastník Rust nepozná, elegantný binárny súbor sa zmení na organizačné riziko a prvá bezpečnostná aktualizácia bude čakať, kým sa nájde niekto, kto to vie skompilovať.
Technická vhodnosť bez dostupného vlastníka nie je udržateľná voľba.
Pri vývoji softvéru na mieru preto hodnotíme aj schopnosť klienta systém po odovzdaní prevádzkovať, nie iba rýchlosť prvého vydania. Dokumentácia lokálneho prostredia, migrácií, incidentov, aktualizácií závislostí patrí do architektúry rovnako ako diagram.

Architektúru musí vedieť prevziať konkrétny tím. Výhoda Rustu sa stráca, ak po odovzdaní chýba človek, ktorý ho bezpečne udrží a rozvinie.
Foto od Vitalyho Garieva na UnsplashNext.js je slabá voľba, ak tím vytvorí veľkú klientsku aplikáciu pre jednoduché formuláre iba preto, že pozná React. Zbytočná hydratácia, duplicitný stav, komplikované invalidácie a hranice Server Action dokážu prekryť obchodný proces, ktorý sa dá popísať tromi vetami.
Framework sa tiež rýchlo mení a upgrade vyžaduje pravidelnú pozornosť.
Ďalšie zlyhanie vznikne, keď sa Next.js použije ako náhodná integračná vrstva aj ako doménový backend, a nikto sa pritom neobťažuje nakresliť hranice medzi jednotlivými modulmi produktu. UI, autorizácia, volania dodávateľov, dlhé úlohy na pozadí. Všetko sa premieša v trasách. Produkt potom nemá jasný kontrakt pre mobil ani miesto, kde sa dá bezpečne testovať obchodné pravidlo.
Kde zlyháva htmx + Rust
Rust vie spomaliť tím, ktorý sa popri hľadaní produktu ešte len učí jazyk. Kompilátor odhalí nezhody, ale nerozhodne, či je obrazovka užitočná, a pri rýchlom prototypovaní môže byť cena typov a kompilácie vyššia než riziko, ktoré tie typy odstraňujú.
htmx zlyháva vtedy, keď sa z fragmentov stane neviditeľná klientská stavová architektúra, teda niečo, čo nemá meno, nemá dokumentáciu a existuje iba v hlave toho, kto to písal. Viac cieľov jednej odpovede, udalosti, ktoré spúšťajú ďalšie udalosti, a nazbieraný vlastný JavaScript vytvoria systém, ktorý sa ťažko sleduje. V takom bode React nepredstavuje prehru. Je to pomenovanie skutočnej povahy rozhrania.
Ďalším rizikom je menší trh ľudí, ktorí rozumejú zároveň Ruste, serverovým šablónam, progresívnemu vylepšeniu, prístupnosti. Jednoduchý runtime môže zakryť drahé odovzdanie.
Hybrid je vhodný vtedy, keď existujú dve samostatne preukázané potreby. Frontend má bohatý stav a potrebuje React ekosystém, zatiaľ čo backend má výpočtovo náročné úlohy, nízku toleranciu latencie, silnú paralelnú záťaž, prípadne vlastný kontrakt pre viac klientov.
Tímy musia vedieť tú hranicu nezávisle testovať, verziovať aj prevádzkovať.
Hybrid nie je poistka proti rozhodnutiu. Prináša dva toolchainy, sieťové zlyhania, schému API, autentifikáciu medzi vrstvami, koreláciu logov, koordináciu zmien.
Ak Rust API iba posunie formulár do databázy a jediným klientom zostane Next.js, potom platíme plnú cenu distribúcie za niečo, čo si v tíme nikto nevypýtal.
Začať sa dá v jednom stacku so zachovanými doménovými hranicami. Rovnaký princíp rozoberá porovnanie modulárneho monolitu a mikroslužieb. API vyčleňte až vtedy, keď samostatnú prevádzku odôvodní vlastníctvo a meranie.
Na menšej obrazovke posuňte tabuľku vodorovne.
| Produkt | Odporúčanie |
|---|---|
| Klientsky portál | Next.js. Axum, Askama a htmx pri prevažne formulárovom portáli bez bohatého lokálneho stavu. |
| Interný systém | Axum, Askama a htmx. Next.js pri zložitom plánovaní, editácii alebo práci bez siete. |
| E-shop | Next.js. Serverový hypermedia model pri jednoduchom katalógu a kontrolovanom nákupe bez aplikačných interakcií. |
| Editor | Next.js. htmx iba pri jednoduchých formulárových blokoch bez lokálnej histórie. |
| Mapa | Next.js. Rust API doplňte, ak merania potvrdia náročné priestorové výpočty alebo veľký dátový tok. |
| Dashboard | Next.js. htmx pri serverových filtroch, tabuľkách a periodickom obnovení bez zložitého prepájania grafov. |
| Marketingový web | Next.js alebo jednoduché statické riešenie. Rust s htmx iba pri významnom serverovom workflow. |
Na Rise používame praktickú heuristiku. Ak väčšinu rozhrania tvoria formuláre, tabuľky a postupné workflow a stav prirodzene žije na serveri, stojí za to Axum, Askama a htmx aspoň vážne posúdiť, kým sa objedná React. Nie je to vedecký prah ani univerzálne pravidlo.
Je to signál, že React môže riešiť problém, ktorý produkt v skutočnosti nemá.
Ak podstatná časť hodnoty vzniká okamžitou manipuláciou v prehliadači, Next.js je bezpečnejší štandard. Ak potrebujete obe vlastnosti, oddeľte najprv skutočný doménový kontrakt, a hybrid zvažujte až potom.
Kontrola pred rozhodnutím
Pred vertikálnym rezom si spíšte rozhodovacie vstupy.
Pre jeden reprezentatívny workflow vytvorte tenký vertikálny rez.
Zmerajte množstvo klientského stavu, počet sieťových krokov, spôsob chýb, veľkosť prenesených aktív, čas potrebný na bezpečnú zmenu. Toto poskytne lepší podklad než všeobecný benchmark.
Overte aj vlastníctvo. Kto aktualizuje framework, kto rieši incident, kto pozná databázové migrácie, kto dokáže prijať projekt o dva roky.
Pri výbere IT partnera má byť odpoveď na tieto štyri otázky súčasťou ponuky, a nie prílohou, ktorá sa dopisuje až vtedy, keď je zmluva podpísaná.
Rozhodnutie uzavrite až po vertikálnom reze a dohode o vlastníkovi. Architektúra je obhájiteľná vtedy, keď budúci tím vie vysvetliť jej hranice, zmerať ich a bezpečne ich zmeniť bez toho, aby sa niekoho pýtal.
Maroš Bednár pripravil článok s podporou AI pri rešerši a jazykovej úprave. Odborné závery, príklady, zdroje a finálny text skontroloval a schválil.

Strategy, Adapter a Factory riešia odlišné druhy zmien. Zistite, kedy si každý vzor zaslúži miesto v kóde a kedy je lepšia priama funkcia.

Mikroslužby kupujú nezávislosť zmien za reálnu prevádzkovú cenu. Porovnajte hranice, vlastníctvo, dáta, nasadzovanie a signály na oddelenie služby.

Kontrolný zoznam pre kupujúceho softvéru. Pokrýva bezpečnosť, integrácie, roly pri dátach, vlastníctvo, podporu a odovzdanie pred podpisom zmluvy.