Przejdź do treści

Dlaczego nie od razu framework – czasem platformą jest sama przeglądarka

Doszliśmy do najtrudniejszej części. W pierwszej chodziło o bibliotekę, w drugiej o warstwę – tu chodzi o coś, co dla wielu programistów jest już nie wyborem, lecz domyślnym punktem startu: framework.

Nowy projekt zaczyna się dziś zwykle od pytania „React czy Vue?” – a nie od pytania „czy w ogóle framework?”. A to jest dokładnie ten sam odruch, o którym jest cała seria: raz nauczyliśmy się, że poważny front-end robi się we frameworku, i tak zaczynamy każdy projekt, zanim sprawdzimy, czy ten konkretny go potrzebuje.

Chcę od razu uprzedzić nieporozumienie, bo temat jest zapalny: to nie jest tekst „frameworki są niepotrzebne”. Frameworki rozwiązują realne, trudne problemy i w wielu projektach są jedynym rozsądnym wyborem. Pytanie nie brzmi „framework czy nie”, tylko: czy ten projekt ma problemy, dla których framework powstał? – i o to, żeby to była odpowiedź, a nie odruch.

Po co powstały frameworki

React, Vue czy Svelte rozwiązują jeden trudny problem: synchronizację interfejsu ze zmieniającym się stanem. Kiedy w aplikacji jest dużo danych, które zmieniają się w czasie, i wiele miejsc w interfejsie, które muszą na te zmiany reagować, ręczne aktualizowanie DOM staje się koszmarem. Zapominasz odświeżyć jeden widok, dwa stany rozjeżdżają się między sobą, kod puchnie od if-ów pilnujących spójności.

Framework mówi: opisz, jak interfejs ma wyglądać dla danego stanu, a ja zajmę się aktualizacją DOM, kiedy stan się zmieni. To jest prawdziwa wartość i dla aplikacji typu edytor, arkusz, pulpit z danymi na żywo czy panel administracyjny – wartość ogromna.

Zapamiętaj to kryterium: dużo współdzielonego stanu, który zmienia się w czasie. To ono, a nie „powaga projektu”, decyduje, czy framework się przyda.

Co dziś umie sama platforma

Powód, dla którego w ogóle warto zadać pytanie „czy framework?”, jest taki, że przeglądarka przez ostatnią dekadę dostała narzędzia, które kiedyś dawał tylko framework.

Komponenty: Web Components

Reużywalny komponent z własnym stanem i zamkniętymi stylami – flagowy powód sięgania po framework – platforma ma natywnie:

class LicznikKlikniec extends HTMLElement {
    #count = 0;
    connectedCallback() {
        this.innerHTML = `<button>Kliknięto: <span>0</span></button>`;
        this.querySelector('button').addEventListener('click', () => {
            this.#count++;
            this.querySelector('span').textContent = this.#count;
        });
    }
}
customElements.define('licznik-klikniec', LicznikKlikniec);
<licznik-klikniec></licznik-klikniec>

Custom Elements i Shadow DOM (izolacja stylów) są Baseline od lat. To działający, reużywalny komponent bez ani jednej zależności – i użyję go za chwilę w konkretnym przykładzie.

Moduły: system import bez bundlera

Kiedyś dzielenie kodu na pliki wymagało bundlera. Dziś przeglądarka rozumie moduły ES natywnie:

// kalendarz.js
export function nazwaMiesiaca(n) {
    return new Intl.DateTimeFormat('pl-PL', { month: 'long' }).format(new Date(2026, n));
}
<script type="module">
    import { nazwaMiesiaca } from './kalendarz.js';
    console.log(nazwaMiesiaca(5));   // "czerwiec"
</script>

Dla dużych projektów bundler wciąż ma sens (mniej żądań, optymalizacja). Ale dla małego – to jedna rzecz mniej w łańcuchu narzędzi.

Formatowanie i lokalizacja: Intl

Nazwy miesięcy, daty względne, liczby, waluty, sortowanie zależne od języka – wbudowane, bez paczek:

new Intl.DateTimeFormat('pl-PL', { dateStyle: 'long' }).format(new Date());
new Intl.NumberFormat('pl-PL', { style: 'currency', currency: 'PLN' }).format(1234.5);
// "1234,50 zł"

