Teknik
TypeScript - från obskyrt till självklart
TypeScript har växt och är ett närmast oumbärligt verktyg vid frontendutveckling.
På Limetta har vi börjat använda oss av utvecklingsplattformen Vite i våra senaste frontendprojekt. Vi har inte valt det bara för att det är nytt och coolt utan vårt val är sprunget ur ett högst konkret behov: hastighet.
Fram till nu har Limetta uteslutande arbetat i utvecklingsmiljöer som bygger på Webpack och Node. Det har fungerat bra och vi har för det mesta varit nöjda. Vi lade dock märke till att ju större projekten blev, desto längre tid tog det att starta dem och jobba i dem. Det är inte så konstigt eftersom många filer med mycket kod betyder mer jobb för transpilatorer och byggscript. Mer jobb innebär längre byggtider. Vi pratar fortfarande tid i termer av sekunder, men 20 sekunder är en lång tid när man arbetar i korta iterationscykler, vilket ofta är fallet i frontendprojekt.
Problemet med webpackbaserade byggplattformar är att de transpilerar och bundlar (i stort sett) all kod varje gång man sparar en fil även om utvecklaren bara har varit inne och ändrat i en enda modul. Koden bundlas (buntas ihop) i en eller ett par stora filer (chunks) som sedan skickas i sin helhet till webbläsaren. I samband med det måste byggplattformen också avgöra vad som ska bundlas, sk. dependecy resolving, vilket tar mycket tid i anspråk.
I Vite har man tänkt annorlunda. Ingen kod bundlas under det att man utvecklar. I stället har man redan från början byggt in stöd för ESM (ECMAScript Modules), som är den officiella standarden för att paketera javascriptkod i moduler. ECMAScript-moduler har den stora fördelen att moderna webbläsare förstår deras struktur och kan läsa koden för att ta reda på om en viss modul i sin tur är beroende av andra moduler. Så i stället för att serva en enda stor javascriptfil servar Vite en eller flera små ECMAScript-moduler. Om webbläsaren upptäcker att en viss modul är beroende av en annan modul hämtar den andra modulen också automatiskt. Detta innebär i slutänden att bara den kod som webbläsaren anser att den behöver skickas.
Den inbyggda utvecklingsservern i Vite tar emot alla anrop från webbläsaren och ser till att serva de filer som webbläsaren vill ha. Om det finns kod som måste transpileras (översättas) innan den kan skickas till webbläsaren, t.ex. kod skriven i TypeScript, SCSS eller JSX så ser Vite till att detta görs innan den skickar tillbaka ett svar till webbläsaren. Transpileringen sköts i sin tur av esbuild som är extremt snabbt (mer om esbuild nedan).
I senare versioner av Node finns det förvisso också stöd för ESM, men i Node används sedan tidigare även en annan standard som heter CommonJS. Att få CommonJS och ESM att samexistera i Node är väldigt bökigt och man riskerar att lägga mer tid på att fixa problem än på själva projektet. Kanske kommer detta att fungera bättre i framtiden?
I Vite finns även något som kallas Hot Module Replacement (HMR). Det innebär att man kan byta ut delar av koden i en applikation som körs i webbläsaren utan att behöva ladda om hela applikationen. Man kan se det som en digital motsvarighet till att operera med lokalbedövning, utan att behöva söva patienten. HMR finns även i Webpack, men man tvingas bundla och byta ut mycket större moduler vilket påverkar prestandan. För utvecklaren innebär Hot Module Replacement att webbläsaren uppdaterar den vy man sitter och jobbar med automatisk så fort man sparar den kod man har uppdaterat. När man sitter och arbetar i Vite så ändras vyn direkt när man har sparat filen.
I Vite har man har byggt in stöd för esbuild för att hantera något som kallas för pre-bundling på ett effektivt sätt. När man startar ett Viteprojekt första gången så kommer det att tugga igenom all kod i projektet, inklusive kod från tredjepartsutvecklare som hämtas in via Node Packet Manager (NPM). Om det finns kod som inte bygger på ESM, utan någon annan moduldefinition, till exempel AMD (Asynchronous Module Definition) eller CommonJS (som är vanlig i Node), så kommer Vite att använda esbuild för att konvertera sådan kod till ECMAScript-moduler. Det måste den göra eftersom Vite bygger på ESM och bara servar ECMAScript-moduler. Pre-bundling är alltså ett sätt att förbereda all kod i projektet för att kunna användas som ESM i Vite.
Esbuild i sin tur är en javascriptbundler som har utvecklats i Go. Go är ett kompilerat programmeringsspråk som närmast kan liknas vid en modern kusin till programmeringsspråket C. Att det är ett kompilerat språk och dess släktskap med C innebär att det går att skriva riktigt snabba program i det. Och esbuild är ruskigt snabbt!
Hittills har vi bara pratat om hur Vite fungerar under det att man utvecklar applikationen. Men förr eller senare kommer man vilja bygga ut all kod till en färdig lösning som man kan lägga upp på en testserver eller sätta i produktion.
Som vi har varit inne på så bundlar Vite ingenting utan servar enbart ECMAScript-moduler. Det är bra under det att man utvecklar, men opraktiskt och ineffektivt när man ska köra applikationen live. Så inför lanseringen av en applikation vill man bundla all kod och samtidigt passa på att göra en massa andra saker, till exempel transpilera, komprimera och optimera kod och dela upp koden i olika block (chunks). För att kunna göra detta har man plockat in en bundler som heter Rollup. Den tar alla ECMAScript-moduler och buntar ihop dem till en eller flera större filer och kan dessutom genom plugins tillhandahålla funktionalitet för allt extra man vill göra i samband med bundling (komprimering, optimering etc.).
Vite säger själva att Rollup är en lösning som man har valt i väntan på att esbuild ska blir bättre på att bundla kod. Till exempel kan man i esbuild inte få till bra CSS-hantering eller uppdelning av kod i chunks. Just dessa delar fungerar inte tillfredsställande i esbuild idag.
I frontendvärlden avlöser plattformarna, verktygen och biblioteken varandra hela tiden. Precis när man har vant sig vid en lösning kommer en ny bättre och snabbare lösning. Byggplattformen Grunt (2012) ersattes av Gulp (2013) och Webpack (2014). Den första stabila versionen av Vite släpptes 2021.
Vågar man verkligen använda ett verktyg som inte ens har funnits ett år i stabil version?
Den frågan ställer vi oss varje gång det kommer något nytt. För att besvara den använder vi oss av massor av indikatorer för att avgöra om det är något vi ska gå in i eller inte:
Bakom Vite står Evan You, skaparen av javascriptramverket Vue. Det är bra både som garant för att koden är livskraftig och att den får god spridning. Vite löser något som är ett verkligt problem för oss: hastighet i byggjobb. Det har runt 400 000 nedladdningar per vecka och 35 000 stjärnor på GitHub och på vitjs.dev finns bra dokumentation. Våra första egna tester visar att det fungerar som det ska och vi ser avsevärt förbättrad prestanda. Sammantaget gör det att Vite är något vi ska och bör testa vidare. Framför allt är vi intresserade av att se hur det beter sig i riktigt stora projekt, något som vi kommer att testa under 2022.
Samtidigt vet vi att det pågår en ständig kamp om vem som ska vara herre på täppan. Det är ingen dum gissning att man i lägret kring Webpack börjar känna sig nafsad i hasorna av Vite och förhoppningsvis kommer att prioritera prestanda i det framtida utvecklingsarbetet. Allt detta är bra för oss och våra kunder. Konkurrens driver på utvecklingen och vi kan leverera effektivare lösningar med automatisering som exekveras snabbt.
Slutsatsen är att oavsett vem som är störst, bäst och vackrast just nu så tjänar alla på att man vågar utforska ny teknik. Utvecklare vill arbeta i miljöer där de slipper vänta på tråkiga byggjobb och kunder vill att vi utnyttjar tiden optimalt för att lösa just deras utmaningar. Det ska bli riktigt spännande att se hur Vite utvecklas framöver och Limetta är gärna med!