21 May 2018

CSS-treeshaking med PurgeCSS

Som webudvikler benytter man typisk et CSS-framework som Bulma, Bootstrap eller Foundation, når man udvikler hjemmesideprojekter.
I hvert fald når det kommer til projekter hvor man med fordel kan drage nytte af allerede eksisterende funktionalitet der har en stor grad af stabilitet og som er fri for bugs/uhensigtsmæssigheder, da det allerede er trykprøvet igennem implementering i utallige andre projekter på tværs af projekttyper. Ligesom det derudover typisk også vil reducere udviklingstid, fordi man ikke skal "genopfinde" den dybe tallerken for hvert nyt projekt, man påbegynder.

Når man inddrager fulde CSS-frameworks i sit udviklingsprojekt, er der dog samtidig stor sandsynlighed for at man kun benytter en delmængde/en underdel af de CSS-klasser som frameworket inkluderer i sine kernefunktionalitet (e.g. gridsystem, form-controls, elementer) og sin komponentmodularitet.

Omtanke og moderne kompositions-workflows er til en hvis grad med til at afhjælpe udfordringen, da de fleste frameworks i forvejen er »bundled« og man via importkontrol selv kan vælge, hvilke dele af frameworkets kernefunktionalitet og komponenter der skal inkluderes i et givent projekts »asset build pipeline«.

Men, medmindre man selv sørger for at vedligeholde en optimeret fork af det CSS-framework som benyttes i projektet, eller man benytter sig af projektbaserede ressourcefiler med cherry-picking af delelementer, vil man alligevel typisk ende med at inkludere CSS-klasser i sit production build, der indeholder CSS som ikke er i brug.
Ligesom et projekts omskiftelighed kan føre til at CSS-klasser der tidligere har været brugt ikke bliver fjernet fra projektfilerne når markup refaktoreres, hvorfor man ender med at have gammel og ikke-benyttet kode i sit projekt (»stale code«).

Projektfiler med ikke-benyttet kode bør undgås, og i dette tilfælde er CSS-klasser i udgangspunktet analogt til kode der styrer applikationslogik: Hvis man ikke er nidkær med at fjerne ikke-brugt kode, når der refaktoreres, vil det uundgåeligt (i hvert fald for projekter som er ud over hobby niveau) føre til »technical debt« på et senere tidspunkt.

Et andet problem med ikke-brugt CSS er, ligesom med andre ubenyttede assets, at det formentligt vil øge en hjemmesides load time og øge den gennemsnitlige request-tid.

Hvor den første udfordring ovenfor bedst løses med rettidig omhu under udviklingen af projektet, så kan den sidste udfordring relativt nemt løses ved at tilføje et ekstra skridt til sit kompositions-workflow: Her kommer Purgecss til redning.

Purgecss fungerer ved at lave en træstruktur over indholdet af et webprojekts CSS-filer for derefter at scanne projektets strukturfiler (filer som indeholder HTML) og via sammenligning fjerne ikke-brugte CSS-klasser fra de endelige build-filer.
Dette sikrer mindre CSS-filer.

Som eksempel kan nævnes at den samlede, pakkede CSS-fil tilhørende denne hjemmeside, season.dk, er henholdvis 218kb uden inklusion af Purgecss i sidens CI-build-steps, og 10,7 kb ved inklusion af Purgecss. Det skal dog nævnes, at det at benytte denne side som et generelt eksempel måske er en smule skævt, da denne side - som nævnt i det foregående blogindlæg - benytter TailwindCSS.
TailwindCss udmærker sig generelt ved relativt store CSS-filer, hvis man ikke sanerer i dets standard konfigurationsfil.

En anden væsentlig pointe i forhold til ovenstående, er, at efterhånden som de fleste sender alt indhold over HTTP2, bliver det mindre relevant at reducere filstørrelser alene i forhold til »render blocking«, hvorimod HTTP2 selvfølgelig ikke gør det mindre relevant fortsat at sørge for hurtig request-tid (og mindre dataforbrug) på mobilenheder.
Selvom HTTP2 i nogle tilfælde gør filstørrelser mindre relevante, er der dog - i mine øjne - ingen grund til ikke at inkludere Purgecss som et værktøj i sin buildpipe: Værktøjet er nemt at integrere, hurtigt i brug og hvis man er "perfektionist" bør unødvendigt store filstørrelser være irriterende nok i sig selv til, at de ikke tolereres om muligt!

Hvis du ikke allerede benytter Purgecss i din build-pipeline, vil jeg på det kraftigste opfordre til det. Purgecss integrerer nemt med Webpack såvel som Rollup, Gulp og Grunt. Læs mere om Purgecss her.