Att stycka en gris

Kristoffer Nordström
Variant Sverige
Published in
6 min readJan 15, 2024

Så, du har återigen fått ärva en kodbas, ett projekt som gått över i förvaltning. Kanske är koden ny, kanske är den gammal? Kanske är den till och med skriven av dig själv! Den är i alla fall full av teknisk skuld och med små utsikter för att få skrivas om inom snar framtid…

Styckningsschema föreställande en gris med delarna: jQuery, Moment, Leaflet, Video.js, Swiper, Slick, main.js, Bulma, Bootstrap
Styckningsschema

Hur går man tillväga för att förbättra denna produkt, förbättra för slutanvändaren och inte minst för dig själv och andra utvecklare som tvingas arbeta med den? Här ska du få några tillvägagångssätt som jag själv brukar använda när jag hamnar i den situationen. I vilken ände börjar man att stycka grisen?

Refaktorering av en stor och gammal kodbas

Lär dig leva med parasiten

I oräkneligt antal projekt jag varit del av har det pratats om att skriva sig bort från jQuery. Dessa projekt är turligt nog minskande. Du stöter ofta på dem när du minst anar det. Jag har ännu inte varit med om ett lyckat försök att bli kvitt jQuery, utan omskrivning av hela kodbasen. Lär dig hellre leva med parasiten jQuery och gör förbättringar på andra områden, det kommer slutanvändaren snabbare till nytta. Tids nog kommer du oavsett skriva om allt från grunden.

Kartlägg terrängen

Börja med att ordentligt kartlägga terrängen. Hur ser kodbasen ut, hur byggs koden samman, vilka tredjepartsberoenden har man, vilka tester och kvalitétssäkrare existerar?

Mätbara mål

Skapa mätbara mål så att du kan se att ditt arbete ger effekt. Lighthouse från Google finns inbyggt i Chrome Devtools men också som CLI om du vill automatisera övervakningen. Här kan du få en baslinje för prestanda med svarstider, Web Vitals, tillgänglighet och sökmotoroptimering — och en del tips på hur dessa kan förbättras.

Lighthouse testresultat på Performance röd 20%, Accessibility grön 100%, Best Practices orange 79%, SEO grön 91%
Testresultat från Lighthouse, före refaktorering

Men du kan också gärna sätta dig andra mål så som hur lång tid ditt bygge tar och därmed stjäl av dina arbetstimmar, antalet tredjepartsberoenden och deras storlek.

Blame game

“Det var en gång en CSS-selektor…”*

Animerad bild som visar en 200 linjer lång CSS-selektor
200 linjer lång CSS-selektor

När man påträffar en tvåhundra linjer lång CSS-selektor är det lätt att ty till fula ord och direkt skriva git blame. Försök att inte klandra människan bakom koden — vi gör alla så gott vi kan, under de förutsättningar vi har — chansen är stor att det är ditt namn som står i marginalen. Det är få människor som alltid gör 100% rätt, för att skapa 1 fel behöver man bara göra fel 1 enda gång. I en kultur där man inte får lov att göra fel utan att hängas ut kommer ingen erkänna ett fel, då kan de redan ha orsakat ännu större skada än om man vågat säga ifrån.

*Baserat på en sann historia, en linje kod och en halvhjärtad code review genererade tvåhundra linjer kompilerad kod. Sensmoral: undersök vad dina ändringar får för effekt på din bundle.

Finn enkla fel

Om det inte redan är satt upp linting bör du få det på plats så snart som överhuvudtaget möjligt. Det hjälper dig att hitta enkla fel och undvika att introducera nya. Fokusera på regler som hjälper till att hindra enkla fel. För JavaScript/TypeScript finns ESLint och för CSS finns Stylelint. På kort sikt i en gammal kodbas kan detta skapa buggar av tidigare “features” men på lite längre sikt hindrar det att nya buggar uppstår.

Enas om en formatering i gruppen, eller om att följa en satt standard exempelvis med Prettier som är ett gott hjälpmedel för att göra koden lättare att läsa.

Finn och ta bort duplicerad kod med exempelvis jscpd.

npx jscpd --pattern "src/**/*.js"

Testning

Om du har tur har någon vänlig själ skrivit tester som gör det möjligt att göra ändringar med självsäkerhet. Men chansen är stor att det inte finns ett enda test, eller kanske bara ett enda…**

