Blazor - Frontend med C#
Framväxten av web-frontend
Jag har jobbat som utvecklare i 25 år. I första hand har jag hållit mig inom Microsoft-sfären och skrev kod långt innan .Net fanns. När webben växte fram så började jag med ASP. Det var coolt att skriva script som blandades med HTML.
Jag har nog haft min tyngdpunkt på backendkod men har alltid tyckt att frontend var intressant. Det är ju trots allt där man kommunicerar med användare och skapar mycket av deras upplevelse. Jag lärde mig HTML och CSS hyggligt, men tyckte det kändes begränsat att göra snygg UX när man alltid var tvungen att jobba med det detachade state som en websida alltid innebär. Round-trips till servern är varken snabbt eller snyggt.
När javascript i olika former började bli användbart så hände det något. Nu kunde man skriva kod på frontend och skapa en hel del funktionalitet direkt i browsern! Men frontend känns ändå som en viss tröskel. Det är i praktiken en helt egen värld där allt fungerar rätt annorlunda jämfört med backend. Det är ett annat språk och en osäker värld där man aldrig kan ta något för givet. Man vet aldrig riktigt i vilken miljö ens kunder sitter i. Har de en browser som kan det man ville? Om man hittar ett paket i NPM med bra funktionalitet så kan man aldrig vara riktigt säker på att det fungerar i morgon.
Efter ett tag har frontend-världen stabiliserats med några plattformar som står kvar som vinnare. Angular, React och Vue är nu de trygga val som många samlas kring.
Frontend utmaningen
- Frontend är fortfarande en utmaning eftersom det är ganska komplexa ekosystem. De ändrar sig ofta med täta releaser som ofta innehåller breaking changes. Det kräver en del att hänga med i den ständiga förändringen.
- Många team vill gå mer mot fullstack upplägg där man följer sin funktionalitet rakt igenom applikationen. Men i praktiken är det svårt att upprätthålla riktigt hög kompetens för både backend och frontend. Det vore önskvärt att ha en mer samlad utvecklingsmiljö, gärna att man kan koda i samma språk och med samma mönster på frontend och backend.
- En helt annan aspekt är att belastningen på systemen ökar. I en global värld så ökar antalet användare snabbt och oberäkneligt. Kraven på serversystem blir snabbt rätt höga. När man behöver riktigt bra prestanda så vore det önskvärt att kunna skjuta ner en del av processandet till klienterna som ofta har rätt mycket kraft.
Webassembly
En ny teknik som smugit upp de senaste åren kallas webassembly. Det innebär att man skapar kompilerad kod som körs i browsern. Det blir därmed väsentligt snabbare än javascript. W3C som styr all webstandard ansvarar även för denna teknik. Redan 2017 enades man om en standard för hur detta ska gå till. Alla stora webläsare har i dag bra stöd för webassembly.
Men eftersom webassembly är kompilerad så är det inget man skriver på något enkelt sätt direkt själv. Fördelen är å andra sidan att man i princip kan skriva i vilket språk man vill så länge det finns en kompilator som kan omvandla det till körbar webassembly kod.
Jag skulle säga att alla som jobbar med web i dag bör lära sig vad webassembly är. Min spaning är att det kommer att förändra webutveckling en hel del.
Blazor
Det låter intressant, men hur gör man i praktiken? Snabbt låter bra, men man skriver ju inte kompilerad kod hur som helst.
2017 läste jag om en idé som någon på Microsoft hade att man skulle kunna skriva kod i vanlig C# och kompilera det till webassembly som sedan kunde köras direkt i browsern. Det lät som en kul fantasi som låg rätt långt fram i tiden. I maj 2019 var jag på NDC i Oslo och lyssnade bland annat på Steve Sanderson som drev ett litet projekt inom Microsoft som han kallade Blazor. Namnet kom av att man skriver sina sidor i Razor och sedan kompilerar det till snabb webassembly. Blazor = Blazing fast Razor. För dem som inte stött på Razor så är det en Microsoft teknik där man skriver HTML-sidor med insprängd C# kod. De exekveras sedan på servern och renderar vanlig HTML som skickas till klienten. Det är en hygglig bra teknik som blivit ganska populär eftersom den är enkel och robust.
I mitt tycke var Steves föredrag det bästa på konferensen och jag började ana att Blazor skulle kunna bli något mycket intressant. Men det fanns fortfarande rätt stora begränsningar och var rätt omoget. En rätt stor nackdel var t.ex. att man var tvungen att skicka med hela .Net Framework runtime som webassembly kod för att kunna köra sin applikation. Det gav en nätt liten extra download på 30 MB. Det är inte precis något man skickar ut till vilka klienter som helst!
Dotnetconf
På Dotnetconf, nu i november 2020, så lanserade Microsoft .NET 5.0. Det är ett stort steg i deras strävan mot en gemensam plattform där hela .Net stacken ska bli tillgänglig för både Windows, Mac och Linux. Det var nog en av de största releaserna jag sett under min tid som utvecklare och innebär stora förändringar på många områden. Blazor var med som en av de stora attraktionerna. Man har lyft upp projektet och gett det mycket fokus som det kanske mest intressanta sättet att skriva modernt webgränssnitt på .NET stacken.
Tekniskt
.NET 5.0 har fört med sig några viktiga saker som var nödvändiga för att Blazor skulle kunna lyfta och bli intressant. Dels så har man gjort om hela sitt framework från botten och hela vägen upp med bättre struktur och stora prestandaökningar. Det finns nu också möjlighet för kompilatorn att avgöra vilka delar av ramverket som faktiskt används av koden och bara inkludera det som behövs. Det liknar mycket det som javascript ramverk brukar kalla tree-shaking. Det ger förstås en rejäl minskning av hur mycket som behöver laddas ner till klienten. De 30 MB som man först fick i en typisk SPA applikation är nu nere på 2 MB. Det är fortfarande rätt mycket, men balanserat mot de övriga vinsterna kan det i många fall vara värt det.
Strukturen med att bygga sin frontend i väl avgränsade komponenter har blivit ganska etablerad genom React, Angular och Vue. Precis samma uppbyggnad används i Blazor.
Mycket annat som man önskar finns med från början: Debugging i både backend och frontend, CSS isolation, Token-Based Authentication, Localization och Time Zone support.
En sidoeffekt av att använda C# är att man nu kan skapa unit-test för frontend lika enkelt som på backend. För mig har toolingen kring frontend tester varit en stor nackdel som ofta fått mig att hoppa över tester.
En viktig sak att förstå är att en Blazor applikation konfigureras att antingen köras som Blazor WebAssembly eller som Blazor Server. I det första fallet laddar man ner en större mängd kod till sin browser och kör den där. Det är lämpligt för applikationer som kräver mycket logik och prestanda på klienten och inte behöver kommunicera så mycket med servern. En serverside applikation genererar det mesta på servern men låter all logik i klienten ske genom kommunikation till servern. Klienten består av ren HTML med javascript webhooks som genereras automatiskt. För att få hög hastighet i kommunikationen så används websockets via inbyggd SignalR vilket ger hög hastighet med minimal latency. Denna variant kräver ingenting av klienten men belastar servern med litet minne per aktiv klient för att hålla SignalR kommunikationen uppe. Kraven är dock inte så jättehöga. Med 1 CPU och 4 MB RAM klarar man 5000 samtidiga klienter. För en längre redogörelse av skillnaderna mellan de två hosting modellerna kan man med fördel läsa denna artikel: Blazor Server vs. Blazor WebAssembly
Blazor bygger normalt på att man designar med SPA mönstret (Single Page Application) där all klientkod laddas ner tillsammans och sedan kan visa olika "sidor" med klient routes utan att anropa servern. Vill man ta detta ett steg vidare så kan man göra en PWA (Progressive Web Application). Det innebär att applikationen fungerar mer som en separat fristående applikation:
- Den kan köras utanför webläsaren och startas som en vanlig applikation.
- Den kan ta emot push-notiser från servern.
- Den kan köras helt frånkopplad, utan kontakt med servern.
- Den kan ha automatisk uppdatering.
Blazor har fullt stöd även för PWA.
Hur fungerar det då i praktiken?
Det är förvånansvärt trevligt!
Det finns fortfarande en del begränsningar. Tooling och intellisens är inte perfekt. Vissa saker känns enklare för mig att göra i Visual Studio som har bra integration mot t.ex. Azure. Men mer och mer märker jag att jag skriver stora delar av koden via VS Code som ju generellt är ett snabbare gränssnitt.
Man ska också inse att det är ett nytt paradigm. Man skriver inte Blazor på samma sätt som man skrev webforms eller MVC applikationer. Men om man testat på någon av de nya frontend ramverken och fått in känslan för att jobba med komponenter, routes och state så kommer man att kunna behålla mycket av samma tänk.
Alla mina egna hobbyprojekt kommer definitivt att använda Blazor. Det går snabbt och smidigt att använda. Det är verkligen underbart att slippa den onaturliga uppdelningen av frontend och backend. Bara en så enkel sak som att modeller är gemensamma. Man behöver inte hålla på att skapa parallella objekt i TypeScript och C# som ska hållas i synk och översättas fram och tillbaka med serialisering av JSON. Hjälpklasser och logik kan också delas där det behövs. Hur länge har jag inte längtat efter att använda vanliga lambda-uttryck med LINQ i min frontend? Nu är det lika enkelt att använda överallt.
Jag tror inte det är värt att göra om stora kundprojekt till Blazor. Men det går definitivt att använda på riktigt redan nu. Jag tycker att man snart bör testa det på mindre avgränsade kundprojekt för att bygga upp en förståelse och testa på tekniken. Även större projekt som ska påbörjas under 2021 bör ha med Blazor som ett mycket intressant alternativ. Att använda samma kompetens och teknik på frontend och backend är en ganska stor framgångsfaktor som jag inte tror att man ska underskatta.