Gdy aplikacja webowa ma działać szybko po stronie przeglądarki, a zespół zna C# i .NET, Blazor WASM staje się naturalnym kandydatem. Wyjaśniam, jak działa ten model hostowania, czym różni się aplikacja samodzielna od rozwiązania z backendem, gdzie pojawiają się koszty i ograniczenia oraz kiedy taki wybór ma sens w praktycznym projekcie.
Najważniejsze decyzje dotyczące aplikacji Blazor WebAssembly
- Kod działa w przeglądarce dzięki środowisku .NET uruchamianemu przez WebAssembly.
- Aplikacja standalone może być wdrożona jako zestaw plików statycznych na CDN lub prostym hostingu.
- Wariant hosted łączy frontend WebAssembly z ASP.NET Core, API, uwierzytelnianiem i wspólnym kodem.
- Pierwsze ładowanie bywa cięższe niż w aplikacji serwerowej, dlatego duże znaczenie mają kompresja, cache i trimming.
- Wrażliwy kod i sekrety muszą pozostać na serwerze, ponieważ kod wysłany do przeglądarki można analizować.

Na czym polega model Blazor WebAssembly
W tym modelu komponenty Razor i kod C# są uruchamiane bezpośrednio w przeglądarce użytkownika. Przeglądarka pobiera środowisko .NET, biblioteki aplikacji oraz pliki komponentów, a potem wykonuje je w bezpiecznym środowisku WebAssembly.
To zmienia przepływ działania interfejsu. Kliknięcie przycisku, walidacja formularza czy zmiana stanu komponentu nie musi za każdym razem oznaczać żądania do serwera. Interakcja odbywa się lokalnie, więc aplikacja może reagować płynnie nawet wtedy, gdy backend nie obsługuje każdego zdarzenia.
Nie oznacza to jednak, że backend znika. W większości realnych systemów przeglądarka komunikuje się z API przez HTTP, gRPC-Web albo SignalR. WebAssembly odpowiada za interfejs i logikę kliencką, natomiast serwer nadal chroni dane, wykonuje operacje biznesowe i rozmawia z bazą danych.
Przeczytaj również: JavaScript case - jak uniknąć błędów wielkości liter?
Co trafia do przeglądarki
Do klienta trafiają między innymi biblioteki .NET, kod aplikacji, zależności oraz zasoby statyczne. Publikacja usuwa część nieużywanego kodu, a kompresja i cache przeglądarki ograniczają koszt kolejnych uruchomień. Mimo to pierwsze wejście może wymagać pobrania większego pakietu niż klasyczna strona HTML.
Trzeba też pamiętać o granicy bezpieczeństwa. Kod wykonywany po stronie klienta można pobrać, zdekompilować i analizować. Nie umieszczam więc w projekcie WebAssembly haseł, kluczy API ani reguł, których ujawnienie pozwoliłoby ominąć autoryzację.
Dwa warianty wdrożenia, które często się myli
Najprostsza wersja to aplikacja samodzielna. Jest budowana do statycznych plików i może być serwowana przez CDN, Azure Static Web Apps, nginx albo inny serwer plików. Po pobraniu aplikacja nie potrzebuje procesu .NET po stronie hostingu, choć może oczywiście korzystać z zewnętrznego API.
Druga możliwość to aplikacja hostowana przez ASP.NET Core. Frontend nadal wykonuje się w przeglądarce, ale backend może dostarczać pliki, obsługiwać API, uwierzytelnianie, logowanie, integracje i wspólne biblioteki. W praktyce ten wariant wybieram częściej przy systemach biznesowych, bo upraszcza kontrolę nad całym rozwiązaniem.
| Obszar | Aplikacja samodzielna | Aplikacja z ASP.NET Core |
|---|---|---|
| Hosting | Pliki statyczne, CDN, prosty serwer | ASP.NET Core lub wspólne środowisko chmurowe |
| Backend | Osobne API albo usługi zewnętrzne | API może działać w tej samej aplikacji |
| Skalowanie frontendu | Bardzo proste, często przez CDN | Zależy także od konfiguracji serwera |
| Wspólny kod | Możliwy przez biblioteki współdzielone | Naturalne współdzielenie modeli i kontraktów |
| Najlepsze zastosowanie | Panele, narzędzia offline, proste SPA | Systemy biznesowe, SaaS, aplikacje z własnym API |
W starszym nazewnictwie często spotkasz określenie hosted Blazor WebAssembly. Dziś podobny efekt można uzyskać również w Blazor Web App, wybierając interaktywny tryb WebAssembly dla konkretnych komponentów. To ważne rozróżnienie, bo nie każda nowa aplikacja musi być w całości klientowym SPA.
Jak wybrać między WebAssembly, Server i trybem Auto
Wybór modelu nie powinien zaczynać się od pytania, który framework jest modniejszy. Zaczynam od przepływu danych, wymagań dotyczących SEO, długości pierwszego ładowania i tego, czy użytkownik może pracować przy niestabilnym połączeniu.
| Kryterium | WebAssembly | Blazor Server | Interactive Auto |
|---|---|---|---|
| Miejsce wykonywania kodu | Przeglądarka | Serwer | Serwer na początku, potem klient |
| Pierwsze ładowanie | Zwykle cięższe | Zwykle lekkie | Szybka odpowiedź i późniejsze pobranie klienta |
| Zależność od stałego połączenia | Mniejsza po pobraniu aplikacji | Duża, zwykle przez SignalR | Zależy od aktualnego trybu |
| Dostęp do sekretów i zasobów serwera | Przez kontrolowane API | Bezpośrednio po stronie serwera | zależy od miejsca wykonania komponentu |
| Typowy scenariusz | Bogate SPA i praca offline | Aplikacja wewnętrzna i szybki start | Nowoczesna aplikacja mieszająca oba podejścia |
Tryb interaktywny WebAssembly sprawdza się tam, gdzie komponent ma wykonywać dużo pracy lokalnie. Tryb serwerowy bywa lepszy dla formularzy administracyjnych i aplikacji, w których ważniejsze są mały payload oraz centralna kontrola. Interactive Auto może połączyć szybki początek z późniejszą pracą klientową, ale zwiększa złożoność rozwiązania i wymaga świadomego podziału komponentów.
Moja praktyczna zasada jest prosta. Dla małego panelu firmowego nie komplikuję projektu WebAssembly tylko dlatego, że używamy C#. Dla rozbudowanego interfejsu, który ma wykonywać wiele operacji po stronie użytkownika, ograniczać ruch do API albo działać częściowo offline, ten model zaczyna mieć wyraźną przewagę.
Wydajność zależy bardziej od paczki niż od samej technologii
Najczęstsze rozczarowanie pojawia się przy pierwszym uruchomieniu. Użytkownik widzi ekran ładowania i czeka, aż przeglądarka pobierze runtime oraz zależności. Późniejsze wizyty mogą być znacznie szybsze dzięki cache, ale pierwszy kontakt z aplikacją trzeba zaprojektować osobno.
Największą różnicę robią konkretne działania:
- włączenie kompresji Brotli lub gzip dla zasobów statycznych,
- usuwanie nieużywanego kodu podczas publikacji,
- dzielenie dużych funkcji na ładowane na żądanie moduły,
- ograniczenie liczby ciężkich bibliotek UI,
- prawidłowe nagłówki cache dla plików, które mają wersjonowane nazwy,
- mierzenie rozmiaru katalogu
_frameworki czasu do pierwszej interakcji.
Kompilacja AOT może przyspieszyć wykonywanie kodu .NET, szczególnie przy obliczeniach, ale często zwiększa rozmiar aplikacji i czas publikacji. Nie włączam jej automatycznie. Najpierw sprawdzam profil użytkownika i charakter obciążenia, bo szybszy kod po pobraniu nie zawsze oznacza szybszą aplikację.
WebAssembly nie jest też uniwersalnym zamiennikiem JavaScriptu. Interop z JavaScriptem nadal bywa potrzebny przy API przeglądarki, bibliotekach map, edytorach czy płatnościach. Dobrze napisany projekt ogranicza tę granicę do kilku adapterów, zamiast mieszać kod JS i C# w każdym komponencie.
Backend, uwierzytelnianie i bezpieczeństwo bez skrótów
Frontend WebAssembly powinien traktować API jak jedyną zaufaną bramę do danych. Walidacja w komponencie poprawia komfort użytkownika, ale nie zastępuje walidacji po stronie serwera. Każdy klient może zmodyfikować żądanie, pominąć interfejs i wywołać endpoint własnym narzędziem.
W aplikacjach z logowaniem najczęściej spotkasz tokeny dostępu, cookies albo rozwiązania oparte na OpenID Connect. Wybór zależy od architektury i dostawcy tożsamości. Przy tokenach trzeba dobrze zaplanować ich przechowywanie, odświeżanie i zakres uprawnień. Nie wkładam tokenu o szerokich uprawnieniach do kodu, który ma dostęp do całej platformy.
Dobrym wzorcem jest współdzielenie kontraktów API, ale nie całej logiki bezpieczeństwa. Modele DTO, enumy i reguły mapowania mogą trafić do wspólnej biblioteki. Reguły decydujące o tym, czy użytkownik może usunąć fakturę albo pobrać dane innej firmy, powinny pozostać po stronie serwera.
Warto również przetestować obsługę błędów i utraty połączenia. Aplikacja klientowa może wyświetlić ostatni stan, kolejkę operacji albo komunikat o konieczności ponowienia żądania. Nie zakładam, że internet będzie stabilny, szczególnie w aplikacjach używanych na laptopach, tabletach i urządzeniach mobilnych.
Gdzie ten model sprawdza się najlepiej
Blazor WebAssembly dobrze pasuje do aplikacji, w których użytkownik spędza dużo czasu w jednym interfejsie. Panel sprzedażowy, system magazynowy, konfigurator produktu czy narzędzie analityczne mogą skorzystać z lokalnego stanu, bogatych formularzy i ograniczenia liczby przeładowań strony.
Dobrym przypadkiem jest kalkulator ofertowy. Użytkownik zmienia parametry, a wynik przelicza się natychmiast w przeglądarce. Do serwera trafia dopiero zapis gotowej oferty lub zapytanie o dane referencyjne. Mniej żądań nie oznacza mniejszego bezpieczeństwa, jeśli serwer ponownie sprawdza wszystkie wartości przy zapisie.
Drugim przykładem jest aplikacja terenowa z trybem PWA. Po wcześniejszym pobraniu części zasobów może działać przy słabym połączeniu, przechowywać dane lokalnie i synchronizować je później. To wymaga jednak świadomego rozwiązania konfliktów, wersjonowania danych i obsługi sytuacji, w której dwóch użytkowników zmieni ten sam rekord.
Nie wybierałbym tego modelu jako pierwszej opcji dla bardzo prostej strony contentowej, gdzie liczą się minimalny payload i natychmiastowy dostęp do treści. W takim przypadku statyczny HTML, Razor Pages albo SSR może dać lepszy efekt przy mniejszej liczbie elementów do pobrania.
Jak zacząć projekt, żeby nie żałować decyzji
Na początku tworzę mały prototyp z jednym ekranem, jednym wywołaniem API i przykładowym logowaniem. Mierzę rozmiar publikacji, czas pierwszego uruchomienia oraz zachowanie aplikacji przy wolnej sieci. Taki test w kilka godzin mówi więcej niż długie dyskusje o samych zaletach frameworka.
W projekcie produkcyjnym pilnuję przede wszystkim kilku granic:
- komponenty odpowiadają za interakcję i prezentację,
- serwisy klienckie obsługują komunikację z API,
- backend przechowuje sekrety i podejmuje decyzje biznesowe,
- kontrakty są wersjonowane, gdy z aplikacji korzystają różne wersje klienta,
- monitoring mierzy błędy zarówno przeglądarki, jak i serwera.
Nie pomijam też ścieżki wdrożenia. Aplikacja statyczna może być bardzo tania w utrzymaniu, ale trzeba skonfigurować fallback routingu do pliku startowego, poprawne nagłówki cache, HTTPS i politykę CORS dla API. W rozwiązaniu hostowanym odpada część tych problemów, lecz pojawia się odpowiedzialność za skalowanie i aktualizacje backendu.
Największy błąd polega na traktowaniu WebAssembly jako sposobu na przeniesienie całej aplikacji do przeglądarki. To model wykonywania interfejsu, a nie zamiennik serwera, bazy danych ani warstwy bezpieczeństwa. Gdy ten podział jest jasny, architektura staje się przewidywalna.
Najlepszy wybór zależy od pierwszych sekund i granic zaufania
Blazor WebAssembly ma sens wtedy, gdy zespół chce budować bogate aplikacje webowe w C#, a interfejs może wykonywać znaczną część pracy po stronie klienta. Największe korzyści dają lokalna interakcja, współdzielenie kodu .NET, możliwość wdrożenia statycznego oraz ograniczenie obciążenia serwera.
Jednocześnie trzeba zaakceptować większy koszt pierwszego ładowania, ograniczenia środowiska przeglądarki i fakt, że kod klienta nie jest tajemnicą. Przed wyborem sprawdzam więc dwie rzeczy: ile użytkownik może czekać na start oraz które operacje muszą pozostać pod kontrolą serwera. Odpowiedzi na te pytania zwykle prowadzą do właściwego wariantu szybciej niż sama lista funkcji frameworka.