Płynne przejścia: View Transitions

Animowane przejście między stanami czy stronami brało się kiedyś z całego frameworka SPA. Platforma daje to natywnie:

document.startViewTransition(() => zaktualizujWidok());

Wariant w obrębie jednej strony jest Baseline (2025); wariant między pełnymi stronami (dla klasycznego MPA) ląduje w przeglądarkach jako cel Interop 2026 – czyli jeszcze przez @supports.

Konkret: ten blog

Nie chcę, żeby to brzmiało teoretycznie, więc najlepszy dowód mam pod ręką. Strona, którą właśnie czytasz, to statyk zbudowany w Astro, serwujący prawie czysty HTML – bez frameworka runtime po stronie klienta. Interaktywne kawałki, które tu są – przełącznik jasny/ciemny, animacje sortowania i struktur danych, frontowa wyszukiwarka wpisów – to pojedyncze skrypty i Web Components, nie aplikacja SPA.

Efekt: strona ładuje się natychmiast, bo nie ma frameworka do pobrania, sparsowania i uruchomienia, zanim cokolwiek się pokaże. A Lighthouse świeci na zielono właśnie dlatego, że najszybszy JavaScript to ten, którego nie ma.

To była świadoma decyzja podjęta przez to kryterium z początku wpisu: blog to treść, nie aplikacja ze współdzielonym stanem. Nie ma tu dużego stanu do synchronizowania między widokami – więc nie ma problemu, który framework by rozwiązywał. Gdybym budował edytor albo pulpit z danymi na żywo, wybór byłby inny i napisałbym to wprost.

Sekcja uczciwości: kiedy framework to właściwy wybór

Ta seria byłaby nieuczciwa, gdyby nie powiedziała jasno, kiedy odpowiedź brzmi „bierz framework”:

  • Dużo współdzielonego, zmiennego stanu. To główne kryterium. Edytor, arkusz, pulpit z danymi na żywo, złożony wieloetapowy formularz – ręczna synchronizacja DOM tu nie skaluje się i framework zwraca swój koszt z nawiązką.
  • Zespół i utrzymanie. Framework narzuca strukturę, którą zna wielu ludzi. Nowa osoba w projekcie na Reakcie wie, gdzie czego szukać. „Kreatywne” własne rozwiązanie na gołej platformie bywa trudniejsze w utrzymaniu niż standardowy framework, mimo że waży mniej.
  • Ekosystem. Gotowe biblioteki komponentów, routing, zarządzanie stanem, narzędzia deweloperskie – jeśli projekt potrzebuje data-grida, virtual-listy i dwudziestu gotowych komponentów, framework z ekosystemem to oszczędność miesięcy.
  • SSR i hydration na skalę. Renderowanie po stronie serwera ze złożoną interaktywnością to problem, który frameworki rozwiązały porządnie i którego samemu lepiej nie odtwarzać.

Wspólny mianownik znów jest ten sam co w poprzednich częściach: framework jest właściwym wyborem tam, gdzie problem, dla którego powstał, faktycznie jest w projekcie.

Puenta całej serii

Trzy części, trzy poziomy – biblioteka, warstwa, framework – ale jeden mechanizm w tle. Za każdym razem chodziło o to samo: o narzędzie, które kiedyś rozwiązywało prawdziwy problem, a dziś bierzemy je odruchowo, nie sprawdziwszy, czy problem jeszcze istnieje.

Nie napisałem tej serii po to, żeby kogoś namówić na porzucenie jQuery, JavaScriptu czy Reacta. Napisałem ją przeciw jednej rzeczy – przeciw odruchowi. Bo najgorszy powód, żeby czegoś użyć, brzmi „bo zawsze tak robię”, a najgorszy powód, żeby czegoś nie użyć, brzmi „bo to stare”. Jedno i drugie to ten sam błąd: decyzja podjęta przez nawyk zamiast przez pytanie.

Wróciłem myślami do siebie sprzed lat, broniącego Perla przed PHP z pierwszej części. Nie żałuję, że znałem Perl – żałuję, że tak długo nie zadałem sobie pytania, czy to wciąż najlepsze narzędzie do tego, co robię. Cała ta seria to prośba – głównie do samego siebie – żeby zadawać to pytanie częściej. Do starego i do nowego tak samo.