Hier is een waarheid waar ik jaren over deed om volledig te waarderen: hoe je code eruitziet is bijna net zo belangrijk als wat het doet. Goed opgemaakte code wordt sneller gereviewd, bevat minder bugs en is dramatisch makkelijker te onderhouden. En aan de andere kant laadt correct geminificeerde code sneller en bespaart je gebruikers bandbreedte.
Laten we het over beide kanten van deze medaille hebben.
Waarom Opmaak Belangrijker is dan Je Denkt
Ik heb teams uren zien verspillen in code reviews met discussies over tabs vs spaties, puntkomma's wel of niet, of waar de accolades moeten staan. Dat is tijd die niet besteed wordt aan het opleveren van features. Consistente opmaak elimineert deze debatten volledig.
Maar het gaat niet alleen om teamharmonie. Uniform opgemaakte code maakt bugs makkelijker te herkennen. Kijk hier eens naar:
Die sendNotification()-aanroep draait elke keer, niet alleen voor admins — de inspringing is misleidend. Met verplichte accolades (die de meeste formatters afdwingen) is deze bug overduidelijk:
Best Practices voor Opmaak
Kies een stijl en automatiseer het. Vertrouw niet op mensen om consistent te formatteren. Gebruik Prettier — het heeft sterke meningen, en dat is precies het punt. Stel het in om bij opslaan te draaien, en denk nooit meer na over opmaak.
Inspringing: 2 spaties is de JavaScript/TypeScript-conventie. De Google style guide, de Airbnb style guide en Standard style zijn het hier allemaal over eens.
Puntkomma's: Gebruik ze. Ja, JavaScript heeft ASI (Automatic Semicolon Insertion), maar het heeft goed gedocumenteerde valkuilen. Zet er gewoon puntkomma's neer.
Regellengte: Houd regels onder 80-100 tekens. Lange regels veroorzaken horizontaal scrollen en maken diffs moeilijker te lezen.
Hoe Minificatie Echt Werkt
Minificatie is het tegenovergestelde van opmaak — het maakt code zo klein mogelijk voor productie. Dit is wat een minifier zoals Terser doet:
- Verwijdert witruimte en commentaar — Al die spaties, tabs, regelovergangen en
// TODO: fix later-commentaren? Weg. - Verkort variabelenamen —
userAccountBalancewordta.calculateMonthlyPaymentwordtb. Alleen lokale variabelen — het hernoemt geen dingen die externe code mogelijk referenceert. - Elimineert dode code — Als een functie nooit wordt aangeroepen, wordt deze verwijderd.
- Berekent constanten vooraf —
const TAX_RATE = 0.2; total * (1 + TAX_RATE)wordttotal*1.2.
Het resultaat? Typisch 50-70% bestandsgrootte-reductie. Hier is een voor/na:
Voor (leesbaar, 147 bytes):
Na (geminificeerd, 62 bytes):
Zelfde functionaliteit, 58% kleiner.
Vergeet de Source Maps Niet
Geminificeerde code is onleesbaar, wat het debuggen van productiefouten pijnlijk maakt. Source maps lossen dit op door geminificeerde code terug te koppelen aan je originele broncode. Elk modern build-tool genereert ze — zorg ervoor dat je ze uploadt naar je error tracking service (Sentry, Bugsnag, etc.).
De Praktische Workflow
De Praktische Workflow
Bij ontwikkeling: schrijf opgemaakte, leesbare code. Gebruik Prettier + ESLint voor automatische opmaak en linting. In productie: minificeer alles via je build-tool (webpack, Vite, esbuild).
Prettier + ESLint Instellen in 60 Seconden
Als je opmaak nog niet hebt geautomatiseerd, hier is de snelste setup:
Voeg dan een format-script toe aan je package.json: "format": "prettier --write src/**/*.{js,ts,jsx,tsx}". Draai het een keer om je hele codebase te formatteren, en stel je editor in om bij opslaan te formatteren. De eerste diff kan enorm zijn, maar daarna zijn opmaakdebatten voor altijd voorbij.
Tree Shaking vs Minificatie
Mensen verwarren deze twee vaak, maar het zijn verschillende optimalisatietechnieken die samenwerken:
- Minificatie maakt individuele bestanden kleiner door witruimte te verwijderen, namen te verkorten en expressies vooraf te berekenen. Het verwijdert geen ongebruikte exports.
- Tree shaking elimineert ongebruikte code over modules heen. Als je alleen
{ debounce }importeert uit lodash-es, verwijdert tree shaking al het andere uit de bundle.
Beide zijn essentieel voor productie-builds. Moderne bundlers zoals Vite en esbuild doen beide automatisch — zorg er alleen voor dat je ES module imports (import) gebruikt in plaats van CommonJS (require), zodat tree shaking je dependency graph kan analyseren.
Veelvoorkomende Minificatie-valkuilen
1. Vertrouwen op function.name in productie. Minifiers hernoemen functies, dus myFunction.name zal "a" of iets even nutteloos teruggeven in productie. Als je stabiele functienamen nodig hebt (voor logging, error tracking of reflectie), gebruik dan expliciete string-identifiers.
2. Code minificeren die eval() gebruikt. eval() kan elke variabele bij naam refereren, dus de minifier kan niets veilig hernoemen in die scope. De meeste minifiers slaan hernoemen over in functies die eval() bevatten, maar dit beperkt de optimalisatie aanzienlijk. Vermijd eval() helemaal als het kan.
3. Geminificeerde builds niet testen. Sommige bugs verschijnen pas na minificatie — vooral rond property name mangling. Draai je test suite altijd tegen de productie-build, niet alleen de development-build.
Je Bundlegrootte Meten
Minificatie doet er alleen toe als je weet waarmee je begint. Hier zijn snelle manieren om je bundlegrootte te controleren:
Deze tools genereren visuele treemaps die precies laten zien welke dependencies je bundle opeten. Je zou verrast kunnen zijn — ik vond ooit een project waar moment.js locales 500KB van de uiteindelijke bundle uitmaken. Overstappen naar dayjs bespaarde direct 490KB.
Prettier vs ESLint: Het is Niet Hetzelfde
Oké, ik moet dit even kwijt omdat ik deze verwarring *overal* zie: Prettier en ESLint zijn niet dezelfde tool. Ze doen niet eens hetzelfde werk. En toch zie ik constant ontwikkelaars ze als uitwisselbaar behandelen. Laat me het uitleggen.
Prettier is een code formatter. Het geeft om hoe je code *eruitziet* — witruimte, regelovergangen, puntkomma's, trailing comma's, quote-stijl, inspringing. Dat is alles. Het weet niet en het kan niet schelen of je code daadwerkelijk werkt. Je zou een functie kunnen hebben die je hele database verwijdert en Prettier zou er alleen voor zorgen dat het netjes is ingesprongen.
ESLint daarentegen is een linter. Het geeft om code-*kwaliteit* — ongebruikte variabelen, onbereikbare code, potentiële bugs, ontbrekende foutafhandeling, toegankelijkheidsproblemen. Het vangt de dingen die je om 2 uur 's nachts op een zaterdag bijten als je opgeroepen wordt.
Maar hier wordt het lastig — ESLint heeft *ook* enkele ingebouwde opmaakregels, en dat is waar het rommelig wordt. Als je beide tools draait zonder ze goed te configureren, gaan ze met elkaar vechten. Prettier maakt je code op de ene manier op, ESLint klaagt dat het anders moet, je fixt het voor ESLint, Prettier maakt het opnieuw op... het is een eindeloze lus van frustratie.
De oplossing is doodeenvoudig: gebruik eslint-config-prettier. Het schakelt alle ESLint-regels uit die botsen met Prettier, zodat ESLint zich richt op codekwaliteit en Prettier de opmaak afhandelt. Geen gevechten meer.
Merk op dat "prettier" het laatste item in de extends-array is? Dat is cruciaal — het moet alle opmaakregels van plugins die erboven staan overschrijven. Ik heb teams uren zien besteden aan het debuggen van ESLint/Prettier-conflicten, alleen om te ontdekken dat ze de volgorde verkeerd hadden. Vertrouw me hierin.
Mijn aanbevolen setup: laat Prettier alles cosmetisch afhandelen, en configureer ESLint-regels die daadwerkelijk bugs vangen. Verspil ESLint niet aan klagen over puntkomma's als Prettier dat al afhandelt.
Het Grote Tabs vs Spaties Debat (Opgelost)
Oké, laten we het hebben over de heilige oorlog van programmeren. Tabs of spaties? Ik heb vriendschappen zien eindigen over dit debat. Ik heb Slack-threads zien doorgaan voor *dagen*. Ik heb persoonlijk een senior ontwikkelaar een 2.000-woorden Confluence-pagina zien schrijven ter verdediging van tabs. Het was prachtig en compleet overbodig.
Laten we naar de werkelijke data kijken. De Stack Overflow Developer Survey heeft consistent laten zien dat spaties populairder zijn — ongeveer 60-65% van de ontwikkelaars geeft de voorkeur aan spaties. GitHub's eigen analyse van publieke repos vertelt een vergelijkbaar verhaal.
Maar hier wordt het interessant: het varieert enorm per taal. Go gebruikt tabs — dat is niet eens een debat, gofmt dwingt tabs af en niemand discussieert met gofmt. Python gebruikt 4 spaties — PEP 8 zegt het, en je discussieert ook niet met PEP 8. JavaScript en TypeScript? De community heeft zich grotendeels geschikt naar 2 spaties, en vrijwel elke grote style guide is het ermee eens.
Het toegankelijkheidsargument voor tabs is echter echt overtuigend — tabs laten elke ontwikkelaar hun gewenste visuele breedte instellen, wat belangrijk is voor ontwikkelaars met visuele beperkingen. Dat is een echte, legitieme reden om tabs te verkiezen.
Maar weet je wat? Hier is het *echte* juiste antwoord, en ik meen het oprecht: gebruik wat je formatter afdwingt en stop met discussiëren. Als je project Prettier gebruikt met tabWidth: 2 en useTabs: false, dan gebruik je 2 spaties. Punt. De formatter neemt de beslissing, jij accepteert het, en je besteedt je energie aan dingen die er echt toe doen — zoals of je app crasht als iemand een emoji in het zoekveld typt.
Het leven is te kort voor opmaakdiscussies. Laat de robots beslissen.
Moderne Minificatie: esbuild, SWC en de Snelheidsrevolutie
Jarenlang was Terser de koning van JavaScript-minificatie. Het verving UglifyJS, het was beproefd in de strijd, het werkte geweldig. Het enige probleem? Het is traag. Echt *heel* traag op grote codebases. En ik bedoel niet "pak een koffie" traag — ik bedoel "heroverweeg je carrièrekeuzes terwijl je naar de CI-pipeline staart" traag.
Toen kwam esbuild en veranderde alles. Geschreven in Go, is esbuild 10-100x sneller dan Terser. Ik overdrijf niet — de benchmarks zijn bijna komisch. Een project dat Terser 30 seconden kost om te minificeren? esbuild doet het in 300 milliseconden. De eerste keer dat ik het zag, dacht ik oprecht dat er iets kapot was omdat het zo snel klaar was.
SWC is nog een concurrent, geschreven in Rust. Het is niet helemaal zo snel als esbuild voor pure minificatie, maar het is een completere toolchain — het doet transpilatie, bundling en minificatie allemaal in één. Als je Next.js gebruikt, gebruik je SWC al onder de motorkap.
Hier is een ruwe vergelijking op een middelgroot project (~500 JS-bestanden):
| 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 |
Doet het snelheidsverschil er echt toe? Eerlijk gezegd, voor een klein project met een 5-seconden build, waarschijnlijk niet. Maar als je CI/CD draait op een grote monorepo en je build-pipeline 50 keer per dag draait? Die minuten tellen snel op. Ik heb teams 10+ minuten van hun CI-tijden zien afschaven alleen door over te stappen van Terser naar esbuild.
Het goede nieuws is dat als je Vite gebruikt, je al esbuild krijgt voor development builds en Rollup (met Terser of esbuild) voor productie. Next.js gebruikt SWC. Angular heeft ook met esbuild geëxperimenteerd. Het ecosysteem beweegt hier snel.
Een waarschuwing: esbuild en SWC produceren niet altijd byte-voor-byte identieke output als Terser. In zeldzame gevallen produceren Terser's agressievere optimalisaties iets kleinere bundles. Maar we hebben het over misschien 1-2% verschil — absoluut de 100x snelheidsverbetering waard in de meeste gevallen.
CSS- en HTML-minificatie Ook
We hebben het over JavaScript gehad, maar vergeet CSS- en HTML-minificatie niet. Serieus, ik heb projecten gezien waar de CSS-bundle *groter* was dan het JavaScript. Vooral als je een utility-first framework zoals Tailwind gebruikt (voordat PurgeCSS zijn werk doet).
Voor CSS is cssnano de standaardtool. Het doet meer dan alleen witruimte verwijderen — het merget ook dubbele regels, converteert kleuren naar kortere formaten (#ff0000 wordt #f00 of zelfs red), verwijdert overtollige properties en optimaliseert calc()-expressies. Op een typische stylesheet kun je 30-50% besparing verwachten.
Voor HTML verwijdert html-minifier-terser witruimte tussen tags, verwijdert optionele sluit-tags, minificeert inline CSS en JS, verwijdert HTML-commentaar en klapt boolean-attributen samen. Het is verrassend effectief — ik heb 20-30% reductie gezien op HTML-zware pagina's.
En nu het goede deel: als je Angular, React, Vue of vrijwel elk modern framework met een build-stap gebruikt, gebeurt dit al voor je. Je build-tool handelt CSS- en HTML-minificatie af als onderdeel van de productie-build. Maar weten wat er onder de motorkap gebeurt is echt nuttig — vooral als je moet debuggen waarom je productie-HTML niet overeenkomt met je broncode, of als je dat laatste kritische render-pad probeert te optimaliseren.
Code-opmaak in CI/CD-Pipelines
Kijk, hier is het ding met "format on save" — het werkt alleen als *iedereen in het team* het correct geconfigureerd heeft. En ik ben hier eerder door gebeten. Je kent het scenario: iemand komt bij het team, kloont de repo, begint wijzigingen te maken, en dient een PR in met 400 opmaakwijzigingen vermengd met hun 5 regels daadwerkelijke code. Die PR reviewen is een nachtmerrie.
De oplossing? Dwing opmaak af in CI. Maak het onmogelijk om ongeformatteerde code te mergen. Zo doe je het:
Stap 1: Voeg een CI-check toe. Voeg prettier --check . toe aan je CI-pipeline. Het eindigt met code 1 als een bestand niet overeenkomt met Prettier's opmaak. Geen argumenten, geen debatten — de CI is de wet.
Stap 2: Voeg pre-commit hooks toe. Opmaakproblemen opvangen in CI is geweldig, maar het is nog beter om ze *voor* het committen op te vangen. Daar komen Husky en lint-staged om de hoek kijken.
Het mooie van lint-staged is dat het alleen draait op de bestanden die je daadwerkelijk hebt gewijzigd, niet de hele codebase. Dus de pre-commit hook duurt 1-2 seconden in plaats van 30. Niemand gaat een hook uitschakelen die 1 seconde duurt.
Ik heb teams zien gaan van "opmaak is een constante bron van PR-frictie" naar "we denken letterlijk nooit meer aan opmaak" binnen een week na het instellen. Het is een van die dingen waar de 15-minuten setup zichzelf duizend keer terugbetaalt.
Bundlegrootte Case Studies uit de Praktijk
Laten we het over echte cijfers hebben, want abstract advies over "bundles klein houden" is niet erg nuttig zonder context. Ik heb deze exacte scenario's zien gebeuren in productieprojecten, en de verschillen zijn echt schokkend.
Case 1: lodash vs lodash-es. Dit is de klassieker. Als je import _ from 'lodash' doet en alleen _.debounce gebruikt, importeer je de hele library — 71.5 KB geminificeerd + gzipped. Schakel over naar import { debounce } from 'lodash-es' en met tree shaking kijk je naar ongeveer 1.5 KB voor alleen die functie. Dat is een reductie van 98%. Check het zelf op Bundlephobia.
Case 2: moment.js vs dayjs. Moment.js was jarenlang de gouden standaard voor datumverwerking, maar het komt op 72.1 KB geminificeerd + gzipped — en dat is inclusief alle locale-data standaard. Day.js heeft een bijna identieke API maar komt op 2.9 KB. Dat is geen typfout. 72 KB vs 3 KB voor in principe dezelfde functionaliteit. Het Moment.js-team zelf beveelt nu alternatieven aan.
Case 3: Iconenbibliotheken. Dit pakt mensen keer op keer. Als je import { FaHome } from 'react-icons/fa' doet, is het prima — dat is tree-shakeable. Maar sommige iconenbibliotheken zijn niet ingericht voor tree shaking, en je importeert uiteindelijk honderden SVG-iconen terwijl je er maar 5 nodig hebt. Ik heb iconen-imports 200+ KB aan bundles zien toevoegen. Controleer altijd of je iconenbibliotheek tree shaking ondersteunt, of importeer iconen individueel.
Case 4: Datumformatteringsbibliotheken. Moest je een datum formatteren in een specifieke tijdzone? Ik zag ooit een project dat moment-timezone importeerde (de volledige versie met alle tijdzonedata) — dat is 97 KB geminificeerd + gzipped — alleen om een enkele datum te formatteren. De native Intl.DateTimeFormat API handelt de meeste tijdzoneformattering native af zonder bundlekosten.
De les hier is niet "gebruik nooit dependencies" — dat zou dom zijn. De les is: weet wat je importeert en hoeveel het kost. Draai npx source-map-explorer build/static/js/*.js of check Bundlephobia voordat je die glimmende nieuwe library toevoegt. Je gebruikers op trage mobiele verbindingen zullen je dankbaar zijn.
Probeer het Zelf
Moet je snel wat rommelige code opschonen? Plak het in onze JavaScript Formatter voor directe, leesbare output. Klaar om het te verkleinen voor productie? De JavaScript Minifier stript het tot het absolute minimum. En als je niet zeker weet of je code geldig is, haal het eerst door de JavaScript Validator.