Files
vibe_coding/.cursor/rules/022-performance.mdc
2026-03-05 21:27:11 +08:00

216 lines
5.4 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
description: >
性能优化规范与审计流程。当用户讨论性能优化、报告页面慢、加载卡、
包体积大、Swoole 调优、数据库查询优化、缓存策略或 Core Web Vitals 时激活。
alwaysApply: false
---
# Performance Standards & Audit
> 本文件同时包含性能**诊断流程**和**编码规范**。
> 完整审计工作流见Read `.cursor/skills/performance-audit/SKILL.md`
## 诊断流程(用户报告性能问题时先走这里)
### 1. 性能基线
收集当前数据(前端 `npm run build` + `du -sh dist/`,后端路由数量)。
### 2. 四维度审计
**前端渲染** — 不必要重渲染、大列表虚拟化、图片压缩、按需导入
**网络请求** — 瀑布式请求、Redis 缓存、Axios 拦截、Nginx 缓存
**打包体积** — 大依赖、dynamic import、tree-shaking、barrel exports
**数据库查询** — N+1、缺少索引、未限制字段、未分页
### 3. 输出优化建议
按影响力排序,每个建议包含:预期收益 + 实施难度 + 具体代码。
### 诊断验证
- [ ] 优化前后有可量化对比
- [ ] 未引入功能回归
- [ ] Core Web Vitals 达标
---
## 性能指标目标
| 指标 | 目标 | 说明 |
|------|------|------|
| FCP | < 1.5s | 首次内容绘制 |
| LCP | < 2.5s | 最大内容绘制 |
| INP | < 200ms | 交互到下一帧 |
| API P95 | < 200ms | 后端接口响应 |
| API P99 | < 500ms | 后端接口响应(长尾) |
| DB Query | < 50ms | 单条数据库查询 |
| Redis | < 5ms | 缓存操作 |
---
## 前端性能
### Vite 构建优化
```typescript
// vite.config.ts
export default defineConfig({
build: {
target: 'es2015',
minify: 'terser',
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true,
},
},
rollupOptions: {
output: {
manualChunks: {
'vue-vendor': ['vue', 'vue-router', 'pinia'],
// 仅管理端:'element-plus': ['element-plus'],
'echarts': ['echarts'],
},
},
},
chunkSizeWarningLimit: 2000,
},
})
```
### 加载优化
- 路由懒加载: `() => import('@/views/module/page/index.vue')`
- 管理端 Element Plus 按需导入: `unplugin-vue-components` + `unplugin-auto-import`(用户端不使用 Element Plus
- 大列表虚拟化: `@tanstack/vue-virtual`
- 组件懒加载: `defineAsyncComponent()`
- 页面缓存: `<keep-alive :include="cachedViews">` 配合 worktab Store
### 资源优化
- 图片: WebP 格式 + 压缩 + CDN
- 图标: 管理端 `@element-plus/icons-vue` 按需导入;用户端使用 `lucide-vue-next`
- 字体: `font-display: swap` 避免阻塞
- Gzip: Nginx 开启 gzip 压缩
### 前端缓存策略
| 数据 | 方式 | TTL |
|------|------|-----|
| 产品列表 | Pinia + localStorage | 5 分钟 |
| 字典数据 | Pinia + localStorage | 1 小时 |
| 用户配置 | Pinia persist | 持久 |
| 路由/菜单 | Pinia persist | 持久 |
| 接口响应 | 不缓存(后端 Redis | — |
---
## 后端性能
### Swoole 调优
```php
// config/autoload/server.php
'settings' => [
'worker_num' => swoole_cpu_num() * 2,
'task_worker_num' => 4,
'max_request' => 10000,
'max_coroutine' => 100000,
'enable_coroutine' => true,
'open_tcp_nodelay' => true,
'socket_buffer_size' => 3 * 1024 * 1024,
'buffer_output_size' => 3 * 1024 * 1024,
'package_max_length' => 5 * 1024 * 1024,
],
```
### 数据库查询优化
| 规则 | 正确做法 | 反模式 |
|------|---------|--------|
| 避免 N+1 | `with(['customer', 'subOrders'])` | 循环中查询关联 |
| 明确列名 | `select('id', 'order_no', 'status')` | `SELECT *` |
| 分页 | 游标分页 `WHERE id > ? LIMIT ?` | `OFFSET` 深分页 |
| 批量操作 | `insert([...])` / `chunk(500)` | 循环单条 SQL |
| 索引 | 复合索引遵循最左前缀 | 过多单列索引 |
| 大表 COUNT | 缓存计数 / 近似值 | `COUNT(*)` 全表 |
### 缓存优化
```php
// Cache-Aside 模式 + TTL 抖动
$data = $cache->withCache("order:{$id}", 300, fn() => Order::find($id));
// 缓存失效:写操作后立即清除
$cache->invalidate("order:{$id}");
$cache->invalidatePattern('orders:list:*');
```
### 协程并发
```php
// 并行无依赖 I/O 操作
$parallel = new Parallel(10);
$parallel->add(fn() => $this->orderService->getStatistics($id));
$parallel->add(fn() => $this->paymentService->getPayments($id));
[$stats, $payments] = $parallel->wait();
```
---
## 服务器性能
### Nginx 优化
```nginx
# Gzip 压缩
gzip on;
gzip_min_length 1k;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/typescript image/svg+xml;
# 静态资源长期缓存Vite 产物带 hash
location /assets/ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
# HTTP/2
listen 443 ssl http2;
```
### 连接池调优
```php
// MySQL 连接池
'pool' => [
'min_connections' => 5,
'max_connections' => 50,
'connect_timeout' => 10.0,
'wait_timeout' => 3.0,
'max_idle_time' => 60,
],
// Redis 连接池
'pool' => [
'min_connections' => 5,
'max_connections' => 30,
'connect_timeout' => 10.0,
'wait_timeout' => 3.0,
],
```
---
## 禁止事项
- 前端同步阻塞主线程的操作
- 未压缩的大图片 (> 200KB)
- 无限滚动不做虚拟化
- Swoole Worker 中执行阻塞 I/O (`file_get_contents`, `sleep`)
- 全表扫描无 WHERE 条件
- 事务内包含远程调用
- 单事务操作 > 1000 行