Ședința de kickoff pentru un SaaS nou. Backend-ul e decis de mult: ASP.NET Core, EF Core, SQL Server. Apoi cineva pune întrebarea care strică liniștea: „Și pe frontend ce folosim?”
În următoarele 40 de minute auzi toate argumentele posibile. „React, că toată lumea îl știe.” „Blazor, că suntem o echipă .NET.” „Angular, că e pentru enterprise.” „Am citit că Svelte e cel mai rapid.” Nimeni nu greșește complet. Dar nimeni nu răspunde la întrebarea corectă, pentru că întrebarea pusă e greșită.
Nu există „cel mai bun framework de UI”. Există framework-ul potrivit pentru ce construiești, cine îl construiește și cât timp va trebui întreținut. Articolul acesta e primul dintr-o serie despre alegerea tehnologiei de UI și se ocupă strict de web. Desktop-ul și mobilul vin în articolele următoare.
Mai întâi, harta: patru familii de framework-uri web
Lista de framework-uri web e lungă, dar aproape toate intră în patru familii. Dacă înțelegi familiile, alegerea devine mult mai simplă decât pare.
- Biblioteci și framework-uri JavaScript pentru componente — React, Angular, Vue, Svelte, plus nișe precum SolidJS, Preact, Lit sau Qwik. UI-ul rulează în browser, iar backend-ul tău devine un API.
- Meta-framework-uri — Next.js și React Router (fostul Remix) peste React, Nuxt peste Vue, SvelteKit peste Svelte, Analog peste Angular, plus Astro, care e un caz aparte. Adaugă server-side rendering, routing pe fișiere, încărcare de date și deploy optimizat.
- UI web în C# — Blazor, în toate modurile lui de randare. Componente scrise în Razor și C#, fără să fii obligat să scrii JavaScript.
- Server-driven HTML — Razor Pages sau MVC, de multe ori combinate cu HTMX. Serverul generează HTML, iar interactivitatea vine din fragmente de HTML schimbate dinamic, nu dintr-o aplicație JavaScript completă.
Diferența fundamentală dintre ele nu e sintaxa. E unde trăiește starea UI-ului: în browser (familiile 1 și 2, plus Blazor WebAssembly), pe server (Blazor Server, Razor + HTMX) sau amestecat (meta-framework-urile și Blazor Auto). Din această decizie decurg aproape toate celelalte: latența, costurile de hosting, SEO, complexitatea și cine poate lucra pe cod.
Aceeași componentă, cinci framework-uri
Înainte de comparații, merită văzut cum arată același lucru banal, un buton care numără click-uri, în fiecare dintre ele. Nu spune tot, dar spune mult despre filozofia fiecăruia.
React
import { useState } from "react";
export function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>Click-uri: {count}</button>;
}
Angular (standalone, cu signals)
import { Component, signal } from '@angular/core';
@Component({
selector: 'app-counter',
template: `<button (click)="count.update(c => c + 1)">Click-uri: {{ count() }}</button>`
})
export class Counter {
count = signal(0);
}
Vue
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
<button @click="count++">Click-uri: {{ count }}</button>
</template>
Svelte 5
<script>
let count = $state(0);
</script>
<button onclick={() => count++}>Click-uri: {count}</button>
Blazor
@rendermode InteractiveServer
<button @onclick="() => count++">Click-uri: @count</button>
@code {
private int count;
}
React e JavaScript cu HTML amestecat (JSX) și te lasă să decizi singur aproape tot restul. Angular e o clasă TypeScript cu decorator, servicii și injecție de dependențe, deci o structură care unui dezvoltator .NET îi va părea familiară. Vue și Svelte pun accentul pe cât mai puțin cod de ceremonie. Blazor e C# pur, iar linia @rendermode îți arată deja că alegerea nu se termină la „Blazor”: mai trebuie să decizi și unde rulează componenta.
React: ecosistemul cel mai mare, cu toate deciziile pe umerii tăi
React e liderul clar al pieței, iar asta are consecințe practice: pentru orice problemă există deja o bibliotecă, un tutorial și un răspuns pe Stack Overflow. Componentele UI (shadcn/ui, MUI, Mantine), state management, formulare, grafice, editoare: ecosistemul e imens.
Prețul este oboseala decizională. React este o bibliotecă pentru componente, nu un framework complet. Routing-ul, încărcarea datelor, formularele și gestionarea stării sunt decizii pe care trebuie să le iei tu, iar recomandările se schimbă la fiecare câțiva ani. În plus, React modern este gândit tot mai mult în jurul unui meta-framework: Server Components, server actions și React Compiler, care face automat o parte din optimizările scrise înainte manual cu useMemo și useCallback. Dacă folosești React „gol” cu Vite, totul funcționează excelent. Doar că rămâi în afara direcției în care evoluează ecosistemul.
Alege React când: construiești un produs public cu UI bogat, ai nevoie de biblioteci specializate (editoare, canvas, vizualizări complexe), vrei să angajezi ușor sau ai deja o echipă de frontend dedicată.
Angular: framework complet, opinionat și surprinzător de familiar pentru .NET
Angular e opusul lui React ca filozofie. Vine cu tot: routing, formulare, client HTTP, injecție de dependențe, testare, CLI. Există de obicei un singur mod corect de a face un lucru, iar pentru echipe mari asta e o calitate, nu o limitare. Un dezvoltator nou se uită în orice proiect Angular și se orientează imediat.
Pentru cine vine din .NET, Angular are un avantaj rar discutat: modelul mental. Servicii injectate în constructor (sau cu inject()), TypeScript strict, separare clară între componente și logică. Seamănă mai mult cu ASP.NET Core decât oricare alt framework JavaScript.
Reputația de framework greoi este în mare parte moștenită din perioada NgModules și zone.js. Angular s-a reconstruit în ultimii ani în jurul componentelor standalone și al signals, iar începând cu versiunea 21, aplicațiile noi sunt zoneless implicit. Detectarea schimbărilor nu mai depinde de zone.js, ci de signals. Tot din versiunea 21, Vitest a devenit runner-ul de teste implicit, iar Signal Forms au apărut ca API experimental.
Alege Angular când: ai o aplicație de business mare, de lungă durată, cu multe ecrane, formulare complexe și mai multe echipe care lucrează pe același cod. Aplicațiile enterprise, back-office-urile și portalurile B2B sunt terenul lui natural.
Vue: drumul de mijloc, cu cea mai blândă curbă de învățare
Vue stă între React și Angular. E mai structurat decât React (are un router și un state management oficial, Pinia), dar mai ușor decât Angular. Single-file components, cu template, script și stil în același fișier, sunt probabil cel mai lizibil format de componentă din toată lista.
Direcția interesantă este Vapor Mode, un mod de compilare fără virtual DOM. Totuși, la momentul scrierii acestui articol, Vapor Mode este complet ca funcționalitate, dar se află încă în release candidate pe linia 3.6, iar versiunea stabilă rămâne 3.5. Așadar este o promisiune pentru viitor, nu un argument de producție astăzi.
Alege Vue când: echipa e mică sau mixtă, vrei productivitate rapidă fără tot aparatul Angular sau vrei să adaugi interactivitate treptat într-o aplicație server-rendered existentă. Vue a fost gândit de la început și pentru acest scenariu.
Svelte și restul: pentru performanță și pentru gustul tău
Svelte compilează componentele în JavaScript care modifică direct DOM-ul, fără runtime greu. Rezultatul: bundle-uri mici și cod foarte concis. Svelte 5 a introdus runes ($state, $derived, $effect), un model de reactivitate explicit, mult mai ușor de urmărit în aplicații mari decât magia din versiunile anterioare. Cu SvelteKit, ai și un meta-framework complet.
Limitarea reală nu e tehnică, ci de ecosistem și piață: mai puține biblioteci, mai puțini oameni de angajat. Pentru o echipă mică ce controlează tot stack-ul, Svelte e o alegere excelentă. Pentru un departament care angajează 20 de frontend-iști pe an, e un risc.
În aceeași zonă de nișă merită să știi de:
- SolidJS — sintaxă asemănătoare cu React, reactivitate fină bazată pe signals, performanță de top.
- Preact — alternativă la React de câțiva KB, utilă pentru widget-uri sau pagini unde fiecare kilobyte contează.
- Lit — pentru Web Components standard. Este ideal pentru design systems care trebuie să funcționeze în aplicații construite cu framework-uri diferite.
- Qwik — construit în jurul ideii de resumability: pagina devine interactivă aproape fără să execute JavaScript la încărcare. Interesant pentru e-commerce, dar cu ecosistem mic.
Meta-framework-urile: când un SPA nu mai e suficient
Un SPA clasic trimite browserului un HTML gol și un bundle JavaScript, apoi construiește pagina pe client. Pentru o aplicație internă în spatele unui login, asta e perfect. Pentru o pagină publică, care trebuie indexată de Google și să apară rapid pe un telefon mediu, e o problemă.
Meta-framework-urile rezolvă problema randând pe server, apoi „hidratând” pagina în browser. Next.js domină în lumea React, Nuxt în lumea Vue, iar SvelteKit și Analog fac același lucru pentru Svelte, respectiv Angular.
Un loc aparte îl ocupă Astro. Pornește de la ideea că majoritatea paginilor de conținut sunt statice, iar interactivitatea trebuie adăugată doar unde e nevoie, în „insule”. Poți folosi componente React, Vue sau Svelte în aceeași pagină, iar restul pleacă în browser ca HTML curat. Pentru bloguri, documentație și site-uri de prezentare, Astro e greu de bătut.
Costul meta-framework-urilor este că frontend-ul devine și el un server. Ai nevoie de Node.js (sau un runtime edge) în producție, iar aplicația ta se transformă într-un sistem cu două backend-uri: ASP.NET Core pentru API și Next.js pentru randare. Pentru o echipă .NET, aceasta este o complexitate operațională reală, care trebuie pusă în balanță.
Blazor: C# până în browser, dar cu decizii proprii
Pentru o echipă .NET, Blazor are un argument greu de egalat: o singură limbă și un singur ecosistem. Aceleași DTO-uri, aceleași reguli de validare, aceleași biblioteci, același debugger. Fără un pipeline separat de npm, fără contracte API duplicate în TypeScript.
Dar „am ales Blazor” nu este o decizie completă. Blazor modern (Blazor Web App, din .NET 8 încoace) are mai multe moduri de randare, iar fiecare are alt profil:
- Static SSR — HTML randat pe server, fără interactivitate permanentă. Seamănă cu Razor Pages, dar folosește modelul de componente Blazor.
- Interactive Server — componenta rulează pe server, iar evenimentele și actualizările circulă printr-o conexiune SignalR. Pornește instant și are acces direct la baza de date, dar fiecare utilizator ține ocupată memorie pe server, iar latența rețelei se simte la fiecare click.
- Interactive WebAssembly — runtime-ul .NET rulează în browser. Scalează excelent și funcționează offline, dar prima încărcare e mai grea decât la un framework JavaScript.
- Interactive Auto — pornește pe server și trece pe WebAssembly după ce runtime-ul s-a descărcat în fundal. Este cel mai bun din ambele lumi, dar cu complexitatea ambelor.
Cea mai importantă calitate a modelului actual este că poți alege modul per componentă: pagini publice statice, un dashboard interactiv pe server, un editor greu pe WebAssembly. Iar .NET 10 a eliminat o parte din durerile cunoscute: scriptul de bază e mult mai mic, resursele WebAssembly se preîncarcă, iar starea componentelor poate fi persistată declarativ între prerendering și randarea interactivă, astfel încât pagina nu mai „clipește” reîncărcând datele.
Punctele slabe rămân reale. Ecosistemul de componente e solid (MudBlazor, Radzen, Fluent UI Blazor, plus suitele comerciale Telerik și Syncfusion), dar e o fracțiune din cel React. Piața de angajare pentru Blazor e mai mică. Iar Blazor Server, oricât de comod, nu e o alegere bună pentru aplicații publice cu mii de utilizatori simultani pe conexiuni mobile instabile.
Alege Blazor când: echipa e preponderent .NET, aplicația este una de business (SaaS B2B, back-office, portal intern), iar valoarea reutilizării codului C# depășește valoarea ecosistemului JavaScript. Pentru aplicații interne pe rețea corporativă, Interactive Server e probabil cel mai productiv mod de a livra UI din tot acest articol.
Razor Pages + HTMX: alternativa subestimată
Există o întrebare pe care multe echipe uită să și-o pună: chiar am nevoie de o aplicație client? Un panou de administrare, un CRUD peste câteva entități sau un flux de formulare nu au nevoie de un framework de componente. Au nevoie de HTML randat pe server și de puțină interactivitate.
HTMX face exact asta. Prin câteva atribute HTML, orice element poate trimite un request și înlocui o bucată din pagină cu HTML-ul primit de la server:
<button hx-post="/counter/increment"
hx-target="#count"
hx-swap="innerHTML">+1</button>
<span id="count">0</span>
app.MapPost("/counter/increment", (CounterService counter) =>
Results.Content(counter.Increment().ToString(), "text/html"));
Nu există bundle, build de frontend sau stare duplicată pe client. Logica, validarea și autorizarea stau într-un singur loc: pe server, în C#. Pentru o echipă .NET care construiește aplicații de business, combinația Razor Pages + HTMX produce adesea cel mai puțin cod cu cea mai mică complexitate. Limita apare când UI-ul devine cu adevărat bogat: drag & drop complex, editare colaborativă, lucru offline. Acolo ai nevoie de stare pe client.
Tabelul de decizie
Iată tot ce am discutat, comprimat într-un singur tabel. Nu e o regulă absolută, ci un punct de plecare pentru discuția din ședința de kickoff.
| Ce construiești | Prima alegere | Alternativă serioasă |
|---|---|---|
| Blog, documentație, site de prezentare | Astro | Razor Pages (SSR) |
| Produs public cu SEO și UI bogat | Next.js sau Nuxt | SvelteKit |
| SaaS B2B, echipă .NET | Blazor Web App | Angular |
| Aplicație enterprise mare, mai multe echipe | Angular | React + reguli interne stricte |
| Back-office, CRUD, panou de admin | Razor Pages + HTMX | Blazor Server |
| Aplicație internă pe rețea corporativă | Blazor Interactive Server | Angular |
| UI foarte interactiv (editoare, canvas, grafice) | React | Svelte |
| Echipă mică, livrare rapidă, stack JS | Vue sau Svelte | React + Vite |
| Widget încorporat în site-uri terțe | Preact sau Lit | Svelte |
Cele cinci întrebări care decid de fapt
Dacă tabelul nu te ajută, întoarce-te la cele cinci întrebări de mai jos. Ele conduc aproape întotdeauna la un răspuns clar.
- Pagina trebuie găsită pe Google și să apară instant pe mobil? Dacă da, ai nevoie de randare pe server: un meta-framework, Astro, Razor Pages sau Blazor Static SSR. Un SPA pur iese din discuție.
- Cine scrie codul, acum și peste trei ani? O echipă .NET care învață React scrie React slab în primul an. Competențele existente valorează mai mult decât orice benchmark.
- Cât de interactiv e UI-ul, de fapt? Majoritatea aplicațiilor de business sunt formulare și tabele. Nu alege un framework pentru 5% din ecrane.
- Cât trăiește aplicația? Pentru un proiect de 10 ani, stabilitatea și convențiile (Angular, Blazor) contează mai mult decât noutatea. Pentru un MVP de validat în trei luni, contează viteza.
- Cât de ușor angajezi? Dacă planul e să crești echipa rapid, piața de React e un argument greu de ignorat. Dacă echipa rămâne mică și stabilă, contează mai puțin.
Greșelile pe care le văd cel mai des
- Alegerea pe baza benchmark-urilor. Diferența de câteva milisecunde între framework-uri nu se observă într-o aplicație de facturare. Un query SQL lent sau un endpoint fără cache se observă.
- Resume-driven development. Alegi tehnologia pe care vrei s-o înveți, nu pe cea de care are nevoie proiectul. Costul îl plătește proiectul, de obicei la mentenanță.
- SPA pentru un site de conținut. Un blog construit ca aplicație React fără SSR e mai lent, mai slab indexat și mai greu de întreținut decât același blog randat pe server.
- Blazor WebAssembly pentru landing page-uri. Un vizitator nou nu ar trebui să descarce un runtime .NET ca să citească trei paragrafe. Folosește Static SSR pentru paginile publice și WebAssembly doar în aplicația din spatele login-ului.
- Două framework-uri fără motiv. Un micro-frontend în Angular lângă unul în React are sens la scară de organizație mare. Într-o echipă de cinci oameni, e doar complexitate dublă.
Recapitulare
Framework-ul de UI nu e o declarație de identitate, ci o decizie de inginerie, cu costuri și beneficii. Pe scurt:
- React are ecosistemul și piața, dar îți lasă toate deciziile ție.
- Angular are structura și stabilitatea, iar versiunile recente, bazate pe signals și zoneless, i-au eliminat o bună parte din greutate.
- Vue și Svelte oferă productivitate și eleganță, cu un ecosistem mai mic.
- Meta-framework-urile și Astro sunt răspunsul când SEO și primul render contează.
- Blazor e alegerea naturală pentru aplicații de business construite de echipe .NET, cu condiția să alegi conștient modul de randare.
- Razor Pages + HTMX e soluția simplă pe care multe echipe o ignoră, deși le-ar rezolva problema cu cel mai puțin cod.
În următorul articol din serie ieșim din browser: desktop și mobil. .NET MAUI, Avalonia, Uno Platform, WPF și WinUI pe partea de .NET, apoi Flutter, React Native, Electron și Tauri. Când merită o aplicație nativă, când e suficient un PWA și cât cod poți împărți, de fapt, între web, desktop și mobil.