Resource preloading (preload/prefetch) technology
Overview of Resource Preloading (preload/prefetch) Technology
Resource preloading is a strategy for fetching critical resources in advance, utilizing the browser's idle time to load resources that may be needed later, thereby reducing user wait times. preload and prefetch are two core implementation methods, with the former targeting critical resources for the current page and the latter targeting resources that may be needed for future navigation.
How preload Works and Its Use Cases
preload uses the <link rel="preload">
directive to force the browser to immediately fetch specified resources, typically with higher priority than regular resource loading. It is suitable for resources that are definitively required in the current rendering path, especially those dynamically requested by CSS or JavaScript but not discovered early.
Typical use cases include:
- Critical font files for the first screen
- Large background images for the first screen
- Asynchronous scripts on the critical path
- Video poster images
<!-- Preload critical CSS -->
<link rel="preload" href="critical.css" as="style">
<!-- Preload web fonts -->
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
<!-- Preload hero section image -->
<link rel="preload" href="hero-image.webp" as="image" media="(min-width: 800px)">
Mechanism and Application Scenarios of prefetch
prefetch (<link rel="prefetch">
) instructs the browser to fetch resources that may be needed in the future during idle time, with lower priority. It is suitable for predicting resources required for the user's next action, such as paginated content, popup resources, or core resources for the next page.
Common application scenarios:
- Product detail page images on e-commerce sites
- Next route components in single-page applications
- Preloading dropdown menu resources on user hover
<!-- Prefetch next page resources -->
<link rel="prefetch" href="page-2.html" as="document">
<!-- Prefetch potentially needed scripts -->
<link rel="prefetch" href="modal.js" as="script">
<!-- DNS prefetch to accelerate cross-origin requests -->
<link rel="dns-prefetch" href="//cdn.example.com">
Technical Implementation Details and Considerations
Resource Priority Control
Browsers assign default priorities based on resource types:
- CSS/fonts: Highest
- Scripts: High/Medium
- Images: Low
Explicitly declaring the resource type via the as
attribute ensures correct priority:
<link rel="preload" href="slider.js" as="script">
Cross-Origin Resource Handling
Loading cross-origin resources requires the crossorigin
attribute, especially for fonts and scripts:
<link rel="preload" href="https://other-domain.com/font.woff2"
as="font" crossorigin="anonymous">
Responsive Preloading
Use the media
attribute for conditional preloading:
<link rel="preload" href="large-bg.jpg" as="image"
media="(min-width: 1024px)">
<link rel="preload" href="small-bg.jpg" as="image"
media="(max-width: 1023px)">
Real-World Performance Optimization Cases
Case 1: Solving Font Flash Issues
Before optimization:
@font-face {
font-family: 'CustomFont';
src: url('custom.woff2') format('woff2');
}
Optimized solution:
<head>
<link rel="preload" href="custom.woff2" as="font" type="font/woff2" crossorigin>
<style>
@font-face {
font-family: 'CustomFont';
src: url('custom.woff2') format('woff2');
font-display: swap;
}
</style>
</head>
Case 2: Route Preloading in Single-Page Applications
React application example:
import { useEffect } from 'react';
import { useRouter } from 'next/router';
const ProductPage = () => {
const router = useRouter();
useEffect(() => {
// Preload checkout page resources on hover
const link = document.createElement('link');
link.rel = 'prefetch';
link.href = '/checkout';
document.head.appendChild(link);
}, []);
return <div>Product Content</div>;
}
Browser Compatibility and Fallback Strategies
Mainstream browser support:
- preload: Chrome 50+, Firefox 56+, Edge 17+
- prefetch: Widely supported, including IE11
Feature detection:
const isPreloadSupported = () => {
const link = document.createElement('link');
return link.relList && link.relList.supports && link.relList.supports('preload');
};
if (isPreloadSupported()) {
// Use preload
} else {
// Fallback: XHR preloading or lazy loading
}
Monitoring and Performance Evaluation
Use Resource Timing API to measure preloading effectiveness:
const measurePreload = (resourceUrl) => {
const entries = performance.getEntriesByName(resourceUrl);
if (entries.length > 0) {
const entry = entries[0];
console.log(`Load duration: ${entry.duration.toFixed(2)}ms`);
console.log(`Start time: ${entry.startTime.toFixed(2)}ms`);
console.log(`Cache hit: ${entry.transferSize === 0}`);
}
};
// Check preloaded font file
measurePreload('https://example.com/font.woff2');
Advanced Application Patterns
Dynamic Preloading Based on User Behavior
document.addEventListener('mouseover', (e) => {
if (e.target.matches('.product-thumbnail')) {
const productId = e.target.dataset.id;
const link = document.createElement('link');
link.rel = 'prefetch';
link.href = `/products/${productId}/details.json`;
document.head.appendChild(link);
}
});
Preloading Strategies in Service Workers
// sw.js
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open('preload-cache').then((cache) => {
return cache.addAll([
'/styles/main.css',
'/scripts/app.js',
'/images/logo.svg'
]);
})
);
});
Common Pitfalls and Best Practices
Mistakes to Avoid
- Over-preloading non-critical resources
<!-- Bad example: Preloading all possible icons -->
<link rel="preload" href="icon-1.png" as="image">
<link rel="preload" href="icon-2.png" as="image">
<!-- ... -->
- Ignoring caching strategies
# Ensure preloaded resources have proper cache headers
Cache-Control: public, max-age=31536000, immutable
Recommended Practices
- Critical request chain analysis
// Use Chrome DevTools Performance panel
// Identify unoptimized resources on the critical path
- Progressive preloading strategy
<!-- First-screen core resources -->
<link rel="preload" href="main.css" as="style">
<link rel="preload" href="main.js" as="script">
<!-- Secondary resources after first-screen load -->
<script>
window.addEventListener('load', () => {
const link = document.createElement('link');
link.rel = 'prefetch';
link.href = 'secondary.js';
document.head.appendChild(link);
});
</script>
Integration with Other Optimization Techniques
Synergy with HTTP/2 Server Push
# nginx configuration example
http2_push_preload on;
location = /styles.css {
http2_push /fonts/Inter.woff2;
}
Complementary Implementation with Lazy Loading
<!-- First-screen image preloading -->
<link rel="preload" href="hero.jpg" as="image">
<!-- Non-first-screen image lazy loading -->
<img data-src="product.jpg" loading="lazy" class="lazyload">
<script>
document.addEventListener('DOMContentLoaded', () => {
if ('IntersectionObserver' in window) {
const lazyImages = [].slice.call(document.querySelectorAll('img.lazyload'));
const imageObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
imageObserver.unobserve(img);
}
});
});
lazyImages.forEach((img) => imageObserver.observe(img));
}
});
</script>
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn