Methods to reduce the number of HTTP requests
The number of HTTP requests is one of the key factors affecting webpage performance. Excessive requests can lead to longer page load times and degrade the user experience. Techniques such as merging resources, using CSS sprites, and inlining critical CSS can effectively reduce the number of requests and improve page performance.
Merging CSS and JavaScript Files
Combining multiple CSS or JavaScript files into a single file is the most straightforward optimization method. Each file requires a separate HTTP request, and merging them can significantly reduce the number of requests.
// Before merging
<link rel="stylesheet" href="reset.css">
<link rel="stylesheet" href="base.css">
<link rel="stylesheet" href="components.css">
// After merging
<link rel="stylesheet" href="all.css">
Build tools like Webpack and Gulp can automate this process:
// webpack.config.js
module.exports = {
entry: {
app: ['./src/js/main.js', './src/js/utils.js']
},
output: {
filename: 'bundle.js'
}
}
Using CSS Sprites
CSS sprites combine multiple small icons into a single large image, displaying specific parts via CSS background positioning. This is particularly useful for navigation icons, social buttons, and similar elements.
.icon {
background-image: url('sprite.png');
background-repeat: no-repeat;
}
.icon-home {
width: 32px;
height: 32px;
background-position: 0 0;
}
.icon-user {
width: 32px;
height: 32px;
background-position: -32px 0;
}
Modern build tools can automatically generate sprites and their corresponding CSS:
// Using gulp.spritesmith
const gulp = require('gulp');
const spritesmith = require('gulp.spritesmith');
gulp.task('sprite', function() {
return gulp.src('images/icons/*.png')
.pipe(spritesmith({
imgName: 'sprite.png',
cssName: 'sprite.css'
}))
.pipe(gulp.dest('dist'));
});
Inlining Critical CSS
Inlining the critical CSS required for above-the-fold rendering directly into the HTML avoids additional requests that block rendering. Non-critical CSS can be loaded asynchronously.
<head>
<style>
/* Critical CSS */
body { font-family: sans-serif; }
.header { background: #333; }
.hero { padding: 2em; }
</style>
<!-- Load remaining CSS asynchronously -->
<link rel="preload" href="non-critical.css" as="style" onload="this.rel='stylesheet'">
</head>
Inlining Small Images with Base64 Encoding
For images smaller than 2KB, consider converting them to Base64 encoding and embedding them directly in CSS or HTML to eliminate additional HTTP requests.
.logo {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AkEEjUXKw0bJQAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAJklEQVQ4y2NgGAWjYBSMglEwCkbBKBgFowAAATMAZ/8Pq/kAAAAASUVORK5CYII=');
}
Using Icon Fonts Instead of Image Icons
Icon fonts treat icons as characters, allowing hundreds of icons to be included in a single font file with just one HTTP request.
<link rel="stylesheet" href="font-awesome.css">
<i class="fa fa-user"></i>
<i class="fa fa-home"></i>
<i class="fa fa-cog"></i>
Lazy Loading Non-Critical Resources
Use lazy loading techniques to defer the loading of images, iframes, and other resources that are not needed for the initial view, reducing the number of initial requests.
<img data-src="image.jpg" class="lazyload" alt="Example image">
<script>
document.addEventListener("DOMContentLoaded", function() {
const lazyImages = [].slice.call(document.querySelectorAll("img.lazyload"));
if ("IntersectionObserver" in window) {
let lazyImageObserver = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
let lazyImage = entry.target;
lazyImage.src = lazyImage.dataset.src;
lazyImageObserver.unobserve(lazyImage);
}
});
});
lazyImages.forEach(function(lazyImage) {
lazyImageObserver.observe(lazyImage);
});
}
});
</script>
Using HTTP/2 Server Push
HTTP/2's server push feature allows the server to proactively send resources, reducing round-trip requests.
# Nginx configuration example
http2_push /style.css;
http2_push /main.js;
Setting Appropriate Caching Policies
Configure proper cache headers to allow browsers to reuse downloaded resources and avoid repeated requests.
# Nginx caching configuration
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 365d;
add_header Cache-Control "public, no-transform";
}
Using WebP Format Images
WebP format typically results in smaller file sizes than PNG or JPEG, reducing the transfer time for image requests.
<picture>
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" alt="Example image">
</picture>
Reducing Third-Party Script Usage
Evaluate the necessity of third-party scripts and merge or remove unnecessary tracking codes, social plugins, etc.
<!-- Avoid this -->
<script src="analytics.js"></script>
<script src="social-share.js"></script>
<script src="chat-widget.js"></script>
<!-- Opt for on-demand loading -->
<button id="load-chat">Need help? Click to load chat</button>
<script>
document.getElementById('load-chat').addEventListener('click', function() {
const script = document.createElement('script');
script.src = 'chat-widget.js';
document.body.appendChild(script);
});
</script>
Using Service Workers to Cache Resources
Service workers can intercept network requests for more granular cache control.
// service-worker.js
const CACHE_NAME = 'v1';
const urlsToCache = [
'/',
'/styles/main.css',
'/scripts/main.js',
'/images/logo.png'
];
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => cache.addAll(urlsToCache))
);
});
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => response || fetch(event.request))
);
});
Optimizing API Requests
Merge API endpoints or use query languages like GraphQL to reduce the number of data requests.
// Traditional REST API
fetch('/api/user/123');
fetch('/api/user/123/posts');
// GraphQL query
fetch('/graphql', {
method: 'POST',
body: JSON.stringify({
query: `
{
user(id: 123) {
name
email
posts {
title
date
}
}
}
`
})
});
Using CDNs to Accelerate Resource Loading
Content Delivery Networks (CDNs) reduce the physical distance for resource requests, improving load times.
<!-- Load common libraries from a CDN -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css">
Preloading Critical Resources
Use <link rel="preload">
to load critical resources in advance and avoid request blocking.
<head>
<link rel="preload" href="critical.css" as="style">
<link rel="preload" href="main.js" as="script">
<link rel="preload" href="hero-image.jpg" as="image">
</head>
Reducing Redirects
Avoid unnecessary redirects, as each redirect generates an additional HTTP request.
# Avoid this
location /old-page {
return 301 /new-page;
}
# Link directly to the final destination
<a href="/new-page">Go to new page</a>
Using SVG Instead of Some Images
SVG is a vector format that typically results in smaller files and can be inlined in HTML.
<!-- Inline SVG example -->
<svg width="100" height="100" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="40" fill="#f00"/>
</svg>
Optimizing Web Font Usage
Use fonts judiciously to avoid excessive font variants that lead to additional requests.
/* Avoid this */
@font-face {
font-family: 'MyFont';
src: url('myfont-regular.woff2') format('woff2');
font-weight: 400;
}
@font-face {
font-family: 'MyFont';
src: url('myfont-bold.woff2') format('woff2');
font-weight: 700;
}
/* Use unicode-range to split font files */
@font-face {
font-family: 'MyFont';
src: url('myfont-latin.woff2') format('woff2');
unicode-range: U+0000-00FF;
}
Reducing Cookie Size
Large cookies are automatically sent with every request, increasing the request payload.
// Set cookies with specific paths to avoid global cookies
document.cookie = "preferences=dark; path=/settings; max-age=31536000";
Using Modular JavaScript
Modern JavaScript module systems allow better control over code splitting and on-demand loading.
// Dynamic module import
button.addEventListener('click', async () => {
const module = await import('./module.js');
module.doSomething();
});
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:性能监控与持续优化的必要性