Every third-party origin — Google Fonts, an analytics service, a Stripe CDN — requires a DNS lookup, TCP handshake, and TLS negotiation before the first byte can transfer. On a cold connection, this setup cost takes 100–300ms per origin. A page loading fonts from Google Fonts, scripts from an analytics CDN, and assets from Stripe can accumulate 400–900ms of connection overhead that runs sequentially if browsers encounter these origins mid-parse. <link rel="preconnect"> tells the browser to complete the TCP+TLS handshake during HTML parsing, eliminating that overhead by the time the asset is requested. ISO 25010 performance-efficiency.time-behaviour defines this as an optimizable latency in the system's response pathway.
Info because preconnect hints are an incremental optimization — missing them adds measurable but not catastrophic latency — and their impact depends heavily on network conditions.
Add <link rel="preconnect"> tags in the <head> for each third-party origin loaded on page init. Use dns-prefetch as a lighter fallback for origins that aren't connection-critical. In Next.js, add these to the root layout's <head> or use the metadata API.
<!-- In public/index.html or app/layout.tsx head -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
<link rel="preconnect" href="https://js.stripe.com" />
<link rel="dns-prefetch" href="https://analytics.example.com" />
// Next.js App Router — app/layout.tsx
export default function RootLayout({ children }) {
return (
<html>
<head>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
</head>
<body>{children}</body>
</html>
)
}
Only preconnect to origins loaded during initial page render — preconnecting to rarely-used origins wastes the connection handshake.
ID: performance-load.caching.preconnect-hints
Severity: info
What to look for: Count all unique third-party origins loaded by the application: external fonts, analytics services, CDN-hosted scripts, external API calls from the client, and image CDNs. For each origin, check whether a <link rel="preconnect"> or <link rel="dns-prefetch"> tag exists in the HTML head or root layout. Enumerate: "X third-party origins detected, Y have preconnect or dns-prefetch hints."
Pass criteria: At least 80% of third-party origins that are loaded on the initial page have preconnect or dns-prefetch hints. No more than 1 frequently-used third-party origin should lack a hint. Report: "X of Y third-party origins have preconnect/dns-prefetch hints in the layout head."
Fail criteria: 2 or more third-party origins are loaded (fonts, analytics, CDN scripts, external API calls from the client) with no preconnect or dns-prefetch hints in the layout head.
Skip (N/A) when: No third-party origins are loaded by the application (0 external fonts, 0 CDN scripts, 0 external API calls from the client detected), or assets are entirely self-hosted.
Detail on fail: "0 of 4 third-party origins have preconnect hints — Google Fonts, analytics.example.com, cdn.example.com, and api.stripe.com all lack preconnect" or "1 of 5 external origins has dns-prefetch — 4 CDN origins loaded without connection hints"
Remediation: Add preconnect hints:
<head>
<!-- Preconnect to critical third-party origins -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://api.example.com" />
<link rel="dns-prefetch" href="https://cdn.example.com" />
</head>
Or in Next.js:
export default function RootLayout() {
return (
<html>
<head>
<link rel="preconnect" href="https://fonts.googleapis.com" />
</head>
</html>
)
}