适用人群:前端/后端开发者
学习时长:约1天
重要程度:★★★★☆(用户体验核心)
一、性能指标
| 指标 | 说明 | 目标 |
|---|
| FCP(首次内容绘制) | 页面首次显示内容 | < 1.8s |
| LCP(最大内容绘制) | 最大内容元素显示 | < 2.5s |
| FID(首次输入延迟) | 用户首次交互响应 | < 100ms |
| CLS(累积布局偏移) | 页面布局稳定性 | < 0.1 |
| TTFB(首字节时间) | 服务器响应时间 | < 200ms |
二、前端优化
2.1 资源优化
<!-- 1. 图片优化 -->
<!-- 使用WebP格式 -->
<img src="image.webp" alt="..." loading="lazy">
<!-- 响应式图片 -->
<img
srcset="small.jpg 480w, medium.jpg 800w, large.jpg 1200w"
sizes="(max-width: 480px) 480px, (max-width: 800px) 800px, 1200px"
src="medium.jpg"
alt="..."
>
<!-- 2. CSS/JS压缩 -->
<!-- Vite自动压缩 -->
npm run build
<!-- 3. 代码分割 -->
<!-- Vue Router懒加载 -->
const routes = [
{ path: '/user', component: () => import('./views/User.vue') }
]
<!-- 4. 预加载关键资源 -->
<link rel="preload" href="critical.css" as="style">
<link rel="preload" href="main.js" as="script">
2.2 缓存策略
# Nginx缓存配置
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
# HTML不缓存
location ~* \.html$ {
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
// Service Worker缓存
// sw.js
const CACHE_NAME = 'v1'
const urlsToCache = ['/', '/styles.css', '/script.js']
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))
)
})
2.3 渲染优化
// 1. 虚拟列表(大数据量)
// 使用vue-virtual-scroller或react-window
// 2. 防抖和节流
// 搜索防抖
function debounce(fn, delay) {
let timer
return function (...args) {
clearTimeout(timer)
timer = setTimeout(() => fn.apply(this, args), delay)
}
}
// 滚动节流
function throttle(fn, delay) {
let last = 0
return function (...args) {
const now = Date.now()
if (now - last >= delay) {
last = now
fn.apply(this, args)
}
}
}
// 3. 图片懒加载
// 使用loading="lazy"或Intersection Observer
三、后端优化
3.1 数据库优化
-- 1. 添加索引
CREATE INDEX idx_status ON posts(status);
CREATE INDEX idx_author_status ON posts(author_id, status);
-- 2. 使用EXPLAIN分析
EXPLAIN SELECT * FROM posts WHERE status = 'published' ORDER BY created_at DESC LIMIT 10;
-- 3. 避免SELECT *
SELECT id, title, slug FROM posts WHERE status = 'published';
-- 4. 分页优化
-- 慢:大偏移量
SELECT * FROM posts LIMIT 10 OFFSET 10000;
-- 快:游标分页
SELECT * FROM posts WHERE id > 10000 LIMIT 10;
-- 5. 批量操作
INSERT INTO users (username, email) VALUES
('user1', 'user1@example.com'),
('user2', 'user2@example.com');
3.2 缓存策略
# Redis缓存模式
# 1. Cache-Aside(旁路缓存)
def get_user(user_id):
# 先查缓存
cache_key = f"user:{user_id}"
user = redis.get(cache_key)
if user:
return json.loads(user)
# 缓存未命中,查数据库
user = User.query.get(user_id)
if user:
# 写入缓存
redis.setex(cache_key, 3600, json.dumps(user.to_dict()))
return user
# 2. Write-Through(写穿透)
def update_user(user_id, data):
# 更新数据库
user = User.query.get(user_id)
user.update(data)
db.session.commit()
# 更新缓存
redis.setex(f"user:{user_id}", 3600, json.dumps(user.to_dict()))
# 3. 缓存失效策略
# 设置过期时间
redis.setex(key, 3600, value) # 1小时过期
# 主动删除
def update_user(user_id, data):
User.query.get(user_id).update(data)
redis.delete(f"user:{user_id}") # 删除缓存
3.3 接口优化
# 1. 响应压缩
from flask import Flask
from flask_compress import Compress
app = Flask(__name__)
Compress(app)
# 2. 分页返回
@app.route('/api/users')
def get_users():
page = request.args.get('page', 1, type=int)
size = request.args.get('size', 10, type=int)
# 限制每页数量
size = min(size, 100)
pagination = User.query.paginate(page=page, per_page=size)
return jsonify({
'items': [u.to_dict() for u in pagination.items],
'total': pagination.total,
'page': page,
'size': size
})
# 3. 字段过滤
@app.route('/api/users')
def get_users():
fields = request.args.get('fields', '').split(',')
users = User.query.all()
if fields:
return jsonify([{k: getattr(u, k) for k in fields if hasattr(u, k)} for u in users])
return jsonify([u.to_dict() for u in users])
四、Nginx优化
# 1. Gzip压缩
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
# 2. 连接优化
keepalive_timeout 65;
client_max_body_size 10m;
# 3. 静态文件缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
expires 30d;
add_header Cache-Control "public, immutable";
access_log off;
}
# 4. 代理缓冲
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
五、监控与分析
// 性能监控
// 1. Web Vitals
import { getCLS, getFID, getLCP } from 'web-vitals'
getCLS(console.log)
getFID(console.log)
getLCP(console.log)
// 2. 性能计时
performance.mark('start')
// ... 执行操作
performance.mark('end')
performance.measure('操作耗时', 'start', 'end')
const measures = performance.getEntriesByName('操作耗时')
console.log(measures[0].duration)
六、优化检查清单
前端
✅ 图片压缩和WebP格式
✅ CSS/JS压缩和代码分割
✅ 路由懒加载
✅ 图片懒加载
✅ 虚拟列表(大数据量)
✅ 防抖和节流
✅ 浏览器缓存
后端
✅ 数据库索引优化
✅ Redis缓存
✅ 响应压缩
✅ 分页查询
✅ 批量操作
✅ 异步处理耗时任务
Nginx
✅ Gzip压缩
✅ 静态文件缓存
✅ 代理缓冲
✅ 连接优化
数据库
✅ 索引设计
✅ 查询优化
✅ 读写分离
✅ 分库分表(大数据量)
学习建议
- 先测量再优化,用Lighthouse等工具分析
- 优先优化瓶颈,不要盲目优化
- 缓存是最有效的优化,合理使用Redis
- 数据库优化是核心,索引和查询优化
- 持续监控,建立性能监控体系