性能优化Skill performance-optimization

该技能专注于优化软件应用程序性能,通过代码分割、懒加载、缓存策略、渲染优化等方法提高前端和后端的响应速度、减少资源使用,并改善用户体验。适用于前端开发、后端开发、DevOps等领域,帮助提升页面加载时间、数据库查询效率、系统监控等。关键词:性能优化、前端优化、后端优化、代码分割、懒加载、缓存策略、数据库优化、监控、Web Vitals、DevOps。

DevOps 0 次安装 0 次浏览 更新于 3/18/2026

name: 性能优化 description: 通过代码分割、懒加载、缓存策略、包大小减少、渲染优化和分析来优化应用程序性能。用于提高页面加载时间、减少包大小、优化React渲染、实现代码分割、配置缓存策略、懒加载组件和路由、优化图像和资产、分析性能瓶颈、为大列表实现虚拟滚动,或改善核心Web Vitals和Lighthouse分数。

性能优化 - 让软件更快

何时使用此技能

  • 改善缓慢的页面加载时间和性能
  • 减少JavaScript包大小
  • 使用记忆化优化React组件渲染
  • 实现代码分割和懒加载
  • 配置浏览器和服务器端缓存
  • 使用next/image或类似工具优化图像
  • 使用DevTools分析性能瓶颈
  • 为大数据集实现虚拟滚动
  • 优化数据库查询和N+1问题
  • 改善核心Web Vitals(LCP、FID、CLS)
  • 实现渐进式图像加载
  • 减少交互时间(TTI)

何时使用此技能

  • 应用程序缓慢,用户抱怨延迟,或者需要提高响应时间、吞吐量或资源使用率。
  • 当处理相关任务或功能时
  • 在需要此专业知识的开发过程中

使用时机:应用程序缓慢,用户抱怨延迟,或者需要提高响应时间、吞吐量或资源使用率。

核心原则

  1. 先测量,后优化 - 永远不要猜测瓶颈
  2. 80/20规则 - 20%的代码导致80%的性能问题
  3. 过早优化是罪恶的 - 先让它工作,再让它正确,然后让它快速
  4. 分析,不要假设 - 惊喜等待着;你的直觉通常是错的
  5. 设置性能预算 - 在优化前定义可接受的限制

性能测量

建立基线

# Web Vitals(前端)
- FCP(首次内容绘制):< 1.8秒
- LCP(最大内容绘制):< 2.5秒
- FID(首次输入延迟):< 100毫秒
- CLS(累积布局偏移):< 0.1
- TTFB(首次字节时间):< 600毫秒

# 后端
- API响应时间:< 200毫秒(p95)
- 数据库查询时间:< 50毫秒(p95)
- 吞吐量:每秒请求数
- 错误率:< 0.1%

分析工具

# 前端
- Chrome DevTools性能选项卡
- Lighthouse CI
- WebPageTest
- webpack-bundle-analyzer

# 后端
- Node.js: node --prof, clinic.js
- Python: cProfile, py-spy
- 数据库: EXPLAIN ANALYZE, 慢查询日志
- APM: New Relic, Datadog, Sentry Performance

# 系统
- top, htop(CPU/内存)
- iostat(磁盘I/O)
- netstat, iftop(网络)

前端性能

1. 减少JavaScript包大小

// 之前 - 导入整个库
import _ from 'lodash'; // 70KB
import moment from 'moment'; // 230KB

// 之后 - 支持树摇动的导入
import debounce from 'lodash/debounce'; // 2KB
import { format } from 'date-fns'; // 13KB

// 代码分割 - 按需加载
const HeavyComponent = lazy(() => import('./HeavyComponent'));

// 动态导入
button.onclick = async () => {
  const module = await import('./analytics');
  module.trackEvent('button_click');
};

2. 优化图像

<!-- 之前 - 未优化的 -->
<img src="photo.jpg" alt="产品" />

<!-- 之后 - 响应式和现代格式 -->
<picture>
  <source srcset="photo.avif" type="image/avif">
  <source srcset="photo.webp" type="image/webp">
  <img 
    src="photo.jpg" 
    alt="产品"
    loading="lazy"
    width="800" 
    height="600"
    srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1200.jpg 1200w"
    sizes="(max-width: 600px) 400px, (max-width: 1200px) 800px, 1200px"
  />
</picture>

<!-- 或使用Next.js Image组件 -->
<Image
  src="/photo.jpg"
  alt="产品"
  width={800}
  height={600}
  placeholder="blur"
  quality={85}
/>

3. 懒加载和代码分割

// React - 懒加载路由
const Dashboard = lazy(() => import('./Dashboard'));
const Settings = lazy(() => import('./Settings'));

