🚀 快速安装

复制以下命令并运行,立即安装此 Skill:

npx @anthropic-ai/skills install supercent-io/skills-template/performance-optimization

💡 提示:需要 Node.js 和 NPM

性能优化

何时使用此技能

  • 页面加载缓慢:Lighthouse 得分低
  • 渲染缓慢:用户交互延迟
  • 打包体积过大:下载时间增加
  • 查询缓慢:数据库瓶颈

指示

步骤 1:测量性能

Lighthouse(Chrome DevTools)

# 命令行
npm install -g lighthouse
lighthouse https://example.com --view

# 在 CI 中自动化
lighthouse https://example.com --output=json --output-path=./report.json

测量 Web Vitals(React):

import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';

function sendToAnalytics(metric: any) {
  // 发送到 Google Analytics, Datadog 等
  console.log(metric);
}

getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getFCP(sendToAnalytics);
getLCP(sendToAnalytics);
getTTFB(sendToAnalytics);

步骤 2:优化 React

React.memo(防止不必要的重新渲染)

// ❌ 反面示例:每次父组件重新渲染时,子组件也会重新渲染
function ExpensiveComponent({ data }: { data: Data }) {
  return <div>{/* 复杂渲染 */}</div>;
}

// ✅ 正确示例:仅在 props 变化时重新渲染
const ExpensiveComponent = React.memo(({ data }: { data: Data }) => {
  return <div>{/* 复杂渲染 */}</div>;
});

useMemo & useCallback

function ProductList({ products, category }: Props) {
  // ✅ 记忆化过滤结果
  const filteredProducts = useMemo(() => {
    return products.filter(p => p.category === category);
  }, [products, category]);

  // ✅ 记忆化回调函数
  const handleAddToCart = useCallback((id: string) => {
    addToCart(id);
  }, []);

  return (
    <div>
      {filteredProducts.map(product => (
        <ProductCard key={product.id} product={product} onAdd={handleAddToCart} />
      ))}
    </div>
  );
}

懒加载 & 代码拆分

import { lazy, Suspense } from 'react';

// ✅ 基于路由的代码拆分
const Dashboard = lazy(() => import('./pages/Dashboard'));
const Profile = lazy(() => import('./pages/Profile'));
const Settings = lazy(() => import('./pages/Settings'));

function App() {
  return (
    <Suspense fallback={<div>加载中...</div>}>
      <Routes>
        <Route path="/dashboard" element={<Dashboard />} />
        <Route path="/profile" element={<Profile />} />
        <Route path="/settings" element={<Settings />} />
      </Routes>
    </Suspense>
  );
}

// ✅ 基于组件的懒加载
const HeavyChart = lazy(() => import('./components/HeavyChart'));

function Dashboard() {
  return (
    <div>
      <h1>仪表板</h1>
      <Suspense fallback={<Skeleton />}>
        <HeavyChart data={data} />
      </Suspense>
    </div>
  );
}

步骤 3:优化打包体积

Webpack Bundle Analyzer

npm install --save-dev webpack-bundle-analyzer

# package.json
{
  "scripts": {
    "analyze": "webpack-bundle-analyzer build/stats.json"
  }
}

Tree Shaking(移除未使用的代码)

// ❌ 反面示例:导入整个库
import _ from 'lodash';

// ✅ 正确示例:只导入所需部分
import debounce from 'lodash/debounce';

动态导入

// ✅ 仅在需要时加载
button.addEventListener('click', async () => {
  const { default: Chart } = await import('chart.js');
  new Chart(ctx, config);
});

步骤 4:优化图片

Next.js Image 组件

import Image from 'next/image';

function ProductImage() {
  return (
    <Image
      src="/product.jpg"
      alt="产品图片"
      width={500}
      height={500}
      priority  // 对于最大内容绘制图片使用
      placeholder="blur"  // 模糊占位符
      sizes="(max-width: 768px) 100vw, 50vw"
    />
  );
}

使用 WebP 格式

<picture>
  <source srcset="image.webp" type="image/webp">
  <source srcset="image.jpg" type="image/jpeg">
  <img src="image.jpg" alt="后备图片">
</picture>

步骤 5:优化数据库查询

修复 N+1 查询问题

// ❌ 反面示例:N+1 查询
const posts = await db.post.findMany();
for (const post of posts) {
  const author = await db.user.findUnique({ where: { id: post.authorId } });
  // 101 次查询(1 + 100)
}

// ✅ 正确示例:JOIN 或 include
const posts = await db.post.findMany({
  include: {
    author: true
  }
});
// 1 次查询

添加索引

-- 识别慢查询
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@example.com';

-- 添加索引
CREATE INDEX idx_users_email ON users(email);

-- 复合索引
CREATE INDEX idx_orders_user_date ON orders(user_id, created_at);

缓存(Redis)

async function getUserProfile(userId: string) {
  // 1. 检查缓存
  const cached = await redis.get(`user:${userId}`);
  if (cached) {
    return JSON.parse(cached);
  }

  // 2. 查询数据库
  const user = await db.user.findUnique({ where: { id: userId } });

  // 3. 存入缓存(1 小时)
  await redis.setex(`user:${userId}`, 3600, JSON.stringify(user));

  return user;
}

输出格式

性能优化检查清单

## 前端
- [ ] 使用 React.memo 防止不必要的重新渲染
- [ ] 恰当地使用 useMemo/useCallback
- [ ] 懒加载 & 代码拆分
- [ ] 优化图片(WebP, 懒加载)
- [ ] 分析并减少打包体积

## 后端
- [ ] 消除 N+1 查询
- [ ] 添加数据库索引
- [ ] Redis 缓存
- [ ] 压缩 API 响应(gzip)
- [ ] 使用 CDN

## 测量指标
- [ ] Lighthouse 得分 90+
- [ ] LCP < 2.5秒
- [ ] FID < 100毫秒
- [ ] CLS < 0.1

约束条件

必需规则(必须遵守)

  1. 先测量:分析性能,不要猜测
  2. 逐步改进:一次只优化一件事
  3. 性能监控:持续跟踪

禁止事项(不得违反)

  1. 过早优化:没有瓶颈时不要优化
  2. 牺牲可读性:不要为性能让代码变得复杂

最佳实践

  1. 二八定律:20% 的努力带来 80% 的改进
  2. 以用户为中心:专注于改善真实用户体验
  3. 自动化:在 CI 中运行性能回归测试

参考资料

元数据

版本

  • 当前版本:1.0.0
  • 最后更新:2025-01-01
  • 兼容平台:Claude, ChatGPT, Gemini

相关技能

标签

#性能 #优化 #React #缓存 #懒加载 #web-vitals #代码质量

示例

示例 1:基本用法

示例 2:高级用法

📄 原始文档

完整文档(英文):

https://skills.sh/supercent-io/skills-template/performance-optimization

💡 提示:点击上方链接查看 skills.sh 原始英文文档,方便对照翻译。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。