it('sums numbers', () => {
expect(3).toEqual(3);
expect(4).not.toEqual(3);
});

Knyt näven i fickan och minns det där om blame game.

Ska du göra större omskrivningar av CSS så kan du sätta upp automatisk visuell testning med Playwright och Sitemapper för att snabbt få kontroll över oanade stilfel.

const { test, expect } = require(‘@playwright/test’);

let sites;

test.beforeAll(async () => {
const Sitemapper = require('sitemapper');
const sitemap = new Sitemapper({
url: 'https://www.yourdomain.com/sitemap.xml'
});
sites = await sitemap.fetch().then(({ sites }) => sites);
});
test('sitemap visual comparison', async ({ page }) => {
for (let site of sites) {
await page.goto(site);
expect(await page.screenshot()).toMatchSnapshot();
}
});

Funktionell testning med Playwright eller Cypress är också ett effektivt sätt att få på plats testning av kritiska delar på system som saknar testning från förr.

**Baserat på en sann historia. Sensmoral: Undersök din testtäckning och om de affärskritiska delarna av systemet faktiskt har tester.

Tillgänglighet

Att säkerställa tillgängligheten är ett måste! Ofta är samma fel reproducerat över flera delar av applikationen och genom att utföra automatisk analys av alla sidor kan du få fram en lista över vilka fel som finns och följa upp hur dina ändringar förbättrar upplevelsen för alla. Det kan du göra med Pa11y CI men glöm inte att dessa analyser bara hittar en liten del av alla fel.

pa11y-ci --sitemap http://www.yourdomain.com/sitemap.xml

Lågt hängande frukter

Hur ser dina JavaScript- och CSS-bundles ut? Undersök dem med exempelvis Webpack Bundle Analyzer för att se vilka delar som är störst så att du kan avgöra vad som bör prioriteras för vidare undersökning. Innehåller de onödigt stora tredjepartsberoenden eller av dig okända paket? Då är det på tid att du ersätter dem av lättare paket eller egenskriven kod. Gör det till en vana att undersöka paket med Bundlephobia före du gör ditt slutliga val att lägga till en ny import.

Nya filformat

Att uppdatera gamla filformat kan vara ett snabbt sätt att korta ned svarstider. Konvertera teckensnitt till WOFF2, video till WebM och bilder till WebP och AVIF. Se bara till att ha en fallback för de som webbläsare som ännu inte stöttar dessa format.

<picture>
<source srcset="photo.avif" type="image/avif" />
<source srcset="photo.webp" type="image/webp" />
<img src="photo.jpg" alt="photo" />
</picture>

Lathet (en dödssynd?)

Se till att icke-kritiska bilder och andra mediafiler inte laddas direkt utan först då de faktiskt behövs.

<picture>
<source srcset="photo.avif" type="image/avif" />
<source srcset="photo.webp" type="image/webp" />
<img src="photo.jpg" alt="photo" loading="lazy" decoding="async" />
</picture>

Undvik att hämtning av teckensnitt blockerar rendering utan hellre visar en fallback.

:root {
font-family: 'MyCustomSerif', serif;
font-display: swap;
}

Om ditt bygge producerar stora sammanpackade filer med JavaScript kan du dela upp dessa i mindre bitar så att delarna kan laddas ner parallellt, först när de behövs eller inte alls om de inte används på en given sida. Ett bra exempel på det är kart- eller videobibliotek som både är stora och kanske bara används på enstaka sidor. Exakt hur du gör detta beror på vilket byggsystem du använder för att sätta samman din kod (tips sök efter code splitting och lazy loading).

Resultat

Kom ihåg att kontinuerligt se tillbaka på dina tidigare uppsatta mål och mätpunkter för att se och kunna jämföra vilken effekt dina förändringar ger! Visa fram dina resultat för teamet och fira den snabbare svarstiden, byggtiden, tillgängligheten eller vad du lyckats förbättra…

Lighthouse testresultat på Performance grön 93%, Accessibility grön 100%, Best Practices grön 92%, SEO grön 100%
Testresultat från Lighthouse, efter refaktorering***

Lycka till med din refaktorering, jag vet att du klarar av det! 🤗

En röd dansk pølse med bröd, rostad lök och ketchup
Belöning efter hårt arbete

**Baserat på en sann historia. Sensmoral: Det finns alltid hopp om att blåsa nytt liv i gamla kodbaser.

--

--