Resource Hints and Preloading Strategies: Optimizing Web Performance
A practical Fusebox guide to resource hints and preloading strategies.
Resource Hints and Preloading Strategies: Optimizing Web Performance
Resource hints are powerful browser directives that help optimize loading performance by informing the browser about resources it will need in the near future. This guide explores how to detect, analyze, and implement resource hints for maximum performance gains.
Run This Resource Hint Analyzer Now
// Copy and paste this into your browser console to analyze resource loading strategies
class ResourceHintAnalyzer {
constructor() {
this.hints = {
preconnect: [],
prefetch: [],
preload: [],
prerender: [],
dnsPrefetch: [],
modulePreload: []
};
this.criticalResources = [];
this.performance = window.performance;
this.recommendations = [];
}
analyzeResourceHints() {
console.log('=� Analyzing Resource Hints and Loading Strategies...\n');
// Detect existing resource hints
this.detectResourceHints();
// Analyze resource timing
this.analyzeResourceTiming();
// Identify critical resources
this.identifyCriticalResources();
// Analyze third-party domains
this.analyzeThirdPartyDomains();
// Check for inefficient loading patterns
this.detectInefficiencies();
// Generate optimization report
this.generateOptimizationReport();
}
detectResourceHints() {
// Check link elements for resource hints
const links = document.querySelectorAll('link');
links.forEach(link => {
const rel = link.rel.toLowerCase();
const href = link.href;
if (rel === 'preconnect') {
this.hints.preconnect.push({
href,
crossorigin: link.crossOrigin
});
} else if (rel === 'prefetch') {
this.hints.prefetch.push({
href,
as: link.as,
type: link.type
});
} else if (rel === 'preload') {
this.hints.preload.push({
href,
as: link.as,
type: link.type,
crossorigin: link.crossOrigin,
media: link.media
});
} else if (rel === 'prerender') {
this.hints.prerender.push({ href });
} else if (rel === 'dns-prefetch') {
this.hints.dnsPrefetch.push({ href });
} else if (rel === 'modulepreload') {
this.hints.modulePreload.push({ href });
}
});
// Check for HTTP Link headers
this.checkHTTPHeaders();
}
checkHTTPHeaders() {
// Check the main document's headers
const entries = this.performance.getEntriesByType('navigation');
if (entries.length > 0) {
console.log('9 Note: HTTP Link headers cannot be fully detected from JavaScript');
console.log(' Check Network tab for Link headers in response');
}
}
analyzeResourceTiming() {
const resources = this.performance.getEntriesByType('resource');
const timingAnalysis = {
byType: {},
slowResources: [],
domains: new Map()
};
resources.forEach(resource => {
const type = this.getResourceType(resource.name);
const duration = resource.duration;
const domain = new URL(resource.name).hostname;
// Group by type
if (!timingAnalysis.byType[type]) {
timingAnalysis.byType[type] = {
count: 0,
totalDuration: 0,
resources: []
};
}
timingAnalysis.byType[type].count++;
timingAnalysis.byType[type].totalDuration += duration;
timingAnalysis.byType[type].resources.push({
url: resource.name,
duration: Math.round(duration),
size: resource.transferSize || 0
});
// Track slow resources
if (duration > 500) {
timingAnalysis.slowResources.push({
url: resource.name,
type,
duration: Math.round(duration),
startTime: Math.round(resource.startTime)
});
}
// Track domains
if (!timingAnalysis.domains.has(domain)) {
timingAnalysis.domains.set(domain, {
count: 0,
totalDuration: 0,
hasPreconnect: this.hints.preconnect.some(h => h.href.includes(domain))
});
}
const domainStats = timingAnalysis.domains.get(domain);
domainStats.count++;
domainStats.totalDuration += duration;
});
this.timingAnalysis = timingAnalysis;
}
getResourceType(url) {
const extension = url.split('.').pop().split('?')[0].toLowerCase();
const typeMap = {
'js': 'JavaScript',
'mjs': 'JavaScript',
'css': 'CSS',
'jpg': 'Image',
'jpeg': 'Image',
'png': 'Image',
'gif': 'Image',
'webp': 'Image',
'svg': 'Image',
'woff': 'Font',
'woff2': 'Font',
'ttf': 'Font',
'otf': 'Font',
'json': 'Data',
'xml': 'Data'
};
return typeMap[extension] || 'Other';
}
identifyCriticalResources() {
// Identify render-blocking resources
const stylesheets = document.querySelectorAll('link[rel="stylesheet"]');
const scripts = document.querySelectorAll('script[src]');
stylesheets.forEach(stylesheet => {
if (!stylesheet.media || stylesheet.media === 'all' || stylesheet.media === 'screen') {
this.criticalResources.push({
type: 'CSS',
url: stylesheet.href,
renderBlocking: true,
preloaded: this.hints.preload.some(h => h.href === stylesheet.href)
});
}
});
scripts.forEach(script => {
if (!script.async && !script.defer && script.src) {
this.criticalResources.push({
type: 'JavaScript',
url: script.src,
renderBlocking: true,
preloaded: this.hints.preload.some(h => h.href === script.src)
});
}
});
// Check for critical fonts
if (document.fonts) {
document.fonts.forEach(font => {
if (font.status === 'loaded') {
this.criticalResources.push({
type: 'Font',
family: font.family,
url: 'Unknown (check CSS)',
renderBlocking: false,
preloaded: false
});
}
});
}
}
analyzeThirdPartyDomains() {
const currentDomain = window.location.hostname;
const thirdPartyDomains = new Map();
this.timingAnalysis.domains.forEach((stats, domain) => {
if (!domain.includes(currentDomain) && domain !== currentDomain) {
thirdPartyDomains.set(domain, stats);
}
});
// Check which third-party domains could benefit from preconnect
thirdPartyDomains.forEach((stats, domain) => {
if (!stats.hasPreconnect && stats.count >= 2) {
this.recommendations.push({
type: 'preconnect',
domain,
reason: `${stats.count} resources loaded from this domain`,
impact: 'high'
});
}
});
this.thirdPartyDomains = thirdPartyDomains;
}
detectInefficiencies() {
// Check for missing preload on critical resources
this.criticalResources.forEach(resource => {
if (resource.renderBlocking && !resource.preloaded) {
this.recommendations.push({
type: 'preload',
resource: resource.url,
as: resource.type.toLowerCase(),
reason: 'Render-blocking resource not preloaded',
impact: 'high'
});
}
});
// Check for unnecessary preloads
this.hints.preload.forEach(hint => {
const isUsed = this.performance.getEntriesByName(hint.href).length > 0;
if (!isUsed) {
this.recommendations.push({
type: 'remove-preload',
resource: hint.href,
reason: 'Preloaded resource not used within 3 seconds',
impact: 'medium'
});
}
});
// Check for late-discovered resources
const lateResources = this.timingAnalysis.slowResources.filter(r => r.startTime > 2000);
lateResources.forEach(resource => {
if (!this.hints.prefetch.some(h => h.href === resource.url)) {
this.recommendations.push({
type: 'prefetch',
resource: resource.url,
reason: `Late discovery (started at ${resource.startTime}ms)`,
impact: 'medium'
});
}
});
}
generateOptimizationReport() {
console.log('=� Resource Hint Analysis Report\n');
// Current hints summary
console.log('=� Current Resource Hints:');
Object.entries(this.hints).forEach(([type, hints]) => {
if (hints.length > 0) {
console.log(`\n${type}: ${hints.length} hints`);
hints.slice(0, 3).forEach(hint => {
console.log(` - ${hint.href || hint.family}`);
});
if (hints.length > 3) {
console.log(` ... and ${hints.length - 3} more`);
}
}
});
// Resource timing summary
console.log('\n� Resource Loading Performance:');
Object.entries(this.timingAnalysis.byType).forEach(([type, stats]) => {
const avgDuration = Math.round(stats.totalDuration / stats.count);
console.log(`${type}: ${stats.count} resources, avg ${avgDuration}ms`);
});
// Critical resources
if (this.criticalResources.length > 0) {
console.log('\n=� Critical Resources:');
this.criticalResources.forEach(resource => {
const status = resource.preloaded ? ' Preloaded' : 'L Not preloaded';
console.log(` ${resource.type}: ${resource.url || resource.family} ${status}`);
});
}
// Third-party domains
if (this.thirdPartyDomains.size > 0) {
console.log('\n< Third-party Domains:');
this.thirdPartyDomains.forEach((stats, domain) => {
const status = stats.hasPreconnect ? '' : 'L';
console.log(` ${domain}: ${stats.count} resources ${status}`);
});
}
// Recommendations
if (this.recommendations.length > 0) {
console.log('\n=� Optimization Recommendations:');
// Group by impact
const highImpact = this.recommendations.filter(r => r.impact === 'high');
const mediumImpact = this.recommendations.filter(r => r.impact === 'medium');
if (highImpact.length > 0) {
console.log('\nHigh Impact:');
highImpact.forEach(rec => {
console.log(` =4 ${rec.type}: ${rec.resource || rec.domain}`);
console.log(` Reason: ${rec.reason}`);
});
}
if (mediumImpact.length > 0) {
console.log('\nMedium Impact:');
mediumImpact.forEach(rec => {
console.log(` =� ${rec.type}: ${rec.resource || rec.domain}`);
console.log(` Reason: ${rec.reason}`);
});
}
}
// Generate implementation code
this.generateImplementationCode();
}
generateImplementationCode() {
console.log('\n=� Implementation Code:\n');
const highImpactRecs = this.recommendations.filter(r => r.impact === 'high');
if (highImpactRecs.length > 0) {
console.log('<!-- Add to <head> section -->');
highImpactRecs.forEach(rec => {
if (rec.type === 'preconnect') {
console.log(`<link rel="preconnect" href="https://${rec.domain}" crossorigin>`);
} else if (rec.type === 'preload') {
const crossorigin = rec.resource.includes(window.location.hostname) ? '' : ' crossorigin';
console.log(`<link rel="preload" href="${rec.resource}" as="${rec.as}"${crossorigin}>`);
}
});
}
}
}
// Run the analyzer
const analyzer = new ResourceHintAnalyzer();
analyzer.analyzeResourceHints();
Understanding Resource Hints
1. DNS Prefetch
Resolves domain names before resources are requested:
<link rel="dns-prefetch" href="//example.com">
2. Preconnect
Establishes early connections (DNS + TCP + TLS):
<link rel="preconnect" href="https://example.com" crossorigin>
3. Prefetch
Downloads resources for likely future navigation:
<link rel="prefetch" href="/next-page.js" as="script">
4. Preload
Downloads critical resources for current navigation:
<link rel="preload" href="/font.woff2" as="font" type="font/woff2" crossorigin>
5. Prerender (Deprecated)
Pre-renders entire pages (use with caution):
<link rel="prerender" href="/next-page.html">
Advanced Resource Loading Optimizer
// Copy and paste this comprehensive resource optimizer
class ResourceLoadingOptimizer {
constructor() {
this.criticalCSS = new Set();
this.criticalFonts = new Set();
this.lazyImages = [];
this.asyncScripts = [];
this.config = {
lazyLoadOffset: 50,
preloadLimit: 5,
prefetchAfterLoad: true
};
}
optimizeResourceLoading() {
console.log('=' Optimizing Resource Loading...\n');
// Extract and inline critical CSS
this.extractCriticalCSS();
// Optimize font loading
this.optimizeFontLoading();
// Implement lazy loading for images
this.setupLazyLoading();
// Optimize script loading
this.optimizeScriptLoading();
// Setup prefetching strategy
this.setupPrefetchingStrategy();
// Monitor and adapt
this.setupPerformanceMonitoring();
}
extractCriticalCSS() {
const stylesheets = document.querySelectorAll('link[rel="stylesheet"]');
const criticalSelectors = new Set();
// Identify above-the-fold elements
const viewportHeight = window.innerHeight;
const elements = document.querySelectorAll('*');
elements.forEach(element => {
const rect = element.getBoundingClientRect();
if (rect.top < viewportHeight && rect.bottom > 0) {
// Element is in viewport
criticalSelectors.add(element.tagName.toLowerCase());
if (element.id) {
criticalSelectors.add(`#${element.id}`);
}
if (element.className) {
element.classList.forEach(cls => {
criticalSelectors.add(`.${cls}`);
});
}
}
});
console.log(`=� Found ${criticalSelectors.size} critical selectors`);
// Generate critical CSS recommendation
this.generateCriticalCSSRecommendation(criticalSelectors);
}
generateCriticalCSSRecommendation(selectors) {
console.log('\n=� Critical CSS Strategy:');
console.log('1. Extract styles for these selectors:',
Array.from(selectors).slice(0, 10).join(', '), '...');
console.log('2. Inline critical CSS in <head>');
console.log('3. Load full CSS asynchronously:');
console.log(`
<link rel="preload" href="style.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="style.css"></noscript>
`.trim());
}
optimizeFontLoading() {
// Detect font usage
const fontPromises = [];
if (document.fonts) {
document.fonts.forEach(font => {
if (font.status === 'loading' || font.status === 'loaded') {
this.criticalFonts.add({
family: font.family,
weight: font.weight,
style: font.style,
status: font.status
});
}
});
}
// Check computed styles for font usage
const elementsToCheck = document.querySelectorAll('h1, h2, h3, h4, h5, h6, p, a, button');
const usedFonts = new Set();
elementsToCheck.forEach(element => {
const style = window.getComputedStyle(element);
const fontFamily = style.fontFamily;
if (fontFamily && !fontFamily.includes('serif') && !fontFamily.includes('sans-serif')) {
usedFonts.add(fontFamily.replace(/['"]/g, ''));
}
});
console.log('\n=$ Font Optimization:');
console.log(`Detected ${usedFonts.size} custom fonts`);
// Generate font loading strategy
this.generateFontStrategy(usedFonts);
}
generateFontStrategy(fonts) {
console.log('\n=� Optimal Font Loading:');
console.log('```html');
fonts.forEach(font => {
console.log(`<link rel="preload" href="/fonts/${font}.woff2" as="font" type="font/woff2" crossorigin>`);
});
console.log('```');
console.log('\nCSS Font Loading API:');
console.log('```javascript');
console.log(`
const fontPromises = [
document.fonts.load('1rem ${Array.from(fonts)[0]}'),
// Add more fonts
];
Promise.all(fontPromises).then(() => {
document.body.classList.add('fonts-loaded');
});
`.trim());
console.log('```');
}
setupLazyLoading() {
const images = document.querySelectorAll('img[src]');
const iframes = document.querySelectorAll('iframe[src]');
// Identify images below the fold
const viewportHeight = window.innerHeight;
images.forEach(img => {
const rect = img.getBoundingClientRect();
if (rect.top > viewportHeight + this.config.lazyLoadOffset) {
this.lazyImages.push({
element: img,
src: img.src,
position: rect.top,
isLazy: img.loading === 'lazy'
});
}
});
console.log(`\n=� Lazy Loading Analysis:`);
console.log(`Total images: ${images.length}`);
console.log(`Below fold: ${this.lazyImages.length}`);
console.log(`Already lazy: ${this.lazyImages.filter(i => i.isLazy).length}`);
// Generate lazy loading implementation
this.generateLazyLoadingCode();
}
generateLazyLoadingCode() {
console.log('\n=� Lazy Loading Implementation:');
// Native lazy loading
console.log('\n1. Native Lazy Loading (Modern Browsers):');
console.log('```html');
console.log('<img src="image.jpg" loading="lazy" alt="Description">');
console.log('```');
// Intersection Observer approach
console.log('\n2. Intersection Observer (Better Control):');
console.log('```javascript');
console.log(`
const lazyImageObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.remove('lazy');
lazyImageObserver.unobserve(img);
}
});
}, {
rootMargin: '50px 0px',
threshold: 0.01
});
document.querySelectorAll('img.lazy').forEach(img => {
lazyImageObserver.observe(img);
});
`.trim());
console.log('```');
}
optimizeScriptLoading() {
const scripts = document.querySelectorAll('script[src]');
const scriptAnalysis = {
blocking: [],
async: [],
defer: [],
module: []
};
scripts.forEach(script => {
const scriptInfo = {
src: script.src,
size: 'Unknown',
position: script.parentElement.tagName
};
if (script.type === 'module') {
scriptAnalysis.module.push(scriptInfo);
} else if (script.async) {
scriptAnalysis.async.push(scriptInfo);
} else if (script.defer) {
scriptAnalysis.defer.push(scriptInfo);
} else {
scriptAnalysis.blocking.push(scriptInfo);
}
});
console.log('\n=� Script Loading Analysis:');
console.log(`Blocking: ${scriptAnalysis.blocking.length}`);
console.log(`Async: ${scriptAnalysis.async.length}`);
console.log(`Defer: ${scriptAnalysis.defer.length}`);
console.log(`Module: ${scriptAnalysis.module.length}`);
// Generate recommendations
if (scriptAnalysis.blocking.length > 0) {
console.log('\n� Blocking Scripts Found:');
scriptAnalysis.blocking.forEach(script => {
console.log(` - ${script.src}`);
console.log(` Consider adding async or defer attribute`);
});
}
}
setupPrefetchingStrategy() {
console.log('\n=. Prefetching Strategy:\n');
// Analyze navigation patterns
const links = document.querySelectorAll('a[href]');
const internalLinks = Array.from(links).filter(link => {
try {
const url = new URL(link.href);
return url.hostname === window.location.hostname;
} catch {
return false;
}
});
// Identify high-priority prefetch candidates
const navigationLinks = internalLinks.filter(link => {
// Main navigation links
return link.closest('nav') || link.closest('header');
});
console.log(`Found ${navigationLinks.length} navigation links for prefetching`);
// Generate prefetch implementation
this.generatePrefetchStrategy(navigationLinks);
}
generatePrefetchStrategy(links) {
console.log('\n=� Intelligent Prefetching:');
console.log('```javascript');
console.log(`
// Prefetch on hover with delay
const prefetchedUrls = new Set();
function prefetchUrl(url) {
if (!prefetchedUrls.has(url)) {
const link = document.createElement('link');
link.rel = 'prefetch';
link.href = url;
document.head.appendChild(link);
prefetchedUrls.add(url);
}
}
// Setup hover prefetching
document.querySelectorAll('a[href]').forEach(link => {
let timer;
link.addEventListener('mouseenter', () => {
timer = setTimeout(() => {
const url = link.href;
if (url.startsWith(window.location.origin)) {
prefetchUrl(url);
}
}, 200); // 200ms delay
});
link.addEventListener('mouseleave', () => {
clearTimeout(timer);
});
});
// Prefetch visible links in viewport
const linkObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const url = entry.target.href;
if (url.startsWith(window.location.origin)) {
prefetchUrl(url);
}
}
});
}, {
rootMargin: '0px 0px 50px 0px'
});
document.querySelectorAll('a[href]').forEach(link => {
linkObserver.observe(link);
});
`.trim());
console.log('```');
}
setupPerformanceMonitoring() {
console.log('\n=� Performance Monitoring Setup:');
console.log('```javascript');
console.log(`
// Monitor resource timing
const perfObserver = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.duration > 1000) {
console.warn('Slow resource:', entry.name, entry.duration + 'ms');
// Consider prefetching similar resources
if (entry.initiatorType === 'script' || entry.initiatorType === 'css') {
// Add to prefetch queue for next navigation
localStorage.setItem('prefetch-' + entry.name, 'true');
}
}
}
});
perfObserver.observe({ entryTypes: ['resource'] });
// Adaptive loading based on connection
if ('connection' in navigator) {
const connection = navigator.connection;
if (connection.effectiveType === '4g') {
// Aggressive prefetching
console.log('Fast connection detected - enabling aggressive prefetching');
} else if (connection.effectiveType === '3g' || connection.effectiveType === '2g') {
// Conservative loading
console.log('Slow connection detected - disabling prefetching');
}
// Monitor connection changes
connection.addEventListener('change', () => {
console.log('Connection changed to:', connection.effectiveType);
});
}
`.trim());
console.log('```');
}
}
// Run the optimizer
const optimizer = new ResourceLoadingOptimizer();
optimizer.optimizeResourceLoading();
Resource Priority Hints
Priority Hints API
Control fetch priority for resources:
// High priority for critical resources
<img src="hero.jpg" fetchpriority="high">
<link rel="stylesheet" href="critical.css" fetchpriority="high">
// Low priority for below-the-fold content
<img src="footer-logo.jpg" fetchpriority="low">
<script src="analytics.js" fetchpriority="low"></script>
// Auto priority (default)
<img src="content.jpg" fetchpriority="auto">
Common Resource Loading Patterns
1. Critical Path Optimization
// Identify and optimize critical rendering path
const criticalPathAnalyzer = () => {
const critical = {
css: [],
js: [],
fonts: []
};
// Find render-blocking CSS
document.querySelectorAll('link[rel="stylesheet"]').forEach(link => {
if (!link.media || link.media === 'all') {
critical.css.push(link.href);
}
});
// Find render-blocking JavaScript
document.querySelectorAll('script:not([async]):not([defer])').forEach(script => {
if (script.src) {
critical.js.push(script.src);
}
});
console.log('Critical Resources:', critical);
// Generate optimization strategy
return {
inline: critical.css.length > 3,
preload: critical.css.concat(critical.js),
defer: true
};
};
2. Progressive Enhancement Loading
// Load enhancements based on device capabilities
const progressiveLoader = () => {
const enhancements = [];
// Check for high-end device features
if (window.matchMedia('(min-width: 1200px)').matches) {
enhancements.push('/js/desktop-enhancements.js');
}
// Check for touch support
if ('ontouchstart' in window) {
enhancements.push('/js/touch-gestures.js');
}
// Check for WebGL support
if (window.WebGLRenderingContext) {
enhancements.push('/js/3d-graphics.js');
}
// Load enhancements
enhancements.forEach(src => {
const script = document.createElement('script');
script.src = src;
script.async = true;
document.body.appendChild(script);
});
};
3. Service Worker Prefetching
// Advanced prefetching with Service Worker
if ('serviceWorker' in navigator) {
// Register service worker
navigator.serviceWorker.register('/sw.js');
// Service worker code (sw.js)
const PREFETCH_CACHE = 'prefetch-v1';
const urlsToPrefetch = [
'/next-page.html',
'/styles/next-page.css',
'/scripts/next-page.js'
];
self.addEventListener('install', event => {
event.waitUntil(
caches.open(PREFETCH_CACHE)
.then(cache => cache.addAll(urlsToPrefetch))
);
});
}
Performance Budget Implementation
// Monitor and enforce performance budgets
class PerformanceBudgetMonitor {
constructor(budgets) {
this.budgets = budgets || {
js: 300 * 1024, // 300KB
css: 100 * 1024, // 100KB
images: 1000 * 1024, // 1MB
fonts: 200 * 1024, // 200KB
total: 2000 * 1024 // 2MB
};
this.violations = [];
}
checkBudgets() {
const resources = performance.getEntriesByType('resource');
const usage = {
js: 0,
css: 0,
images: 0,
fonts: 0,
total: 0
};
resources.forEach(resource => {
const size = resource.transferSize || 0;
const type = this.getResourceCategory(resource.name);
if (usage[type] !== undefined) {
usage[type] += size;
}
usage.total += size;
});
// Check for violations
Object.entries(this.budgets).forEach(([type, budget]) => {
if (usage[type] > budget) {
this.violations.push({
type,
usage: usage[type],
budget: budget,
overBy: ((usage[type] - budget) / 1024).toFixed(1) + 'KB'
});
}
});
this.generateBudgetReport(usage);
}
getResourceCategory(url) {
if (/\.js(\?|$)/.test(url)) return 'js';
if (/\.css(\?|$)/.test(url)) return 'css';
if (/\.(jpg|jpeg|png|gif|webp|svg)(\?|$)/.test(url)) return 'images';
if (/\.(woff|woff2|ttf|otf)(\?|$)/.test(url)) return 'fonts';
return 'other';
}
generateBudgetReport(usage) {
console.log('\n=� Performance Budget Report:\n');
Object.entries(usage).forEach(([type, bytes]) => {
const budget = this.budgets[type];
const percentage = ((bytes / budget) * 100).toFixed(1);
const status = bytes > budget ? 'L' : '';
console.log(`${type}: ${(bytes / 1024).toFixed(1)}KB / ${(budget / 1024).toFixed(0)}KB (${percentage}%) ${status}`);
});
if (this.violations.length > 0) {
console.log('\n� Budget Violations:');
this.violations.forEach(violation => {
console.log(` ${violation.type}: Over by ${violation.overBy}`);
});
}
}
}
// Check performance budgets
const budgetMonitor = new PerformanceBudgetMonitor();
budgetMonitor.checkBudgets();
Real-World Performance Wins
1. Amazon (2019)
Implemented aggressive prefetching, reducing page load time by 1.2 seconds and increasing conversions by 2%.
2. Netflix (2020)
Used predictive prefetching based on user behavior, reducing time-to-play by 50%.
3. Instagram (2021)
Implemented route-based code splitting with prefetching, improving interaction time by 23%.
Implementation Best Practices
Resource Hint Strategy
<!-- Optimal order in <head> -->
<!DOCTYPE html>
<html>
<head>
<!-- 1. Preconnect to critical third-party origins -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://cdn.example.com" crossorigin>
<!-- 2. DNS prefetch for other third-parties -->
<link rel="dns-prefetch" href="//www.google-analytics.com">
<!-- 3. Preload critical resources -->
<link rel="preload" href="/css/critical.css" as="style">
<link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin>
<!-- 4. Prefetch next-page resources -->
<link rel="prefetch" href="/next-page.js">
<!-- 5. Actual resource loading -->
<link rel="stylesheet" href="/css/critical.css">
</head>
Adaptive Loading Strategy
// Adapt resource loading based on user context
const adaptiveLoader = {
init() {
this.connectionType = this.getConnectionType();
this.deviceMemory = navigator.deviceMemory || 4;
this.saveData = navigator.connection?.saveData || false;
this.loadResources();
},
getConnectionType() {
if (!navigator.connection) return '4g';
return navigator.connection.effectiveType;
},
loadResources() {
if (this.saveData) {
console.log('Save-Data mode: Loading minimal resources');
return;
}
switch (this.connectionType) {
case '4g':
this.loadHighQuality();
this.enablePrefetching();
break;
case '3g':
this.loadMediumQuality();
this.enableSelectivePrefetching();
break;
case '2g':
case 'slow-2g':
this.loadLowQuality();
this.disablePrefetching();
break;
}
},
loadHighQuality() {
// Load high-res images, videos, etc.
document.querySelectorAll('[data-src-high]').forEach(el => {
el.src = el.dataset.srcHigh;
});
},
enablePrefetching() {
// Enable aggressive prefetching
document.querySelectorAll('a[href]').forEach(link => {
if (link.href.startsWith(window.location.origin)) {
const prefetchLink = document.createElement('link');
prefetchLink.rel = 'prefetch';
prefetchLink.href = link.href;
document.head.appendChild(prefetchLink);
}
});
}
};
Conclusion
Resource hints and preloading strategies are powerful tools for optimizing web performance. By understanding when and how to use each hint type, you can significantly improve loading times and user experience. Remember to measure the impact of your optimizations and adapt your strategy based on real user metrics and network conditions.
The key is finding the right balance between aggressive optimization and bandwidth consideration, always keeping your users' context and capabilities in mind.