function App() {
  return (
    <Suspense fallback={<Loading />}>
      <Routes>
        <Route path="/dashboard" element={<Dashboard />} />
        <Route path="/settings" element={<Settings />} />
      </Routes>
    </Suspense>
  );
}

// Next.js - 自动代码分割
// 只需使用动态导入
import dynamic from 'next/dynamic';

const DynamicChart = dynamic(() => import('./Chart'), {
  loading: () => <Spinner />,
  ssr: false // 不在服务器上渲染
});

4. 记忆化和缓存

// React - 防止不必要的重新渲染
const ExpensiveComponent = memo(({ data }) => {
  return <div>{/* 复杂渲染 */}</div>;
});

// 记忆化昂贵计算
function ProductList({ products, filters }) {
  const filteredProducts = useMemo(() => {
    return products.filter(p => matchesFilters(p, filters));
  }, [products, filters]); // 仅当依赖项更改时重新计算
  
  return <div>{filteredProducts.map(renderProduct)}</div>;
}

// 记忆化回调以防止子组件重新渲染
function Parent() {
  const handleClick = useCallback(() => {
    console.log('点击');
  }, []); // 稳定的函数引用
  
  return <Child onClick={handleClick} />;
}

5. 长列表的虚拟化

// 之前 - 渲染10,000项(慢!)
function ProductList({ products }) {
  return (
    <div>
      {products.map(product => (
        <ProductCard key={product.id} product={product} />
      ))}
    </div>
  );
}

// 之后 - 仅渲染可见项
import { FixedSizeList } from 'react-window';

function ProductList({ products }) {
  return (
    <FixedSizeList
      height={600}
      itemCount={products.length}
      itemSize={100}
      width="100%"
    >
      {({ index, style }) => (
        <div style={style}>
          <ProductCard product={products[index]} />
        </div>
      )}
    </FixedSizeList>
  );
}

后端性能

1. 数据库查询优化

-- 之前 - N+1查询问题
-- 先获取用户,然后为每个用户单独查询帖子
SELECT * FROM users;
-- 然后为每个用户:
SELECT * FROM posts WHERE user_id = ?;

-- 之后 - 连接或急切加载
SELECT 
  users.*, 
  posts.id as post_id,
  posts.title as post_title
FROM users
LEFT JOIN posts ON posts.user_id = users.id;

-- 为频繁查询的列添加索引
CREATE INDEX idx_posts_user_id ON posts(user_id);
CREATE INDEX idx_posts_created_at ON posts(created_at);

-- 为常见查询模式添加复合索引
CREATE INDEX idx_posts_user_created 
ON posts(user_id, created_at DESC);

2. 缓存策略

// 内存缓存用于昂贵计算
const cache = new Map();

async function getExpensiveData(key) {
  if (cache.has(key)) {
    return cache.get(key);
  }
  
  const data = await expensiveComputation(key);
  cache.set(key, data);
  
  // 5分钟后过期
  setTimeout(() => cache.delete(key), 5 * 60 * 1000);
  
  return data;
}

// Redis缓存用于分布式系统
import Redis from 'ioredis';
const redis = new Redis();

async function getCachedUserProfile(userId) {
  const cacheKey = `user:${userId}:profile`;
  
  // 先尝试缓存
  const cached = await redis.get(cacheKey);
  if (cached) {
    return JSON.parse(cached);
  }
  
  // 缓存未命中 - 从数据库获取
  const profile = await db.users.findById(userId);
  
  // 存入缓存(1小时后过期)
  await redis.setex(cacheKey, 3600, JSON.stringify(profile));
  
  return profile;
}

// HTTP缓存头
app.get('/api/products', (req, res) => {
  res.set({
    'Cache-Control': 'public, max-age=300', // 5分钟
    'ETag': generateETag(data)
  });
  res.json(products);
});

3. 数据库连接池

// 之前 - 每个查询新连接(慢!)
async function getUser(id) {
  const connection = await mysql.createConnection(config);
  const [rows] = await connection.execute('SELECT * FROM users WHERE id = ?', [id]);
  await connection.end();
  return rows[0];
}

// 之后 - 连接池
import mysql from 'mysql2/promise';

const pool = mysql.createPool({
  host: 'localhost',
  user: 'root',
  database: 'mydb',
  waitForConnections: true,
  connectionLimit: 10,
  queueLimit: 0
});

async function getUser(id) {
  const [rows] = await pool.execute('SELECT * FROM users WHERE id = ?', [id]);
  return rows[0];
}

// NeonDB无服务器 - 使用@neondatabase/serverless
import { Pool } from '@neondatabase/serverless';

