Browser Networking & Resource Loading
Before any JavaScript runs, before any component renders, the browser must fetch resources over the network. The decisions you make about how resources are discovered, prioritized, and delivered determine your app's performance ceiling.
HTTP/1.1 vs HTTP/2 vs HTTP/3
HTTP/1.1 â The Bottleneck
Browser needs: index.html, style.css, app.js, logo.png, font.woff2
HTTP/1.1 (one request per connection):
Connection 1: ââ[index.html]ââ[style.css]ââ[app.js]ââ
Connection 2: ââ[logo.png]ââ[font.woff2]ââ
(Browser opens 6 parallel connections max per domain)Problems:
- Head-of-line blocking â One slow response blocks everything behind it on that connection
- Connection limit â Max 6 connections per domain (workaround: domain sharding)
- Redundant headers â Full headers sent with every request (~500 bytes each)
HTTP/2 â Multiplexing
HTTP/2 (multiple streams on one connection):
Single Connection: ââ[html]ââ[css]ââ[js]ââ[img]ââ[font]ââ
All multiplexed on one TCP connection
Each resource is a "stream"Key features:
- Multiplexing â Multiple requests/responses on a single connection, interleaved
- Header compression (HPACK) â Headers compressed, delta-encoded
- Server push â Server can send resources before the client asks (deprecated in most implementations)
- Stream priority â Client tells server which resources matter most
HTTP/3 â QUIC Protocol
HTTP/3:
Single QUIC Connection (over UDP):
Stream 1: [html] â lost packet? Only stream 1 waits
Stream 2: [css] â keeps flowing
Stream 3: [js] â keeps flowingKey improvement: Eliminates TCP head-of-line blocking. In HTTP/2, a lost TCP packet stalls ALL streams (because TCP guarantees order). HTTP/3 uses QUIC over UDP â each stream is independent. A lost packet in one stream doesn't affect others.
Additional benefits:
- 0-RTT connection establishment â Reconnections skip the handshake
- Connection migration â Survives network changes (WiFi â cellular)
- Built-in encryption â TLS 1.3 baked into the protocol
When Each Protocol Matters
| Scenario | Impact |
|---|---|
| Many small resources (icons, API calls) | HTTP/2 multiplexing eliminates connection limits |
| High-latency connections (mobile, global users) | HTTP/3 0-RTT saves round trips |
| Lossy networks (mobile, WiFi) | HTTP/3 eliminates TCP head-of-line blocking |
| Large bundles | HTTP/2 stream priority ensures critical CSS/JS loads first |
Resource Discovery & Hints
The browser discovers resources in order: HTML â CSS â JS. Resource hints let you tell the browser about resources earlier.
preconnect â Warm Up Connections
<!-- Establish connection before it's needed (DNS + TCP + TLS) -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://api.example.com" crossorigin>Saves 100-500ms per third-party origin. Use for:
- CDN origins
- API servers
- Font providers
- Analytics endpoints
dns-prefetch â DNS Only
<!-- Lighter than preconnect â just DNS resolution -->
<link rel="dns-prefetch" href="https://analytics.example.com">Cheaper than preconnect. Use for origins you'll use later (not immediately).
preload â Critical Resources NOW
<!-- Font needed immediately â don't wait for CSS to discover it -->
<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin>
<!-- Hero image needed for LCP -->
<link rel="preload" href="/images/hero.webp" as="image">
<!-- Critical JS module -->
<link rel="preload" href="/scripts/critical.js" as="script">preload says: "This resource is needed for the current page. Start downloading NOW."
as Value | Resource Type |
|---|---|
script | JavaScript files |
style | CSS files |
font | Font files |
image | Images |
fetch | API responses |
prefetch â Resources for NEXT Page
<!-- User will likely navigate to /dashboard next -->
<link rel="prefetch" href="/dashboard.js" as="script">
<link rel="prefetch" href="/api/dashboard-data" as="fetch">prefetch says: "This resource will be needed on a future page. Download when idle."
preload vs prefetch
| preload | prefetch | |
|---|---|---|
| Priority | High (current page) | Low (future navigation) |
| When used | Needed within seconds | Might be needed eventually |
| Warning if unused | Yes (console warning after 3s) | No |
| Best for | Fonts, hero images, critical JS | Next-page resources |
modulepreload â ES Module Preload
<link rel="modulepreload" href="/components/Header.js">Like preload but also parses and compiles the module immediately, saving time when it's eventually imported.
Resource Loading Priority
The browser assigns priority to resources automatically:
| Resource | Default Priority | Notes |
|---|---|---|
| HTML | Highest | The document itself |
CSS (in <head>) | Highest | Render-blocking |
Sync <script> (in <head>) | High | Parser-blocking |
| Fonts (used above fold) | High | Needed for text rendering |
<script defer> | Low (during parse) | Executed after parsing |
| Images (above fold) | High | Visible to user |
| Images (below fold) | Low | Not immediately needed |
<script async> | Low | Independent script |
| Prefetch resources | Lowest | Future page resources |
fetchpriority â Override Default Priority
<!-- Boost LCP image priority -->
<img src="/hero.webp" fetchpriority="high" alt="Hero">
<!-- Lower priority for below-fold images -->
<img src="/footer-logo.webp" fetchpriority="low" alt="Logo" loading="lazy">
<!-- Boost critical fetch request -->
<link rel="preload" href="/api/critical-data" as="fetch" fetchpriority="high">Lazy Loading
Native Lazy Loading
<!-- Browser handles viewport detection automatically -->
<img src="photo.webp" loading="lazy" alt="Photo">
<iframe src="embed.html" loading="lazy"></iframe>Don't lazy load above-the-fold images â it delays LCP.
Connection-Aware Loading
function getImageQuality() {
const connection = navigator.connection;
if (!connection) return 'high';
if (connection.saveData) return 'low';
if (connection.effectiveType === '4g') return 'high';
if (connection.effectiveType === '3g') return 'medium';
return 'low';
}
function getImageSrc(baseUrl) {
const quality = getImageQuality();
return `${baseUrl}?quality=${quality}`;
}Image Optimization Strategy
<!-- Modern format with fallback -->
<picture>
<source srcset="photo.avif" type="image/avif">
<source srcset="photo.webp" type="image/webp">
<img src="photo.jpg" alt="Photo" width="800" height="600">
</picture>
<!-- Responsive images -->
<img
srcset="photo-400.webp 400w,
photo-800.webp 800w,
photo-1200.webp 1200w"
sizes="(max-width: 600px) 400px,
(max-width: 1000px) 800px,
1200px"
src="photo-800.webp"
alt="Photo"
width="800"
height="600"
loading="lazy"
decoding="async"
>Always set width and height â prevents layout shifts (CLS) by reserving space.
Critical Request Chain
The critical request chain is the sequence of dependent requests that must complete before first render:
Without optimization:
HTML â CSS â @import CSS â Font (discovered in CSS) â Render
1 2 3 4 total: 4 round trips
With optimization:
HTML (inline critical CSS + preload font) â Render
1 total: 1 round tripAudit with Lighthouse
Lighthouse shows the critical request chain in its report:
- Which resources block rendering
- The depth of the chain (number of serial round trips)
- Total bytes on the critical path
Compression
Original: app.js (500KB)
Gzip: app.js.gz (120KB) â 76% reduction
Brotli: app.js.br (95KB) â 81% reductionBrotli (br) is 15-25% smaller than Gzip for text assets. All modern browsers support it over HTTPS.
# Nginx configuration
brotli on;
brotli_types text/html text/css application/javascript application/json;Interview Signal
Senior candidates demonstrate:
- Protocol evolution â HTTP/1.1 limitations, HTTP/2 multiplexing, HTTP/3 QUIC advantages
- Resource hint fluency â preconnect, preload, prefetch â and when each applies
- Priority understanding â Browser's default priorities and how to override them
- Critical path thinking â Minimizing the request chain depth for faster first render
- Image strategy â Responsive images, modern formats, lazy loading, CLS prevention