前端性能优化与网络请求#
#概述
前端性能优化是提升用户体验的关键,网络请求优化是其中最重要的一环。通过减少请求数量、压缩资源、合理缓存等手段,可以显著提升页面加载速度。
#网络请求分析
#1. 关键性能指标
- FP(First Paint):首次绘制时间
- FCP(First Contentful Paint):首次内容绘制
- LCP(Largest Contentful Paint):最大内容绘制
- FID(First Input Delay):首次输入延迟
- CLS(Cumulative Layout Shift):累计布局偏移
#2. 网络瀑布图分析
DNS 查询 |====|
TCP 连接 |====|
TLS 握手 |====|
请求发送 |==|
等待响应 |=======|
接收数据 |============|#3. Chrome DevTools 网络面板
- 请求列表:查看所有网络请求
- 时间线:分析请求各阶段耗时
- 瀑布图:可视化请求时序
- 请求详情:查看请求头、响应头、内容
#减少请求数量
#1. 合并资源文件
// Webpack 配置示例
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
},
commons: {
name: 'commons',
minChunks: 2,
chunks: 'initial',
minSize: 0
}
}
}
}
};#2. 使用 CSS Sprites
.icon {
background-image: url('sprites.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;
}#3. 内联关键 CSS
<!DOCTYPE html>
<html>
<head>
<style>
/* 关键CSS内联 */
.header { display: flex; }
.logo { width: 100px; }
/* 非关键CSS异步加载 */
</style>
<link rel="preload" href="styles.css" as="style" onload="this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="styles.css"></noscript>
</head>
</html>#4. 使用 Data URLs
<!-- 小图片转为 Base64 -->
<img src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCI+PC9zdmc+">
<!-- CSS 中内联小图片 -->
.icon {
background-image: url('data:image/svg+xml;utf8,<svg>...</svg>');
}#压缩与优化
#1. 资源压缩
# Nginx Gzip 配置
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript
application/javascript application/xml+rss
application/json image/svg+xml;
gzip_comp_level 6;#2. 图片优化
// 使用现代图片格式
// WebP:比 JPEG 小 25-35%,支持透明度
// AVIF:比 WebP 更优,但兼容性较差
// 响应式图片
<picture>
<source srcset="image.avif" type="image/avif">
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" alt="描述">
</picture>
// 懒加载
<img src="placeholder.jpg" data-src="real-image.jpg" loading="lazy">#3. 代码压缩
# 使用工具压缩
# JavaScript: UglifyJS, Terser
# CSS: CSSNano
# HTML: HTMLMinifier
# Webpack 配置
const TerserPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin(),
new CssMinimizerPlugin(),
],
},
};#缓存策略
#1. 浏览器缓存
# 强缓存
Cache-Control: max-age=31536000, public
Expires: Wed, 13 Mar 2027 14:30:00 GMT
# 协商缓存
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
Last-Modified: Wed, 12 Mar 2026 14:30:00 GMT#2. Service Worker 缓存
// 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 => {
if (response) {
return response; // 返回缓存
}
return fetch(event.request); // 网络请求
})
);
});#3. CDN 缓存
<!-- 使用 CDN 加速 -->
<script src="https://cdn.example.com/jquery@3.6.0.min.js"></script>
<link rel="stylesheet" href="https://cdn.example.com/bootstrap@5.1.3/css/bootstrap.min.css">
<!-- 子资源完整性校验 -->
<script
src="https://cdn.example.com/jquery@3.6.0.min.js"
integrity="sha384-...">
</script>#请求优化
#1. 预加载与预连接
<!-- DNS 预解析 -->
<link rel="dns-prefetch" href="https://api.example.com">
<!-- 预连接 -->
<link rel="preconnect" href="https://api.example.com" crossorigin>
<!-- 预加载关键资源 -->
<link rel="preload" href="critical.css" as="style">
<link rel="preload" href="critical.js" as="script">
<!-- 预获取可能需要的资源 -->
<link rel="prefetch" href="next-page.html" as="document">#2. 请求优先级
// 使用 fetch API 设置优先级
fetch('/api/data', {
priority: 'high' // high, low, auto
});
// 图片懒加载
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
document.querySelectorAll('img[data-src]').forEach(img => {
observer.observe(img);
});#3. 请求合并与批处理
// 批量请求示例
class BatchRequest {
constructor(delay = 100) {
this.requests = [];
this.timer = null;
this.delay = delay;
}
add(request) {
this.requests.push(request);
this.schedule();
}
schedule() {
if (this.timer) clearTimeout(this.timer);
this.timer = setTimeout(() => this.execute(), this.delay);
}
async execute() {
if (this.requests.length === 0) return;
const batch = this.requests.splice(0, 10); // 每次最多10个
const results = await Promise.all(
batch.map(req => fetch(req.url, req.options))
);
batch.forEach((req, index) => {
req.resolve(results[index]);
});
}
}
// 使用示例
const batch = new BatchRequest();
batch.add({
url: '/api/user/1',
resolve: response => console.log('User 1:', response)
});#监控与测量
#1. Performance API
// 测量页面性能
const perfData = window.performance.timing;
const loadTime = perfData.loadEventEnd - perfData.navigationStart;
console.log(`页面加载时间: ${loadTime}ms`);
// 测量资源加载
const resources = performance.getEntriesByType('resource');
resources.forEach(resource => {
console.log(`${resource.name} 加载时间: ${resource.duration}ms`);
});
// 用户自定义测量
performance.mark('task-start');
// 执行任务...
performance.mark('task-end');
performance.measure('task-duration', 'task-start', 'task-end');#2. 真实用户监控 (RUM)
// 发送性能数据到分析服务
function sendPerformanceData() {
const data = {
url: window.location.href,
fcp: performance.getEntriesByName('first-contentful-paint')[0]?.startTime,
lcp: performance.getEntriesByName('largest-contentful-paint')[0]?.startTime,
fid: performance.getEntriesByName('first-input')[0]?.processingStart,
cls: performance.getEntriesByName('layout-shift')
.reduce((sum, entry) => sum + entry.value, 0),
timestamp: Date.now()
};
// 使用 navigator.sendBeacon 异步发送
navigator.sendBeacon('/api/performance', JSON.stringify(data));
}
// 页面卸载时发送数据
window.addEventListener('beforeunload', sendPerformanceData);#3. 性能预算
{
"performanceBudget": {
"metrics": {
"fcp": 1000,
"lcp": 2500,
"fid": 100,
"cls": 0.1
},
"resourceSizes": {
"total": 500000,
"javascript": 200000,
"css": 50000,
"images": 200000
},
"requests": {
"total": 15,
"thirdParty": 5
}
}
}#工具与自动化
#1. 构建工具
// Vite 配置示例
export default {
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
utils: ['lodash', 'dayjs']
}
}
},
// 代码分割
chunkSizeWarningLimit: 1000,
// 资源内联阈值
assetsInlineLimit: 4096
}
};#2. 自动化测试
// Lighthouse 自动化测试
const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');
async function runAudit(url) {
const chrome = await chromeLauncher.launch();
const options = {
logLevel: 'info',
output: 'json',
onlyCategories: ['performance'],
port: chrome.port
};
const runnerResult = await lighthouse(url, options);
const report = runnerResult.report;
await chrome.kill();
return JSON.parse(report);
}
// WebPageTest 集成
// 使用 webpagetest-api 包进行自动化测试#3. 持续监控
# GitHub Actions 工作流
name: Performance Monitoring
on:
schedule:
- cron: '0 0 * * *' # 每天运行
push:
branches: [main]
jobs:
performance:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run Lighthouse
uses: foo-software/lighthouse-check-action@master
with:
urls: 'https://example.com'
outputDirectory: './reports'
- name: Upload Report
uses: actions/upload-artifact@v2
with:
name: lighthouse-report
path: ./reports#最佳实践总结
#1. 核心原则
- 测量优先:没有测量就没有优化
- 渐进增强:确保基础功能快速可用
- 按需加载:只加载当前需要的资源
- 缓存为王:合理利用各级缓存
#2. 优化 checklist
- 压缩所有文本资源(HTML、CSS、JS)
- 优化图片格式和尺寸
- 合并和减少 HTTP 请求
- 使用 CDN 分发静态资源
- 实现合理的缓存策略
- 启用 HTTP/2 或 HTTP/3
- 使用 Service Worker 缓存
- 监控真实用户性能数据
#3. 持续改进
- 定期进行性能审计
- 设置性能预算并监控
- A/B 测试优化效果
- 关注 Core Web Vitals 指标
#总结
前端性能优化是一个系统工程,需要从网络请求、资源加载、代码执行等多个维度进行优化。通过合理的缓存策略、资源压缩、请求优化和持续监控,可以显著提升用户体验和业务指标。
创建时间:2026-03-12 分类:前端网络 标签:性能优化, 网络请求, 前端开发, 性能监控