const pool = new Pool({ connectionString: process.env.DATABASE_URL });

4. 分页和限制

// 之前 - 获取所有记录(内存爆炸!)
async function getProducts() {
  return await db.products.findAll(); // 可能是数百万行
}

// 之后 - 基于游标的分页
async function getProducts({ cursor, limit = 20 }) {
  return await db.products.findMany({
    take: limit,
    skip: cursor ? 1 : 0,
    cursor: cursor ? { id: cursor } : undefined,
    orderBy: { createdAt: 'desc' }
  });
}

// 偏移分页(更简单,但对深层页面较慢)
async function getProducts({ page = 1, limit = 20 }) {
  const offset = (page - 1) * limit;
  return await db.products.findMany({
    take: limit,
    skip: offset,
    orderBy: { createdAt: 'desc' }
  });
}

5. 异步处理和作业队列

// 之前 - 阻塞请求直到邮件发送
app.post('/signup', async (req, res) => {
  const user = await createUser(req.body);
  await sendWelcomeEmail(user.email); // 阻塞2-3秒!
  res.json({ success: true });
});

// 之后 - 队列作业,立即响应
import { Queue } from 'bullmq';

const emailQueue = new Queue('emails', {
  connection: { host: 'localhost', port: 6379 }
});

app.post('/signup', async (req, res) => {
  const user = await createUser(req.body);
  
  // 将邮件任务加入队列异步发送
  await emailQueue.add('welcome', {
    to: user.email,
    userId: user.id
  });
  
  res.json({ success: true }); // 快速响应!
});

// 工作进程在后台处理作业
const worker = new Worker('emails', async (job) => {
  await sendEmail(job.data.to, 'welcome', { userId: job.data.userId });
});

算法优化

选择正确的数据结构

// 之前 - O(n)查找
const activeUsers = [];
function isActive(userId) {
  return activeUsers.includes(userId); // 线性搜索
}

// 之后 - O(1)查找
const activeUsers = new Set();
function isActive(userId) {
  return activeUsers.has(userId); // 常数时间
}

// 之前 - 在开头频繁插入/删除时为O(n)
const queue = [];
queue.unshift(item); // O(n) - 移动整个数组

// 之后 - 使用适当数据结构的O(1)
class Queue {
  constructor() {
    this.items = {};
    this.head = 0;
    this.tail = 0;
  }
  
  enqueue(item) {
    this.items[this.tail] = item;
    this.tail++;
  }
  
  dequeue() {
    const item = this.items[this.head];
    delete this.items[this.head];
    this.head++;
    return item;
  }
}

减少计算复杂度

// 之前 - O(n²)嵌套循环
function findDuplicates(arr) {
  const duplicates = [];
  for (let i = 0; i < arr.length; i++) {
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[i] === arr[j]) {
        duplicates.push(arr[i]);
      }
    }
  }
  return duplicates;
}

// 之后 - 使用Set的O(n)
function findDuplicates(arr) {
  const seen = new Set();
  const duplicates = new Set();
  
  for (const item of arr) {
    if (seen.has(item)) {
      duplicates.add(item);
    }
    seen.add(item);
  }
  
  return Array.from(duplicates);
}

监控和警报

添加性能指标

import { performance } from 'perf_hooks';

async function processOrder(order) {
  const startTime = performance.now();
  
  try {
    const result = await expensiveProcessing(order);
    
    const duration = performance.now() - startTime;
    
    // 记录慢操作
    if (duration > 1000) {
      logger.warn('订单处理慢', { 
        orderId: order.id, 
        duration 
      });
    }
    
    // 发送指标到监控服务
    metrics.histogram('order_processing_time', duration, {
      status: 'success'
    });
    
    return result;
  } catch (error) {
    const duration = performance.now() - startTime;
    metrics.histogram('order_processing_time', duration, {
      status: 'error'
    });
    throw error;
  }
}

性能检查清单

前端:
□ 包大小 < 200KB(gzipped)
□ 图像优化(WebP/AVIF)
□ 首屏以下内容懒加载
□ 路由代码分割
□ 长列表虚拟化
□ 昂贵计算记忆化
□ HTTP缓存头设置
□ 关键CSS内联

后端:
□ 数据库查询索引化
□ N+1查询消除
□ 连接池配置
□ 响应分页
□ 重操作队列化
□ 响应缓存实现
□ Gzip压缩启用
□ 静态资产使用CDN

通用:
□ 性能预算定义
□ 监控和警报配置
□ CI中定期性能测试
□ 在真实数据上进行分析

资源


记住:快速软件让用户愉悦。测量、优化瓶颈,并持续监控。