Forkert konfigureret HTTP-komprimering sparer sjældent tid og skaber ofte nye problemer. Jeg viser konkret, hvordan forkerte niveauer, manglende overskrifter og en uklar komprimeringsplacering øger TTFB, udløser overvågningsalarmer og i sidste ende bremser brugerne.
Centrale punkter
- Niveauer Skel mellem: moderat on-the-fly, høj ved forkomprimering
- typer Korrekt: Komprimér tekst, ikke billeder
- Adskillelse statisk vs. dynamisk, caching først
- Overskrift ren: Vary og Accept‑Encoding
- Overvågning med TTFB, CPU og vitale funktioner
Hvorfor forkerte indstillinger gør mere skade end gavn
Kompression virker som en simpel kontakt, men høj CPU-omkostninger kan ødelægge alle fordele. Hvis jeg indstiller Brotli til dynamiske svar på niveau 9-11, forlænger jeg servertiden og forringer TTFB betydeligt. Især ved HTML-visninger eller API-svar fører dette til langsom rendering og frustrerer brugerne. Overvågningen rapporterer derefter om formodede udfald, fordi slutpunkterne reagerer langsomt eller med forkerte kodninger. Derfor behandler jeg komprimering som en performance-funktion, som jeg skal kalibrere, i stedet for at aktivere den blindt.
Prioriter målene korrekt: Reducer nyttelasten uden TTFB-skader
Jeg reducerer først nyttelast renderingskritiske tekstressourcer og hold samtidig øje med latenstiden. Brotli giver ofte 15-21 % mindre payloads end Gzip for tekstfiler, men gevinsten er kun værd, hvis CPU-tiden holder sig inden for rimelige grænser. Ved dynamiske svar starter jeg konservativt, måler TTFB og justerer niveauerne i små trin. Rene tekstaktiver i cachen vinder konstant, mens for kraftige trin on-the-fly har den modsatte effekt. Målet er fortsat en hurtig levering af første byte og en hurtig First Contentful Paint på ægte enheder.
Hyppige fejlkonfigurationer og deres bivirkninger
For høj Niveauer Dynamisk indhold skaber CPU-spidsbelastninger, blokerer flush-punkter og forsinker rendering mærkbart. Forkert vedligeholdte indholdstypelister lader CSS, JS, JSON eller SVG ligge ukomprimeret, mens allerede komprimerede billeder spiser unødvendig regnetid. Mangler der adskillelse mellem statisk og dynamisk, komprimerer serveren assets hver gang på ny og spilder ressourcer. Uden Vary: Accept‑Encoding ender blandede varianter i cachen, hvilket fører til ulæselige svar for klienter uden den relevante kodning. I kæder med proxy eller CDN opstår der desuden dobbelt komprimering, dekomprimering på det forkerte hop og inkonsekvente headers, som er svære at gengive.
Gzip vs. Brotli: træf en praktisk beslutning
Jeg bruger Brødpind for statiske tekstaktiver med høj niveau og holder dynamiske svar på et moderat niveau. For HTML og JSON on-the-fly vælger jeg Brotli 3-4 eller Gzip 5-6, fordi forholdet mellem datastørrelse og CPU-tid for det meste er passende. Forudkomprimerede CSS/JS/skrifttyper pakker jeg med Brotli 9–11 og leverer dem fra cache eller CDN. Mangler klientunderstøttelse, falder serveren pænt tilbage på Gzip eller ukomprimeret. Hvis du vil sammenligne mere indgående, finder du en kompakt oversigt under Brotli vs. Gzip, inklusive effekter på tekstressourcer.
| Indholdstype | Procedure | Niveau på farten | Niveau før komprimering | Hint |
|---|---|---|---|---|
| HTML (dynamisk) | Brotli eller Gzip | Br 3–4 / Gz 5–6 | ikke almindeligt | Indstil flush-punkter, mål TTFB |
| JSON-API'er | Brotli eller Gzip | Br 3–4 / Gz 5–6 | ikke almindeligt | Hold overskriften konsistent |
| CSS/JS (statisk) | Brotli foretrækkes | ingen | Br 9–11 | forkomprimeret cache |
| SVG/skrifttyper | Brotli foretrækkes | ingen | Br 9–11 | Kontroller range-anmodninger |
Grænseværdier: minimumsstørrelser, små svar og tærskler
Kompression er først effektiv ved en vis Minimumstørrelse. Meget små HTML-snippets eller 1–2 kB JSON vokser endda let på grund af header-overhead eller initialisering af ordbog. Derfor sætter jeg en nedre grænse (f.eks. 512–1024 bytes), under hvilken serveren svarer ukomprimeret. Samtidig begrænser jeg for store objekter: Flere megabytes tekst med højt niveau blokerer arbejdere i lang tid. I praksis hjælper to justeringsskruer: gzip_min_length eller tilsvarende afbrydere samt grænser for buffere for at reducere risikoen for OOM.
MIME-typer og genkendelse: Korrekt vedligeholdelse af indholdstype
Det, der komprimeres, er det, der betragtes som Tekst gælder – styret via MIME-typer. Jeg holder listen eksplicit og undgår jokertegn. Typiske kandidater: text/html, tekst/css, application/javascript, application/json, image/svg+xml, application/xml, tekst/plain. Komprimér ikke: image/* (JPEG/PNG/WebP/AVIF), application/zip, application/pdf, font/woff2, application/wasm. Korrekt Indholdstype‑Headers er afgørende for, at motoren kan træffe pålidelige beslutninger og ikke behøver at sniffe.
Statisk vs. dynamisk: ren adskillelse og caching
Jeg skiller mig ud statisk og dynamisk klar, så CPU'en ikke konstant pakker de samme bytes om. Jeg komprimerer statiske aktiver i buildet eller på kanten og leverer dem fra en cache med lang levetid. Jeg komprimerer dynamiske svar moderat og sørger for, at kritiske dele sendes tidligt. På den måde drager brugeren direkte fordel af de første bytes, mens store tekstblokke fortsætter med at strømme bagved. Jo sjældnere jeg genererer nyt indhold, jo mere stabil forbliver belastningskurven.
HTTP/2 og HTTP/3: Komprimering uden blokeringer
Multiplexing ændrer Prioriteringer: Mange små, godt komprimerede tekstaktiver via en forbindelse giver tempo, men en langsom komprimering på farten kan bremse flere streams samtidigt. Jeg indstiller flush-punkter, så browseren begynder at rendere tidligt. Headers, kritisk CSS og de første HTML-bytes skal ud med det samme, derefter følger resten komprimeret. Hvis du vil se nærmere på samspillet, kan du finde baggrundsinformation under HTTP/2 multiplexing. Små justeringer af bufferstørrelser og kompressionsvinduer har ofte en mærkbar effekt.
Proxies, load balancers, CDN: det rigtige sted at komprimere
I kæder med Proxy og CDN bestemmer jeg, hvor der skal komprimeres, og holder mig strengt til det. Dobbelt komprimering eller dekomprimering på det forkerte hop ødelægger fordelene og forvirrer caches. Ideelt set komprimerer Edge for statiske tekstaktiver, mens backend leverer dynamiske svar moderat on-the-fly. Hvis en klient ikke accepterer Brotli, kommer Gzip eller Plain tilbage, tydeligt signaleret via Vary: Accept-Encoding. For en effektiv levering hjælper vejledningen til CDN-optimering med klare caching-regler og konsistente varianter.
Build-pipeline: Pålidelig styring af prækomprimering
Forudkomprimerede filer har brug for Disciplin i leveringen. Ud over .css/.js også .css.br og .css.gz (analogt for JS/SVG/TTF) i build. Serveren vælger på baggrund af Accept-Encoding den passende variant og sætter Indholdskodning, Indholdstype, Indholdslængde konsistent. Vigtigt: ingen dobbelt komprimering, ingen forkerte længder. ETags og checksummer er variantrelateret – Jeg accepterer forskellige ETags pr. kodning eller bruger svage ETags. Jeg tester Range-anmodninger separat, så byte-intervaller ved .br-aktiver betjenes korrekt.
Header-detaljer: Længde, caching, revalidering
Ved on-the-fly-komprimering sender jeg ofte Overførselskodning: chunked i stedet for en fast Indholdslængde. Klienten kan håndtere dette; det bliver først kritisk, hvis en efterfølgende instans fejlagtigt tilføjer en fast længde. I caching-lag sørger jeg for, at Varierer-header Kompressionsvarianter adskille og Cache-kontrol fornuftige TTL'er. For statiske aktiver er lange TTL'er med ren versionering (f.eks. hash i filnavnet) ideelle, dynamiske svar får korte TTL'er eller no‑store, afhængigt af følsomheden. Sidst ændret og If-None-Match hjælpe med at holde revalideringer effektive – pr. kodningsvariant.
Streaming, flush og serverbuffer
For hurtig Opfattet ydeevne Jeg sender tidligt: HTML-head, kritisk CSS og de første markup-bytes sendes straks, efterfulgt af den komprimerede krop. Serversidede buffere (f.eks. proxy-buffer, app-framework-buffer) må ikke bremse dette. For server-sendte begivenheder eller chat-lignende streams tjekker jeg, om komprimering er fornuftig: ASCII-begivenheder drager fordel af det, men for aggressiv buffering ødelægger live-effekten. Jeg deaktiverer om nødvendigt proxy-buffering og indstiller moderate niveauer, så heartbeats og små begivenheder ikke hænger fast.
Vary-header, forhandling og „http-komprimeringsfejl“
Den korrekte Varierer-headeren afgør, om caches leverer de passende varianter. Jeg sender konsekvent Vary: Accept-Encoding med komprimeret indhold og forhindrer dermed fejl. Overvågning markerer gerne mål som „ned“, hvis headers er inkonsekvente eller der forekommer dobbeltkodning. Hvis dette sker sporadisk, ser jeg separat på stier via proxy-hops og regioner. Testværktøjer til Gzip/Brotli hjælper mig med at forstå headers og payloads.
Sikkerhed: Komprimering og fortrolige data
Kompression kan i kombination med TLS i bestemte mønstre fremmer side-channel-angreb. Derfor tjekker jeg svar, der indeholder følsomme formularoplysninger og angriberstyret indhold. Hvis omfanget kan varieres, reducerer jeg komprimeringen eller isolerer indholdet. Ofte er det tilstrækkeligt at levere specifikke stier uden komprimering eller uden dynamisk blanding. Sikkerhed går forud for et par sparede kilobyte.
Målemetode: TTFB, CPU, Core Web Vitals
Jeg vurderer TTFB, FCP og LCP parallelt med CPU-tid pr. medarbejder og bytes pr. anmodning. Jeg tester ændringer i niveauer eller procedurer på en kontrolleret måde og sammenligner varianter. Det er vigtigt at skelne klart mellem ressourcetyper, da HTML, JSON og CSS/JS opfører sig forskelligt. Real User Monitoring bekræfter, om ægte enheder drager fordel af ændringerne. Hvis belastningen eller fejlprocenten stiger, ruller jeg hurtigt ændringen tilbage.
Tuning-arbejdsgang: Sådan går jeg frem trin for trin
I starten aktiverer jeg kun moderat Niveauer for dynamiske svar og lader statiske aktiver pakke på forhånd. Derefter kontrollerer jeg, at headeren er korrekt forhandlet, og tilføjer Vary: Accept‑Encoding. Derefter måler jeg TTFB og CPU over spidsbelastning, justerer niveauet i små spring og kontrollerer igen. I næste trin indstiller jeg flush-punkter for tidlige HTML-dele, så browseren renderer tidligere. Til sidst kontrollerer jeg CDN- og proxy-hops for dobbelt komprimering og holder ansvarsområderne klare.
Fejlbilleder i praksis: Symptomer, årsager, løsning
Typisk „http-komprimeringsfejl“ Jeg genkender det i tilbagevendende mønstre:
- Dobbelt kompression:
Indholdskodning: gzip, gzipeller mærkelige binære tegn i HTML. Årsag: Upstream komprimerer allerede, downstream pakker igen. Løsning: Lad kun én instans være ansvarlig.,IndholdskodningKontroller, respekter forudgående komprimering. - Forkert længde:
IndholdslængdePasser ikke til det komprimerede svar, klienter afbryder. Årsag: Længde beregnet før komprimering. Løsning: Udelad længde (chunked) eller indstil korrekt efter komprimering. - Blandede varianter i cachen: Gzip-bytes til klienter uden understøttelse. Årsag: manglende
Vary: Accept-Encoding. Fix: Indstil Vary og tøm cachen. - Timeouts/høj TTFB: Komprimering blokerer arbejdere, ingen tidlige flush-bytes. Løsning: Sænk niveauet, indstil flush-punkter, begræns CPU-budgettet pr. anmodning.
- „Ukendt indholdskodning“: Ældre proxyer fjerner headers eller accepterer
brNej. Løsning: Sørg for at falde tilbage på Gzip, konfigurer Edge til inkompatible hops.
Test og diagnose: hurtig og pålidelig kontrol
Jeg begynder med enkle header-kontroller: curl -sI -H "Accept-Encoding: br,gzip" https://example.org/ bør Indholdskodning og Varierer vise. Derefter indlæser jeg ressourcen uden og med Accept-Encoding og sammenlign bytes. DevTools i browseren afslører størrelsen om ledelse vs. efter dekompression. Under belastning tester jeg varianter separat (p50/p95/p99), fordi kompressionsomkostninger ikke skaleres lineært. Vigtigt: Test via ægte stier (inkl. CDN/proxy-kæde), ikke kun direkte ved oprindelsen.
Server- og framework-faldgruber
På app-niveau er Middleware ofte aktiveres forhastet. Jeg bruger dem kun, hvor der ikke er nogen forudgående reverse-proxy, der komprimerer. I PHP-stacks undgår jeg zlib.output_compression Parallelt med Nginx/Apache-komprimering. I Node/Express begrænser jeg middleware til tekstbaserede ruter og indstiller en minimumsstørrelse. Java-stacks med filtre (f.eks. GzipFilter) får undtagelser for binære formater. Generelt: kun ét komprimeringslag aktivt, klare ansvarsområder.
Hvad man ikke (eller kun sjældent) skal komprimere
Mange formater er allerede komprimeret eller reagerer dårligt: WOFF2-skrifttyper, WebP/AVIF, MP4, PDF, ZIP, WASM. Binære protokoller som Protobuf eller Parquet giver heller ikke mange fordele. SVG er tekst og drager fordel af det, men jeg tjekker det. Range-anmodninger for springmærker i dokumenter. For billeder undgår jeg dekompression i mellemhop: Når det først er komprimeret, forbliver det komprimeret.
API'er og data: Optimering af struktur frem for niveau
Med JSON-API'er bringer strukturerede optimeringer Mere end niveauorgier: Fjern unødvendige felter, tal i stedet for strenge, ingen overdreven formatering i produktionen. Kompas: Hvis svaret efter Gzip/Brotli stadig har mange kilobyte „luft“, er det værd at gennemføre en skema-kur. For GraphQL/REST kan serverbaseret batching reducere antallet af komprimerede svar.
Drift og kapacitetsplanlægning
Komprimering er CPU-arbejde. Jeg planlægger Budgetter pr. medarbejder/pod og begrænser samtidige komprimeringsopgaver. Under belastning skalerer jeg horisontalt og holder niveauet stabilt i stedet for at skrue op i spidsbelastningsperioder. I CDN'en holder jeg øje med regionparitet: Brotli ved kanten aflaster originalt enormt. Jeg kalibrerer alarmer til P95/99 af TTFB og CPU-mætning, ikke kun til gennemsnitsværdier.
Tjekliste for stabil HTTP-komprimering
- Moderate niveauer for dynamiske svar, høje niveauer kun for prækomprimering
- Vedligehold MIME-typelisten eksplicit, udelad billeder/binære formater
- Statisk vs. dynamisk adskillelse, prækomprimering i build/edge
- Vary: Send altid Accept-Encoding, konsistente ETag/Cache-headers
- Indstil minimumsstørrelse og buffergrænser, test rækkeviddeanmodninger
- Placer flush-punkter, hold øje med proxy/app-buffering
- Kun komprimeret med Hop, sikre fallback til Gzip/Plain
- Mål TTFB, CPU og vitale værdier, se p95/p99, foretag ændringer trinvist
- Kontroller specifikt for fejl (dobbelt komprimering, forkert længde)
Gennemgå eksempelkonfigurationer i tankerne
På Apache aktiverer jeg mod_deflate eller mod_brotli, definerer jeg teksttyper eksplicit og indstiller niveauer afhængigt af stien. Til Nginx bruger jeg gzip-direktiver og leverer forkomprimerede .br-filer til statiske aktiver, mens brotli_static eller et modul betjener Edge-varianten. IIS adskiller statisk og dynamisk komprimering, hvilket jeg supplerer med CPU-tærskler og klare typelister. I alle tilfælde kontrollerer jeg Vary-header, Content-Encoding og Content-Length for konsistens. Eksempelværdier hjælper, men i sidste ende er det måling under reel belastning, der tæller.
Kort opsummeret
Den mest effektive Strategi HTTP-komprimering starter konservativt, måler konsekvent og adskiller statisk fra dynamisk. Brotli viser sine styrker ved forkomprimerede tekstaktiver, Gzip eller moderat Brotli holder dynamiske svar slanke nok. Rene headers, klare ansvarsområder i proxy-/CDN-kæder og realistiske tests undgår „http compression errors“. Jeg prioriterer altid tidlig levering af kritiske bytes frem for at tvinge hver eneste procent komprimering igennem. På den måde leverer siden mærkbart hurtigere uden at øge serverbelastningen og fejlmeddelelserne.


