[{"data":1,"prerenderedAt":511},["ShallowReactive",2],{"guide-server-side-html-optimization":3},{"id":4,"title":5,"body":6,"date":502,"description":503,"extension":504,"meta":505,"navigation":403,"path":506,"readingTime":507,"seo":508,"stem":509,"__hash__":510},"guides\u002Fguides\u002Fserver-side-html-optimization.md","Server-Side HTML Optimization: From Compression to Caching",{"type":7,"value":8,"toc":491},"minimark",[9,13,18,21,89,92,134,137,141,144,150,161,168,173,182,193,196,224,228,231,234,249,252,256,259,262,294,297,301,304,365,368,372,379,416,419,423,450,454,475,479,487],[10,11,12],"p",{},"Server-side HTML optimization covers every technique that reduces the time between a user's request and the moment the browser receives a complete HTML response. Unlike client-side optimizations that run in the browser, these strategies operate on your server, CDN, or edge network — shrinking response size, cutting Time to First Byte (TTFB), and minimizing redundant work.",[14,15,17],"h2",{"id":16},"compression-the-biggest-win","Compression: The Biggest Win",[10,19,20],{},"Enabling gzip or Brotli compression is the single most impactful server-side optimization. Most HTML files are highly compressible because they contain repetitive tags and attributes.",[22,23,24,43],"table",{},[25,26,27],"thead",{},[28,29,30,34,37,40],"tr",{},[31,32,33],"th",{},"Algorithm",[31,35,36],{},"Compression Ratio",[31,38,39],{},"CPU Cost",[31,41,42],{},"Browser Support",[44,45,46,61,75],"tbody",{},[28,47,48,52,55,58],{},[49,50,51],"td",{},"gzip (level 6)",[49,53,54],{},"70–75%",[49,56,57],{},"Low",[49,59,60],{},"Universal",[28,62,63,66,69,72],{},[49,64,65],{},"Brotli (level 4)",[49,67,68],{},"78–83%",[49,70,71],{},"Moderate",[49,73,74],{},"Modern browsers",[28,76,77,80,83,86],{},[49,78,79],{},"Zstd (level 3)",[49,81,82],{},"76–82%",[49,84,85],{},"Very low",[49,87,88],{},"Chrome 123+, Firefox 126+",[10,90,91],{},"For dynamic HTML generated on each request, use moderate compression levels (4–6) to balance CPU usage and file size. For static HTML, pre-compress at build time using the highest levels — there is no runtime cost.",[93,94,99],"pre",{"className":95,"code":96,"language":97,"meta":98,"style":98},"language-nginx shiki shiki-themes github-light github-dark","# Nginx: enable gzip for HTML\ngzip on;\ngzip_types text\u002Fhtml;\ngzip_min_length 1024;\ngzip_comp_level 6;\n","nginx","",[100,101,102,110,116,122,128],"code",{"__ignoreMap":98},[103,104,107],"span",{"class":105,"line":106},"line",1,[103,108,109],{},"# Nginx: enable gzip for HTML\n",[103,111,113],{"class":105,"line":112},2,[103,114,115],{},"gzip on;\n",[103,117,119],{"class":105,"line":118},3,[103,120,121],{},"gzip_types text\u002Fhtml;\n",[103,123,125],{"class":105,"line":124},4,[103,126,127],{},"gzip_min_length 1024;\n",[103,129,131],{"class":105,"line":130},5,[103,132,133],{},"gzip_comp_level 6;\n",[10,135,136],{},"Most CDNs enable compression automatically. If you manage your own server, gzip should be the first line in your optimization checklist — before minification, before caching, before anything else.",[14,138,140],{"id":139},"http-caching-headers","HTTP Caching Headers",[10,142,143],{},"Caching prevents the server from re-generating or re-sending HTML that has not changed. The right headers depend on whether your pages are static or dynamic.",[10,145,146],{},[147,148,149],"strong",{},"Static pages (SSG):",[93,151,155],{"className":152,"code":153,"language":154,"meta":98,"style":98},"language-http shiki shiki-themes github-light github-dark","Cache-Control: public, max-age=31536000, immutable\n","http",[100,156,157],{"__ignoreMap":98},[103,158,159],{"class":105,"line":106},[103,160,153],{},[10,162,163,164,167],{},"These pages never change between deployments. The ",[100,165,166],{},"immutable"," flag tells the browser to skip conditional.requests — zero network round-trips on repeat visits.",[10,169,170],{},[147,171,172],{},"Dynamic pages (SSR):",[93,174,176],{"className":152,"code":175,"language":154,"meta":98,"style":98},"Cache-Control: public, max-age=0, s-maxage=3600, stale-while-revalidate=86400\n",[100,177,178],{"__ignoreMap":98},[103,179,180],{"class":105,"line":106},[103,181,175],{},[10,183,184,185,188,189,192],{},"The CDN caches the response for one hour (",[100,186,187],{},"s-maxage","). After that, it serves the stale version while fetching a fresh copy in the background (",[100,190,191],{},"stale-while-revalidate","). Users always get a fast response.",[10,194,195],{},"Common caching mistakes:",[197,198,199,209,218],"ul",{},[200,201,202,208],"li",{},[147,203,204,205],{},"Missing ",[100,206,207],{},"Vary: Accept-Encoding"," — caches may serve gzip content to browsers that requested uncompressed HTML",[200,210,211,217],{},[147,212,213,214],{},"Overly short ",[100,215,216],{},"max-age"," — reconsider whether your content truly changes every few minutes",[200,219,220,223],{},[147,221,222],{},"No cache invalidation strategy"," — when content updates, you need a way to purge stale entries",[14,225,227],{"id":226},"html-minification-at-the-server","HTML Minification at the Server",[10,229,230],{},"For server-rendered apps (Next.js, Nuxt, Express), HTML is generated dynamically and often retains template indentation and whitespace. Minifying this output reduces the response body by 15–35%.",[10,232,233],{},"Two approaches:",[235,236,237,243],"ol",{},[200,238,239,242],{},[147,240,241],{},"Middleware minification"," — an Express\u002FNuxt middleware minifies each response before sending it. Simple but adds latency on every request.",[200,244,245,248],{},[147,246,247],{},"CDN auto-minification"," — Cloudflare and Akamai can minify HTML at the edge. No server changes required, but adds processing time at the CDN layer.",[10,250,251],{},"For static sites, minify at build time instead. It is faster, more predictable, and produces identical results on every deploy.",[14,253,255],{"id":254},"streaming-html-responses","Streaming HTML Responses",[10,257,258],{},"Traditional SSR waits for the entire page to render before sending anything. Streaming sends HTML in chunks — the browser can start parsing and rendering before the full response arrives.",[10,260,261],{},"Frameworks like Nuxt and Next.js support streaming out of the box:",[197,263,264,278,284],{},[200,265,266,269,270,273,274,277],{},[147,267,268],{},"Nuxt",": Enable with ",[100,271,272],{},"experimental.componentIslands"," or use ",[100,275,276],{},"renderResponse"," with streaming",[200,279,280,283],{},[147,281,282],{},"Next.js",": App Router streams by default with Suspense boundaries",[200,285,286,289,290,293],{},[147,287,288],{},"Remix",": Streams responses when you ",[100,291,292],{},"defer"," loader data",[10,295,296],{},"Streaming reduces TTFB and First Contentful Paint (FCP) because the browser receives the document head and initial shell immediately. Slow data fetching no longer blocks the entire page.",[14,298,300],{"id":299},"edge-rendering","Edge Rendering",[10,302,303],{},"Edge rendering moves your SSR logic from a single origin server to CDN edge nodes worldwide. This cuts network latency because the HTML is generated physically closer to the user.",[22,305,306,319],{},[25,307,308],{},[28,309,310,313,316],{},[31,311,312],{},"Platform",[31,314,315],{},"Edge Runtime",[31,317,318],{},"Latency Reduction",[44,320,321,332,343,354],{},[28,322,323,326,329],{},[49,324,325],{},"Cloudflare Workers",[49,327,328],{},"V8 isolates",[49,330,331],{},"50–150 ms",[28,333,334,337,340],{},[49,335,336],{},"Vercel Edge",[49,338,339],{},"V8 \u002F Deno",[49,341,342],{},"30–100 ms",[28,344,345,348,351],{},[49,346,347],{},"Netlify Edge",[49,349,350],{},"Deno",[49,352,353],{},"40–120 ms",[28,355,356,359,362],{},[49,357,358],{},"AWS Lambda@Edge",[49,360,361],{},"Node.js",[49,363,364],{},"30–80 ms",[10,366,367],{},"Edge runtimes have limitations — restricted Node.js API access, smaller memory limits, no filesystem. Use them for pages that need personalization but not heavy computation. For compute-intensive pages, stick with origin SSR and strong CDN caching.",[14,369,371],{"id":370},"early-hints-103-status","Early Hints (103 Status)",[10,373,374,375,378],{},"The ",[100,376,377],{},"103 Early Hints"," response lets the server send resource hints before the final HTML is ready. The browser can start loading critical CSS, JavaScript, or preconnecting to origins while the server finishes rendering.",[93,380,382],{"className":152,"code":381,"language":154,"meta":98,"style":98},"HTTP\u002F1.1 103 Early Hints\nLink: \u003C\u002Fcss\u002Fcritical.css>; rel=preload; as=style\nLink: \u003C\u002Fjs\u002Fapp.js>; rel=modulepreload\n\nHTTP\u002F1.1 200 OK\nContent-Type: text\u002Fhtml\n",[100,383,384,389,394,399,405,410],{"__ignoreMap":98},[103,385,386],{"class":105,"line":106},[103,387,388],{},"HTTP\u002F1.1 103 Early Hints\n",[103,390,391],{"class":105,"line":112},[103,392,393],{},"Link: \u003C\u002Fcss\u002Fcritical.css>; rel=preload; as=style\n",[103,395,396],{"class":105,"line":118},[103,397,398],{},"Link: \u003C\u002Fjs\u002Fapp.js>; rel=modulepreload\n",[103,400,401],{"class":105,"line":124},[103,402,404],{"emptyLinePlaceholder":403},true,"\n",[103,406,407],{"class":105,"line":130},[103,408,409],{},"HTTP\u002F1.1 200 OK\n",[103,411,413],{"class":105,"line":412},6,[103,414,415],{},"Content-Type: text\u002Fhtml\n",[10,417,418],{},"Early Hints work最好的当 SSR takes 200 ms or more. The browser uses that wait time productively instead of sitting idle. Cloudflare and Vercel support Early Hints with zero configuration changes.",[14,420,422],{"id":421},"key-takeaways","Key Takeaways",[197,424,425,428,441,444,447],{},[200,426,427],{},"Enable gzip or Brotli compression first — it delivers the largest size reduction with the least effort",[200,429,430,431,434,435,437,438,440],{},"Use ",[100,432,433],{},"Cache-Control"," with ",[100,436,187],{}," and ",[100,439,191],{}," for dynamic pages",[200,442,443],{},"Minify SSR output via middleware or CDN, but prefer build-time minification for static sites",[200,445,446],{},"Stream HTML responses so the browser can start rendering before the full page is ready",[200,448,449],{},"Edge rendering reduces latency for personalized pages but has runtime limitations",[14,451,453],{"id":452},"related-guides","Related Guides",[197,455,456,463,469],{},[200,457,458],{},[459,460,462],"a",{"href":461},"\u002Fguides\u002Fhtml-minification-guide","HTML Minification: Reducing Page Size for Faster Loading",[200,464,465],{},[459,466,468],{"href":467},"\u002Fguides\u002Fhtml-minification-vs-gzip","HTML Minification vs Gzip Compression",[200,470,471],{},[459,472,474],{"href":473},"\u002Fguides\u002Fweb-performance-basics","Web Performance Basics: From First Byte to Interactive",[14,476,478],{"id":477},"try-it-yourself","Try It Yourself",[10,480,481,482,486],{},"Minify your HTML server output with our free ",[459,483,485],{"href":484},"\u002Ftools\u002Fhtml-minifier","HTML Minifier",". Paste your rendered markup and see instant size reduction — then deploy minification at build time or via your CDN for production traffic.",[488,489,490],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":98,"searchDepth":112,"depth":112,"links":492},[493,494,495,496,497,498,499,500,501],{"id":16,"depth":112,"text":17},{"id":139,"depth":112,"text":140},{"id":226,"depth":112,"text":227},{"id":254,"depth":112,"text":255},{"id":299,"depth":112,"text":300},{"id":370,"depth":112,"text":371},{"id":421,"depth":112,"text":422},{"id":452,"depth":112,"text":453},{"id":477,"depth":112,"text":478},"2026-05-28","Learn how server-side HTML optimization techniques — including compression, caching, streaming, and edge rendering — reduce load times and TTFB.","md",{"immutable":403},"\u002Fguides\u002Fserver-side-html-optimization",7,{"title":5,"description":503},"guides\u002Fserver-side-html-optimization","Y6VFUh_E7fb60YndWq3FDrx3eMKUvu80J8WvAxBew3M",1780401336748]