PatternsCore Optimizations
Resource Hints
Use preconnect, dns-prefetch, and preload to eliminate network latency and accelerate resource loading.
Resource Hints
Problem
Each external resource (APIs, CDNs, fonts) requires DNS lookup, TCP connection, and TLS handshake. This adds 300-1000ms of latency before downloading even starts. For apps using multiple third-party services, this compounds quickly.
Solution
Use resource hints to tell the browser to perform these operations early, in parallel with page parsing.
/**
* Resource hint types
*/
type HintType = 'preconnect' | 'dns-prefetch' | 'preload' | 'prefetch' | 'prerender';
interface ResourceHint {
type: HintType;
href: string;
as?: string;
crossOrigin?: 'anonymous' | 'use-credentials';
}
/**
* Add resource hint to document
*/
function addResourceHint(hint: ResourceHint): HTMLLinkElement {
const link = document.createElement('link');
link.rel = hint.type;
link.href = hint.href;
if (hint.as) {
link.as = hint.as;
}
if (hint.crossOrigin) {
link.crossOrigin = hint.crossOrigin;
}
document.head.appendChild(link);
return link;
}
/**
* Resource hint manager
*/
class ResourceHintManager {
private hints = new Set<string>();
/**
* Preconnect to origin (DNS + TCP + TLS)
*/
public preconnect(origin: string, crossOrigin?: 'anonymous' | 'use-credentials'): void {
const key = `preconnect:${origin}`;
if (this.hints.has(key)) {
return;
}
addResourceHint({
type: 'preconnect',
href: origin,
crossOrigin,
});
this.hints.add(key);
}
/**
* DNS prefetch only (lighter than preconnect)
*/
public dnsPrefetch(origin: string): void {
const key = `dns-prefetch:${origin}`;
if (this.hints.has(key)) {
return;
}
addResourceHint({
type: 'dns-prefetch',
href: origin,
});
this.hints.add(key);
}
/**
* Preload critical resource
*/
public preload(
href: string,
as: string,
crossOrigin?: 'anonymous' | 'use-credentials'
): void {
const key = `preload:${href}`;
if (this.hints.has(key)) {
return;
}
addResourceHint({
type: 'preload',
href,
as,
crossOrigin,
});
this.hints.add(key);
}
/**
* Prefetch resource for next navigation
*/
public prefetch(href: string): void {
const key = `prefetch:${href}`;
if (this.hints.has(key)) {
return;
}
addResourceHint({
type: 'prefetch',
href,
});
this.hints.add(key);
}
/**
* Preconnect to multiple origins
*/
public preconnectMultiple(origins: string[]): void {
// Browsers limit preconnect to 6-10 origins
const maxPreconnects = 6;
origins.slice(0, maxPreconnects).forEach((origin) => {
this.preconnect(origin);
});
}
}
// Practical examples
/**
* Setup resource hints for common third-party services
*/
class ThirdPartyOptimizer {
private hintManager = new ResourceHintManager();
public setupAnalytics(): void {
// Google Analytics
this.hintManager.preconnect('https://www.google-analytics.com');
this.hintManager.preconnect('https://www.googletagmanager.com');
}
public setupFonts(): void {
// Google Fonts
this.hintManager.preconnect('https://fonts.googleapis.com');
this.hintManager.preconnect('https://fonts.gstatic.com', 'anonymous');
// Preload critical font
this.hintManager.preload(
'https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Me5WZLCzYlKw.woff2',
'font',
'anonymous'
);
}
public setupCDN(): void {
// Cloudflare CDN
this.hintManager.preconnect('https://cdnjs.cloudflare.com');
}
public setupAPIs(apiOrigins: string[]): void {
// Preconnect to primary API
this.hintManager.preconnect(apiOrigins[0], 'use-credentials');
// DNS prefetch for secondary APIs
apiOrigins.slice(1).forEach((origin) => {
this.hintManager.dnsPrefetch(origin);
});
}
public setupImages(): void {
// Image CDN
this.hintManager.preconnect('https://images.example.com');
// Preload hero image
this.hintManager.preload(
'https://images.example.com/hero.jpg',
'image'
);
}
}
/**
* Smart prefetching based on user behavior
*/
class SmartPrefetcher {
private hintManager = new ResourceHintManager();
private hoveredLinks = new Map<string, number>();
constructor() {
this.setupLinkHoverPrefetch();
}
/**
* Prefetch when user hovers over link
*/
private setupLinkHoverPrefetch(): void {
let hoverTimeout: ReturnType<typeof setTimeout> | null = null;
document.addEventListener('mouseover', (event: MouseEvent) => {
const target = event.target as HTMLElement;
const link = target.closest('a[href]') as HTMLAnchorElement;
if (!link || !link.href) {
return;
}
// Wait 200ms to avoid prefetching during fast mouse movement
hoverTimeout = setTimeout(() => {
this.prefetchLink(link.href);
}, 200);
});
document.addEventListener('mouseout', () => {
if (hoverTimeout) {
clearTimeout(hoverTimeout);
}
});
}
/**
* Prefetch link intelligently
*/
private prefetchLink(href: string): void {
// Don't prefetch same origin (already connected)
const url = new URL(href, window.location.origin);
if (url.origin === window.location.origin) {
this.hintManager.prefetch(href);
} else {
this.hintManager.preconnect(url.origin);
}
// Track hover count
const count = this.hoveredLinks.get(href) || 0;
this.hoveredLinks.set(href, count + 1);
}
/**
* Prefetch most likely next page
*/
public prefetchNextPage(likelyUrls: string[]): void {
// Prefetch top 3 most likely next pages
likelyUrls.slice(0, 3).forEach((url) => {
this.hintManager.prefetch(url);
});
}
}
/**
* Conditional preconnect based on feature usage
*/
class ConditionalPreconnect {
private hintManager = new ResourceHintManager();
public setupVideoPlayer(): void {
// Only preconnect to video CDN if video element exists
if (document.querySelector('video')) {
this.hintManager.preconnect('https://video-cdn.example.com');
}
}
public setupPayment(): void {
// Preconnect to payment gateway when user adds to cart
document.addEventListener('cart:add', () => {
this.hintManager.preconnect('https://api.stripe.com');
});
}
public setupChat(): void {
// Preconnect to chat service on user interaction
const chatButton = document.getElementById('chat-button');
chatButton?.addEventListener('click', () => {
this.hintManager.preconnect('https://chat.example.com');
}, { once: true });
}
}HTML Implementation
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Optimized App</title>
<!-- Preconnect to critical origins (highest priority) -->
<link rel="preconnect" href="https://api.example.com" crossorigin="use-credentials">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="anonymous">
<!-- DNS prefetch for secondary origins (lower priority) -->
<link rel="dns-prefetch" href="https://www.google-analytics.com">
<link rel="dns-prefetch" href="https://cdn.example.com">
<!-- Preload critical resources -->
<link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin="anonymous">
<link rel="preload" href="/images/hero.jpg" as="image">
<link rel="preload" href="/styles/critical.css" as="style">
<link rel="stylesheet" href="/styles/critical.css">
</head>
<body>
<img src="/images/hero.jpg" alt="Hero">
</body>
</html>Performance Impact
Before Resource Hints
DNS lookup: 120ms
TCP connect: 80ms
TLS handshake: 100ms
Total: 300ms (before first byte)After Resource Hints
DNS lookup: 0ms (done in parallel)
TCP connect: 0ms (done in parallel)
TLS handshake: 0ms (done in parallel)
Total: 0ms (ready when needed)Time saved: 300-1000ms per origin
When to Use Each Hint
Preconnect (DNS + TCP + TLS)
✅ Use for:
- Primary API origin
- Critical font CDN
- Payment gateway
- Auth service
❌ Don't use for:
- More than 6 origins (browser limit)
- Unlikely-to-be-used resources
- Same-origin resources (already connected)
DNS Prefetch (DNS only)
✅ Use for:
- Secondary origins
- Analytics services
- Social media widgets
- When preconnect limit reached
Preload (high priority download)
✅ Use for:
- Critical fonts (above-the-fold)
- Hero images (LCP)
- Critical CSS
- Main JavaScript bundle
❌ Don't use for:
- Below-the-fold resources
- More than 3-5 resources (causes congestion)
- Resources that might not be used
Prefetch (low priority for next page)
✅ Use for:
- Next page in a flow
- Likely navigation targets
- User-hovered links
Best Practices
- Limit preconnects: Maximum 6 origins
- Prioritize: Use preconnect for immediate needs, dns-prefetch for future
- Combine with CDN: Fewer origins = fewer preconnects needed
- Test on real networks: 3G/4G shows biggest gains
- Monitor: Track connection timing in analytics
Impact on Core Web Vitals
- LCP: 15-30% faster (fonts and images load sooner)
- FID: Minimal direct impact
- CLS: Prevents layout shift from late-loading fonts
For apps with millions of users, resource hints can save hundreds of hours of cumulative waiting time per day.
Usage
// Initialize optimizers
const thirdParty = new ThirdPartyOptimizer();
thirdParty.setupFonts();
thirdParty.setupAnalytics();
thirdParty.setupAPIs(['https://api.example.com']);
// Smart prefetching
const prefetcher = new SmartPrefetcher();
prefetcher.prefetchNextPage(['/checkout', '/cart']);
// Conditional preconnect
const conditional = new ConditionalPreconnect();
conditional.setupVideoPlayer();
conditional.setupPayment();Resource hints are free performance wins with minimal code and zero runtime cost.