Her er en sannhet det tok meg år å fullt ut verdsette: hvordan koden din ser ut betyr nesten like mye som hva den gjør. Godt formatert kode blir raskere gjennomgått, har færre feil og er dramatisk enklere å vedlikeholde. Og på den andre siden laster riktig minifisert kode raskere og sparer brukerne dine for båndbredde.
La oss snakke om begge sider av denne mynten.
Hvorfor formatering betyr mer enn du tror
Jeg har sett team kaste bort timer i kodegjennomganger med diskusjoner om tabs vs mellomrom, semikolon eller ikke, eller hvor krøllparentesene skal plasseres. Det er tid som ikke brukes på å levere funksjoner. Konsekvent formatering eliminerer disse debattene fullstendig.
Men det handler ikke bare om teamharmoni. Ensartet formatert kode gjør feil lettere å oppdage. Tenk på dette:
Det sendNotification()-kallet kjøres hver gang, ikke bare for admins — innrykket er villedende. Med obligatoriske krøllparenteser (som de fleste formaterere håndhever) er denne feilen åpenbar:
Beste praksis for formatering
Velg en stil og automatiser den. Ikke stol på mennesker for konsekvent formatering. Bruk Prettier — det har sterke meninger, og det er nettopp poenget. Sett det opp til å kjøre ved lagring, og tenk aldri på formatering igjen.
Innrykk: 2 mellomrom er JavaScript/TypeScript-konvensjonen. Googles stilguide, Airbnbs stilguide og Standard er alle enige om dette.
Semikolon: Bruk dem. Ja, JavaScript har ASI (Automatic Semicolon Insertion), men det har veldokumenterte fallgruver. Bare legg til semikolonene.
Linjelengde: Hold linjer under 80-100 tegn. Lange linjer forårsaker horisontal rulling og gjør differ vanskeligere å lese.
Hvordan minifisering faktisk fungerer
Minifisering er det motsatte av formatering — det gjør kode så liten som mulig for produksjon. Her er hva en minifiserer som Terser gjør:
- Fjerner mellomrom og kommentarer — Alle de mellomrommene, tabsene, linjeskiftene og
// TODO: fix later-kommentarene? Borte. - Forkorter variabelnavn —
userAccountBalanceblir tila.calculateMonthlyPaymentblir tilb. Bare lokale variabler — den vil ikke gi nytt navn til ting som ekstern kode kan referere til. - Eliminerer død kode — Hvis en funksjon aldri kalles, fjernes den.
- Forhåndsberegner konstanter —
const TAX_RATE = 0.2; total * (1 + TAX_RATE)blir tiltotal*1.2.
Resultatet? Typisk 50-70% filstørrelsesreduksjon. Her er et før/etter:
Før (lesbart, 147 bytes):
Etter (minifisert, 62 bytes):
Samme funksjonalitet, 58% mindre.
Ikke glem Source Maps
Minifisert kode er uleselig, noe som gjør feilsøking av produksjonsfeil smertefullt. Source maps løser dette ved å koble minifisert kode tilbake til den opprinnelige kilden. Alle moderne byggeverktøy genererer dem — sørg for at du laster dem opp til feilsporingstjenesten din (Sentry, Bugsnag, osv.).
Den praktiske arbeidsflyten
Den praktiske arbeidsflyten
I utvikling: skriv formatert, lesbar kode. Bruk Prettier + ESLint for automatisk formatering og linting. I produksjon: minifiser alt gjennom byggeverktøyet ditt (webpack, Vite, esbuild).
Sette opp Prettier + ESLint på 60 sekunder
Hvis du ikke har automatisert formatering ennå, her er det raskeste oppsettet:
Legg deretter til et formateringsskript i package.json: "format": "prettier --write src/**/*.{js,ts,jsx,tsx}". Kjør det én gang for å formatere hele kodebasen, og sett editoren din til å formatere ved lagring fremover. Den første diffen kan være enorm, men etter det er formateringsdebatter over for alltid.
Tree Shaking vs minifisering
Folk forveksler disse to ofte, men de er forskjellige optimaliseringsteknikker som fungerer sammen:
- Minifisering gjør individuelle filer mindre ved å fjerne mellomrom, forkorte navn og forhåndsberegne uttrykk. Den fjerner ikke ubrukte eksporter.
- Tree shaking eliminerer ubrukt kode på tvers av moduler. Hvis du bare importerer
{ debounce }fra lodash-es, fjerner tree shaking alt annet fra bundlen.
Begge er essensielle for produksjonsbygg. Moderne bundlere som Vite og esbuild gjør begge automatisk — bare sørg for at du bruker ES-modulimporter (import) i stedet for CommonJS (require) slik at tree shaking kan analysere avhengighetsgrafen din.
Vanlige minifiseringsfallgruver
1. Stole på function.name i produksjon. Minifiserere gir funksjoner nytt navn, så myFunction.name vil returnere "a" eller noe like ubrukelig i produksjon. Hvis du trenger stabile funksjonsnavn (for logging, feilsporing eller refleksjon), bruk eksplisitte strengidentifikatorer i stedet.
2. Minifisere kode som bruker eval(). eval() kan referere til enhver variabel ved navn, så minifisereren kan ikke trygt gi nytt navn til noe i det scopet. De fleste minifiserere vil hoppe over navngivning i funksjoner som inneholder eval(), men dette begrenser optimaliseringen betydelig. Unngå eval() helt om mulig.
3. Ikke teste minifiserte bygg. Noen feil dukker bare opp etter minifisering — spesielt rundt property name mangling. Kjør alltid testsuiten din mot produksjonsbygget, ikke bare utviklingsbygget.
Måle bundlestørrelsen din
Minifisering betyr bare noe hvis du vet hva du starter med. Her er raske måter å sjekke bundlestørrelsen din:
Disse verktøyene genererer visuelle trekart som viser nøyaktig hvilke avhengigheter som spiser opp bundlen din. Du kan bli overrasket — jeg fant en gang et prosjekt der moment.js-lokaler utgjorde 500KB av den endelige bundlen. Å bytte til dayjs sparte 490KB umiddelbart.
Prettier vs ESLint: De er ikke det samme
Okay, jeg må få dette av brystet fordi jeg ser denne forvirringen *overalt*: Prettier og ESLint er ikke det samme verktøyet. De gjør ikke engang den samme jobben. Og likevel ser jeg stadig utviklere som behandler dem som utskiftbare. La meg forklare.
Prettier er en kodeformaterer. Den bryr seg om hvordan koden din *ser ut* — mellomrom, linjeskift, semikolon, avsluttende kommaer, anførselstegnstil, innrykk. Det er alt. Den vet ikke og bryr seg ikke om koden din faktisk fungerer. Du kan ha en funksjon som sletter hele databasen, og Prettier ville bare sørge for at den er pent innrykket.
ESLint, på den annen side, er en linter. Den bryr seg om kode*kvalitet* — ubrukte variabler, utilgjengelig kode, potensielle feil, manglende feilhåndtering, tilgjengelighetsproblemer. Den fanger de tingene som biter deg kl. 2 på natten en lørdag når du blir vekket av en alarm.
Men her er greia — ESLint har *også* noen innebygde formateringsregler, og det er der ting blir rotete. Hvis du kjører begge verktøyene uten å konfigurere dem riktig, vil de slåss med hverandre. Prettier formaterer koden din på én måte, ESLint klager på at den burde være en annen, du fikser det for ESLint, Prettier reformaterer det... det er en evig loop av frustrasjon.
Løsningen er dødenkel: bruk eslint-config-prettier. Den slår av alle ESLint-reglene som konflikter med Prettier, slik at ESLint fokuserer på kodekvalitet og Prettier håndterer formatering. Ikke mer krangel.
Legg merke til at "prettier" er det siste elementet i extends-arrayen? Det er avgjørende — den må overstyre formateringsregler fra plugins listet over den. Jeg har sett team bruke timer på å feilsøke ESLint/Prettier-konflikter bare for å oppdage at de hadde rekkefølgen feil. Stol på meg her.
Mitt anbefalte oppsett: la Prettier håndtere alt kosmetisk, og konfigurer ESLint-regler som faktisk fanger feil. Ikke kast bort ESLint på å klage over semikolon når Prettier allerede håndterer det.
Den store tabs vs mellomrom-debatten (avgjort)
Greit, la oss snakke om programmeringens hellige krig. Tabs eller mellomrom? Jeg har sett vennskap ta slutt over denne debatten. Jeg har sett Slack-tråder vare i *dagevis*. Jeg har personlig vært vitne til at en seniorutvikler skrev en 2000-ords Confluence-side som forsvarte tabs. Det var praktfullt og fullstendig unødvendig.
La oss se på de faktiske dataene. Stack Overflow Developer Survey har konsekvent vist at mellomrom er mer populært — omtrent 60-65% av utviklere foretrekker mellomrom. GitHubs egen analyse av offentlige repoer forteller en lignende historie.
Men her er det interessante: det varierer voldsomt etter språk. Go bruker tabs — det er ikke engang en debatt, gofmt håndhever tabs og ingen krangler med gofmt. Python bruker 4 mellomrom — PEP 8 sier det, og du krangler ikke med PEP 8 heller. JavaScript og TypeScript? Fellesskapet har i stor grad landet på 2 mellomrom, og praktisk talt alle store stilguider er enige.
Tilgjengelighetsargumentet for tabs er faktisk overbevisende — tabs lar hver utvikler sette sin foretrukne visuelle bredde, noe som betyr noe for utviklere med synshemninger. Det er en reell, legitim grunn til å foretrekke tabs.
Men vet du hva? Her er det *faktisk* riktige svaret, og jeg mener dette oppriktig: bruk det formateren din håndhever og slutt å krangle. Hvis prosjektet ditt bruker Prettier med tabWidth: 2 og useTabs: false, da bruker du 2 mellomrom. Punktum. Formateren tar avgjørelsen, du aksepterer den, og du bruker energien din på ting som faktisk betyr noe — som om appen din krasjer når noen skriver en emoji i søkeboksen.
Livet er for kort for formateringskrangler. La robotene bestemme.
Moderne minifisering: esbuild, SWC og hastighetsrevolusjonen
I årevis var Terser kongen av JavaScript-minifisering. Den erstattet UglifyJS, var kamptestet og fungerte utmerket. Det eneste problemet? Den er treg. Virkelig *veldig* treg på store kodebaser. Og jeg mener ikke "hent en kaffe" treg — jeg mener "revurder karrierevalgene dine mens du stirrer på CI-pipelinen" treg.
Så dukket esbuild opp og forandret alt. Skrevet i Go, er esbuild 10-100x raskere enn Terser. Jeg overdriver ikke — benchmarkene er nesten komiske. Et prosjekt som tar Terser 30 sekunder å minifisere? esbuild gjør det på 300 millisekunder. Første gang jeg så det, trodde jeg oppriktig at noe var ødelagt fordi det ble ferdig så fort.
SWC er en annen utfordrer, skrevet i Rust. Den er ikke helt like rask som esbuild for ren minifisering, men den er en mer komplett verktøykjede — den håndterer transpilering, bundling og minifisering alt i ett. Hvis du bruker Next.js, bruker du allerede SWC under panseret.
Her er en grov sammenligning på et mellomstort prosjekt (~500 JS-filer):
| Tool | Language | Minification Time | Notes |
| Terser | JavaScript | ~25s | Battle-tested, most compatible |
| esbuild | Go | ~0.3s | Blazing fast, some edge cases |
| SWC | Rust | ~0.8s | Full toolchain, great ecosystem |
Betyr hastighetsforskjellen faktisk noe? Ærlig talt, for et lite prosjekt med et 5-sekunders bygg, sannsynligvis ikke. Men når du kjører CI/CD på et stort monorepo og byggepipelinen kjører 50 ganger om dagen? De minuttene legger seg opp fort. Jeg har sett team barbere 10+ minutter av CI-tidene sine bare ved å bytte fra Terser til esbuild.
Den gode nyheten er at hvis du bruker Vite, får du allerede esbuild for utviklingsbygg og Rollup (med Terser eller esbuild) for produksjon. Next.js bruker SWC. Angular har også eksperimentert med esbuild. Økosystemet beveger seg raskt her.
Et ord til forsiktighet: esbuild og SWC produserer ikke alltid byte-for-byte identisk output som Terser. I sjeldne tilfeller produserer Tersers mer aggressive optimaliseringer litt mindre bundler. Men vi snakker om kanskje 1-2% forskjell — absolutt verdt 100x hastighetsforbedringen i de fleste tilfeller.
CSS- og HTML-minifisering også
Vi har snakket om JavaScript, men ikke overse CSS- og HTML-minifisering. Seriøst, jeg har sett prosjekter der CSS-bundlen var *større* enn JavaScript. Spesielt hvis du bruker et utility-first rammeverk som Tailwind (før PurgeCSS gjør sitt).
For CSS er cssnano standardverktøyet. Det gjør mer enn bare å fjerne mellomrom — det slår også sammen dupliserte regler, konverterer farger til kortere formater (#ff0000 blir #f00 eller til og med red), fjerner overflødige egenskaper og optimaliserer calc()-uttrykk. På et typisk stilark kan du forvente 30-50% besparelse.
For HTML fjerner html-minifier-terser mellomrom mellom tagger, fjerner valgfrie avslutningstagger, minifiserer inline CSS og JS, fjerner HTML-kommentarer og kollapser boolske attributter. Det er overraskende effektivt — jeg har sett 20-30% reduksjon på HTML-tunge sider.
Og her kommer det gode: hvis du bruker Angular, React, Vue eller praktisk talt ethvert moderne rammeverk med et byggesteg, skjer dette allerede for deg. Byggeverktøyet ditt håndterer CSS- og HTML-minifisering som en del av produksjonsbygget. Men å vite hva som skjer under panseret er genuint nyttig — spesielt når du trenger å feilsøke hvorfor produksjons-HTMLen din ikke matcher kilden, eller når du prøver å optimalisere den siste kritiske renderingsstien.
Kodeformatering i CI/CD-pipelines
Hør her, her er greia med "formater ved lagring" — det fungerer bare hvis *hver eneste person i teamet* har det konfigurert riktig. Og jeg har blitt brent av dette før. Du kjenner scenariet: noen blir med i teamet, kloner repoet, begynner å gjøre endringer, og sender inn en PR med 400 formateringsendringer blandet inn med de 5 linjene med faktisk kode. Å gjennomgå den PRen er et mareritt.
Løsningen? Håndhev formatering i CI. Gjør det umulig å merge uformatert kode. Slik gjør du det:
Steg 1: Legg til en CI-sjekk. Legg til prettier --check . i CI-pipelinen din. Den avslutter med kode 1 hvis noen fil ikke matcher Prettiers formatering. Ingen argumenter, ingen debatter — CI er loven.
Steg 2: Legg til pre-commit hooks. Å fange formateringsproblemer i CI er bra, men det er enda bedre å fange dem *før* koden i det hele tatt er committet. Det er her Husky og lint-staged kommer inn.
Det fine med lint-staged er at den bare kjører på filene du faktisk har endret, ikke hele kodebasen. Så pre-commit hooken tar 1-2 sekunder i stedet for 30. Ingen kommer til å deaktivere en hook som tar 1 sekund.
Jeg har sett team gå fra "formatering er en konstant kilde til PR-friksjon" til "vi tenker bokstavelig talt aldri på formatering lenger" i løpet av en uke etter å ha satt dette opp. Det er en av de tingene der 15-minutters oppsettet betaler seg tilbake tusen ganger.
Bundlestørrelse-casestudier fra virkeligheten
La oss snakke om virkelige tall, fordi abstrakte råd om å "holde bundler små" ikke er veldig nyttige uten kontekst. Jeg har sett nøyaktig disse scenariene utspille seg i produksjonsprosjekter, og forskjellene er genuint sjokkerende.
Case 1: lodash vs lodash-es. Dette er klassikeren. Hvis du gjør import _ from 'lodash' og bare bruker _.debounce, importerer du hele biblioteket — 71,5 KB minifisert + gzippet. Bytt til import { debounce } from 'lodash-es' og med tree shaking ser du på omtrent 1,5 KB bare for den funksjonen. Det er 98% reduksjon. Sjekk det selv på Bundlephobia.
Case 2: moment.js vs dayjs. Moment.js var gullstandarden for datohåndtering i årevis, men den veier 72,1 KB minifisert + gzippet — og det inkluderer alle lokaldataene som standard. Day.js har et nesten identisk API men kommer inn på 2,9 KB. Det er ikke en skrivefeil. 72 KB vs 3 KB for i bunn og grunn samme funksjonalitet. Moment.js-teamet selv anbefaler nå alternativer.
Case 3: Ikonbiblioteker. Denne fanger folk hele tiden. Hvis du gjør import { FaHome } from 'react-icons/fa', er du fin — det er tree-shakeable. Men noen ikonbiblioteker er ikke satt opp for tree shaking, og du ender opp med å importere hundrevis av SVG-ikoner når du bare trenger 5. Jeg har sett ikonimporter legge til 200+ KB til bundler. Sjekk alltid at ikonbiblioteket ditt støtter tree shaking, eller importer ikoner individuelt.
Case 4: Datoformateringsbiblioteker. Trengte å formatere én dato i en spesifikk tidssone? Jeg så en gang et prosjekt som hentet inn moment-timezone (fullversjonen med alle tidssonedataene) — det er 97 KB minifisert + gzippet — bare for å formatere en eneste dato. Det native Intl.DateTimeFormat-APIet håndterer det meste av tidssoneformatering nativt uten noen bundlekostnad.
Lærdommen her er ikke "aldri bruk avhengigheter" — det ville vært dumt. Lærdommen er: vit hva du importerer og hva det koster. Kjør npx source-map-explorer build/static/js/*.js eller sjekk Bundlephobia før du legger til det skinnende nye biblioteket. Brukerne dine på trege mobilforbindelser vil takke deg.
Prøv det selv
Trenger du å rydde opp i noe rotete kode raskt? Lim det inn i JavaScript Formatter for øyeblikkelig, lesbar output. Klar til å krympe det for produksjon? JavaScript Minifier stripper det ned til det absolutte minimum. Og hvis du ikke er sikker på om koden din i det hele tatt er gyldig, kjør den gjennom JavaScript Validator først.