SkillPilotAI

Web Performance: Compression, Caching, SSR/CSR/SSG

Show the page quickly on the user's phone: send fewer bytes (Gzip/Brotli), do not send again (Cache-Control/ETag), load only when needed (lazy) and choose the right rendering.

52.1 Why is it used?

  • Every extra 100ms of load time lowers conversion; in e-commerce a slow page means an abandoned cart.
  • Many users in India are on slow 4G/budget phones; heavy JS and big images make the page slow for them.
  • Compression and browser caching reduce both the bandwidth bill and server load.
  • Core Web Vitals (LCP, INP, CLS) count in Google search ranking; performance matters for SEO.
  • On sale day, if static files come from the browser/CDN cache, the load on the origin server drops a lot.

52.2 How it works

  • Gzip: older text compression supported everywhere (HTML/CSS/JS/JSON); cuts size by roughly 60-80%; header Content-Encoding: gzip.
  • Brotli: Google's newer algorithm, producing roughly 15-25% smaller output than Gzip on text files; supported over HTTPS, header Content-Encoding: br.
  • Cache-Control: max-age=31536000, immutable for hashed static files (app.3f9a.js); no-cache for HTML (revalidate every time); no-store for sensitive data.
  • ETag / Last-Modified: the server sends a version tag; the browser sends If-None-Match, and if the file is the same it gets 304 Not Modified; the body is not sent again.
  • Lazy Loading: images/components lower down load only when they come onto the screen: img loading="lazy", dynamic import(), code splitting.
  • CSR (Client-Side Rendering): empty HTML + a big JS bundle, the page is built in the browser; fine for interactive apps, but weak first load and SEO.
  • SSR (Server-Side Rendering): the server builds and sends HTML on every request, then hydration; fast first paint, good SEO, higher server cost.
  • SSG / ISR: HTML is generated at build time and served from the CDN; the fastest; with ISR (Next.js) the page regenerates in the background every N seconds.
Compression + browser caching headers: sale landing page
  1. 1.Browser (Chrome, slow 4G): 1 GET /static/app.3f9a.js
  2. 2.CDN edge (Cloudflare / CloudFront) + Nginx origin (gzip on; brotli; ETag): 2 200 OK, Content-Encoding: br, 2 MB -> ~500 KB, Cache-Control: max-age=31536000, immutable
  3. 3.Browser cache: app.3f9a.js, CSS; repeat visit = cache hit, 0 network
  4. 4.HTML revalidation: 3 GET /index.html If-None-Match: "v7" -> 4 304 Not Modified, no body, only headers

Hashed JS/CSS = immutable for 1 year; HTML = no-cache + ETag; sensitive = no-store.

Lazy loading and where the HTML is built
  1. 1.Lazy loading: on the first screen (above the fold) the Hero banner loads instantly as WebP, and so do Price + Buy; images further down use img loading="lazy"; the Reviews widget uses dynamic import and loads only when scrolled to
  2. 2.CSR: empty HTML + 2 MB JS -> JS runs, API call -> page built in the browser; slow first load, weak SEO; best: dashboard, admin panel
  3. 3.SSR (Next.js): HTML built on the server on every request -> ready HTML, fast paint -> hydration, interactive; good SEO, higher server cost; best: product page with live price/stock
  4. 4.SSG / ISR: HTML at build time -> ready HTML from the CDN, revalidate: 60s; fastest, low server load; best: sale landing, blog, category

Result (WebPageTest, Mumbai 4G): LCP 6s -> ~2s; JS 2 MB -> 500 KB; very little traffic on the origin.

52.3 Tools

ToolTypeHow it is used
Next.jsReact frameworkIn one app you can choose per-page SSR, SSG, ISR (revalidate: 60) and CSR; next/image gives automatic lazy loading and resizing.
NginxWeb serverRules such as gzip on; the brotli module; location /static { expires 1y; add_header Cache-Control "public, immutable"; }.
LighthouseAudit toolBuilt into Chrome DevTools; gives a performance score, LCP/CLS/TBT and suggestions (unused JS, uncompressed text).
WebPageTestTesting toolTests from real devices and locations (Mumbai, slow 4G) and shows what is slow with a waterfall chart and filmstrip.
Cloudflare / CloudFrontCDNBrotli compression, cache rules and image optimization (resize, WebP/AVIF) at the edge, automatically.
Webpack / ViteBundlerDo code splitting, tree shaking, minification and hashed filenames so that long caching is safe.

52.4 Comparison: CSR vs SSR vs SSG (ISR)

PointCSRSSRSSG / ISR
When the HTML is builtIn the browser, after JS runsOn the server, on every requestAt build time (periodically with ISR)
First load speedSlow: JS must download firstFast first paintFastest: ready HTML from the CDN
SEOWeak (the crawler has to run JS)GoodVery good
Server loadLow: only static filesHigh: renders on every requestVery low: the CDN serves it
Data freshnessReal-time (API call)Real-time per requestStale until the build or revalidate time
PersonalizationEasyEasy (cookie based)Hard: has to be added client side
Best forDashboards, admin panels, logged-in appsProduct page with live price/stock, newsBlogs, docs, landing pages, category pages

52.5 When to choose which

  • Brotli for text (over HTTPS), Gzip as a fallback; do not compress images again: use WebP/AVIF.
  • Hashed static files: Cache-Control max-age=1 year + immutable; HTML: no-cache + ETag.
  • SSG/ISR: when content rarely changes and you need SEO: marketing pages, blogs, category listings.
  • SSR: when you need SEO and the data must be fresh on every request: a product page with price/stock.
  • CSR: dashboards after login where SEO is not needed.

52.6 Real-world example

An illustrative scenario: optimizing an e-commerce sale landing page.

  1. Lighthouse report: LCP 6s, JS bundle 2 MB, uncompressed JPEG images, no caching headers.
  2. Brotli is enabled on Nginx/CDN; the 2 MB JS becomes roughly 500 KB in transfer.
  3. Hashed filenames from the bundler + Cache-Control max-age=1 year; on a repeat visit JS/CSS come from the browser cache, 0 network.
  4. HTML gets no-cache + ETag: it is checked every time, and if unchanged the answer is 304 Not Modified (headers only).
  5. Banner images in WebP, product images further down with loading=lazy; the first screen appears quickly.
  6. The landing page is served from the CDN via SSG + ISR (revalidate 60s); the product page uses SSR so price/stock stay live.
  7. Retest on WebPageTest (Mumbai, 4G): LCP from 6s to roughly 2s; very little traffic on the origin server.

52.7 Interview tips

  • no-cache does not mean 'do not cache', it means 'revalidate before using'; no-store means do not store at all.
  • Common mistake: putting a long max-age on index.html; a new deploy will not reach users, so HTML should always have a short cache or revalidate.
  • Running gzip again on already compressed files (JPEG, MP4, ZIP) wastes CPU and does not reduce size.
  • Lazy loading even the above-the-fold hero image makes LCP worse. Numbers to quote: Brotli 2 MB -> ~500 KB, LCP 6s -> ~2s.