本文へ移動
cccskills
無料GitHub で公開

performance-optimization

优化前端性能 / 包大小 / 渲染 / 网络时使用。覆盖 Web Vitals (LCP/INP/CLS) / Bundle / Image / Code Splitting / 虚拟列表。融合性能预算 + RUM + 优化优先级。

インストール方法を見る

含まれるファイル(2)

  • SKILL.md12.8 KB
  • templates/performance-checklist.md3.9 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

性能优化(Performance Optimization)

参考来源:Google Web Vitals、Web.dev、Vercel Edge / Next.js 性能实践、Stripe 前端性能指南、Core Web Vitals 2024 更新(FID → INP)。

适用场景

  • 首屏速度优化(LCP / FCP)
  • 交互响应(INP / TTI)
  • 视觉稳定性(CLS)
  • 包大小优化
  • 大列表 / 大表格性能
  • 长任务拆解
  • 内存泄漏排查

核心原则

1. 测量优先,不要猜
   先 Lighthouse / DevTools / RUM
   定位瓶颈再优化

2. 性能预算
   首屏 JS < 200KB(gzip)
   首屏图片 < 200KB
   LCP < 2.5s / INP < 200ms / CLS < 0.1

3. 关注真实用户(RUM)
   实验室数据 ≠ 真实数据

4. 优先级:网络 → 渲染 → 计算
   - 减少传输
   - 减少阻塞
   - 减少重排

5. 不过早优化
   小项目过度优化 = 浪费时间

6. 持续监控
   性能退化是渐进的

Core Web Vitals 2026

指标含义好差
LCPLargest Contentful Paint< 2.5s> 4s
INPInteraction to Next Paint(替代 FID)< 200ms> 500ms
CLSCumulative Layout Shift< 0.1> 0.25
FCPFirst Contentful Paint< 1.8s> 3s
TTFBTime to First Byte< 800ms> 1.8s

性能预算(Performance Budget)

首屏(Critical Path):
  HTML:< 30 KB
  关键 CSS:< 15 KB(inline 或 critical CSS)
  JS(首屏):< 200 KB(gzip)
  字体:< 100 KB(仅必要字重)
  首屏图片:< 200 KB(webp/avif)
  
总页面:
  JS(全部):< 500 KB
  CSS(全部):< 100 KB
  图片(全部):< 1 MB

时间:
  TTFB:< 800ms
  LCP:< 2.5s
  INP:< 200ms
  CLS:< 0.1

测量工具

实验室

Lighthouse(Chrome DevTools / CLI):
  - Performance 评分
  - 4 个 Web Vitals
  - 问题清单

WebPageTest:
  - 多地理位置
  - 网络节流
  - 视频对比

Chrome DevTools:
  - Performance 面板(火焰图)
  - Network 面板
  - Coverage(未用代码)
  - Memory 面板(泄漏)

Bundle Analyzer:
  - webpack-bundle-analyzer
  - vite-bundle-visualizer
  - Source Map Explorer

真实用户(RUM)

import { onLCP, onINP, onCLS, onFCP, onTTFB } from 'web-vitals';

function sendToAnalytics(metric: any) {
  // 发到 Sentry / Datadog / GA / 自建
  navigator.sendBeacon('/analytics', JSON.stringify({
    name: metric.name,
    value: metric.value,
    id: metric.id,
    rating: metric.rating,  // 'good' | 'needs-improvement' | 'poor'
    url: window.location.pathname,
  }));
}

onLCP(sendToAnalytics);
onINP(sendToAnalytics);
onCLS(sendToAnalytics);
onFCP(sendToAnalytics);
onTTFB(sendToAnalytics);

1. 网络优化(最大杠杆)

减少 / 推迟资源

策略:
  □ 移除未用代码(Tree-shake)
  □ 第三方脚本 lazy load(async / defer)
  □ 字体子集 + font-display: swap
  □ 图片 webp / avif + responsive
  □ HTTP/2 / HTTP/3
  □ Brotli 压缩
  □ CDN 边缘

图片优化(最大坑)

// Next.js Image
<Image
  src="/hero.jpg"
  alt="Hero"
  width={1200}
  height={600}
  priority                    // 首屏加 priority
  placeholder="blur"
  blurDataURL="..."
/>

// 原生 picture
<picture>
  <source type="image/avif" srcset="hero.avif" />
  <source type="image/webp" srcset="hero.webp" />
  <img
    src="hero.jpg"
    alt="Hero"
    loading="lazy"            // 非首屏 lazy
    decoding="async"
    width="1200"
    height="600"              // 必填(防 CLS)
  />
</picture>

// Responsive srcset
<img
  src="hero-small.jpg"
  srcset="hero-small.jpg 400w, hero-medium.jpg 800w, hero-large.jpg 1200w"
  sizes="(max-width: 600px) 400px, (max-width: 1200px) 800px, 1200px"
  alt="Hero"
/>

字体优化

@font-face {
  font-family: 'Inter';
  src: url('/fonts/Inter-var.woff2') format('woff2-variations');
  font-display: swap;          /* 不阻塞渲染 */
  font-weight: 100 900;
}

/* 子集 - 只用拉丁 */
@font-face {
  font-family: 'Inter';
  src: url('/fonts/Inter-latin.woff2') format('woff2');
  unicode-range: U+0000-007F;
}
<!-- 关键字体预加载 -->
<link rel="preload" href="/fonts/Inter-var.woff2" as="font" type="font/woff2" crossorigin>

关键资源 preload / prefetch

<!-- 当前页关键 -->
<link rel="preload" href="/api/critical-data" as="fetch" crossorigin>

<!-- 下一页可能用 -->
<link rel="prefetch" href="/dashboard">

<!-- DNS 预解析 -->
<link rel="dns-prefetch" href="https://api.example.com">
<link rel="preconnect" href="https://api.example.com">

2. 包大小优化

Bundle 分析

# Vite
npm i -D rollup-plugin-visualizer
# vite.config.ts
import { visualizer } from 'rollup-plugin-visualizer';
plugins: [visualizer({ open: true, gzipSize: true })]

# Webpack
npm i -D webpack-bundle-analyzer

Tree Shaking

// ✅ 命名导入(tree-shake 友好)
import { debounce } from 'lodash-es';

// ❌ 整库引入
import _ from 'lodash';

// ❌ CommonJS 难 tree-shake
import { debounce } from 'lodash';

Code Splitting

// 路由级(最重要)
const Dashboard = lazy(() => import('./pages/Dashboard'));
const Settings = lazy(() => import('./pages/Settings'));

// 组件级(重组件 / 模态)
const HeavyChart = lazy(() => import('./HeavyChart'));

function App() {
  return (
    <Suspense fallback={<Skeleton />}>
      <HeavyChart />
    </Suspense>
  );
}

// 命名 chunk
const HeavyChart = lazy(() => 
  import(/* webpackChunkName: "heavy-chart" */ './HeavyChart')
);

替换大库

moment.js (66KB) → date-fns (modular) / dayjs (2KB)
lodash → lodash-es (tree-shake) / 单独函数
axios → fetch / ky
全 ECharts → echarts/core + 按需导入模块
全 lucide-react → lucide-react/icons/Specific

动态导入

// 按需加载重计算
async function exportToExcel(data) {
  const { utils, writeFile } = await import('xlsx');
  const ws = utils.json_to_sheet(data);
  // ...
}

3. 渲染优化

React 优化

// 1. memo(仅当父组件频繁渲染但 props 不变)
const ExpensiveItem = memo(function ExpensiveItem({ item }) {
  return <div>...</div>;
});

// 2. useMemo(重计算)
const filteredList = useMemo(
  () => list.filter(complexFilter),
  [list]
);

// 3. useCallback(传给 memo 子组件)
const handleClick = useCallback((id: number) => {
  setSelectedId(id);
}, []);

// 4. 状态拆分(减少重渲染范围)
// ❌ 大对象
const [state, setState] = useState({ ... 10 个字段 ... });

// ✅ 拆细
const [name, setName] = useState('');
const [age, setAge] = useState(0);
// ...

// 5. 用 Zustand selector 避免重渲染
const userName = useStore((s) => s.user.name);  // 仅 name 变才重渲

// 6. React Compiler(实验,自动优化)

Vue 3 优化

<!-- 1. v-once 静态内容 -->
<header v-once>
  <h1>{{ title }}</h1>
</header>

<!-- 2. v-memo 跳过重渲染 -->
<div v-for="item in list" v-memo="[item.id, item.selected]">
  ...
</div>

<!-- 3. 大列表 shallowRef -->
<script setup>
import { shallowRef } from 'vue';
const heavyData = shallowRef(largeArray);
</script>

<!-- 4. 异步组件 -->
<script setup>
import { defineAsyncComponent } from 'vue';
const HeavyChart = defineAsyncComponent(() => import('./HeavyChart.vue'));
</script>

虚拟列表(大数据必备)

// TanStack Virtual
import { useVirtualizer } from '@tanstack/react-virtual';

function VirtualList({ items }: { items: Item[] }) {
  const parentRef = useRef<HTMLDivElement>(null);
  
  const virtualizer = useVirtualizer({
    count: items.length,
    getScrollElement: () => parentRef.current,
    estimateSize: () => 50,
    overscan: 5,
  });
  
  return (
    <div ref={parentRef} style={{ height: 600, overflow: 'auto' }}>
      <div style={{ height: virtualizer.getTotalSize(), position: 'relative' }}>
        {virtualizer.getVirtualItems().map((virtualRow) => (
          <div
            key={virtualRow.key}
            style={{
              position: 'absolute',
              top: 0,
              left: 0,
              width: '100%',
              height: virtualRow.size,
              transform: `translateY(${virtualRow.start}px)`,
            }}
          >
            {items[virtualRow.index].name}
          </div>
        ))}
      </div>
    </div>
  );
}

CLS 优化

原因:图片 / 广告 / 字体 / 异步内容插入

解决:
  □ 图片必须有 width/height(保留位置)
  □ 字体 size-adjust 适配
  □ 骨架屏占位
  □ 广告 / 嵌入式预留容器(min-height)
  □ Skeleton 与最终尺寸一致
<!-- 必须 width / height -->
<img src="hero.jpg" alt="" width="1200" height="600" />

<!-- 或 aspect-ratio -->
<div style="aspect-ratio: 16/9; background: #eee;">
  <img src="hero.jpg" alt="" />
</div>

INP 优化

INP = 用户交互 → 下次绘制的时间

优化:
  □ 长任务拆分(< 50ms)
  □ 防抖输入
  □ 节流滚动
  □ Web Worker 计算
  □ requestIdleCallback / scheduler.yield()
  □ 避免 forced reflow
// 长任务拆分
async function processLargeData(data: Data[]) {
  const chunks = chunk(data, 100);
  for (const c of chunks) {
    processChunk(c);
    await new Promise(resolve => setTimeout(resolve, 0));  // yield
  }
}

// scheduler.yield()(新 API,更精确)
async function processLargeData(data: Data[]) {
  for (const item of data) {
    processItem(item);
    if ('scheduler' in window && 'yield' in scheduler) {
      await scheduler.yield();
    }
  }
}

// Web Worker
const worker = new Worker(new URL('./worker.ts', import.meta.url));
worker.postMessage(data);
worker.onmessage = (e) => setResult(e.data);

4. 缓存与离线

HTTP 缓存:
  - Cache-Control: public, max-age=31536000, immutable(哈希文件名)
  - ETag / Last-Modified(HTML)

Service Worker:
  - 预缓存关键资源
  - Stale-While-Revalidate
  - 离线兜底页

应用层:
  - TanStack Query 内存缓存
  - localStorage 用户偏好
  - IndexedDB 大量数据

5. SSR / 流式渲染

SSR 优势:
  - 首屏快(HTML 直出)
  - SEO 好
  
潜在问题:
  - TTFB 慢(服务端渲染要时间)
  - hydration 慢

优化:
  - Streaming SSR(HTML 流式返回)
  - Server Components(React 19)
  - Selective Hydration(部分 hydrate)
  - Islands(Astro / Qwik)
  - Resumability(Qwik)

性能优化优先级(ROI)

1. 图片优化(40% 收益)
2. 包大小(20%)
3. Code splitting(15%)
4. 虚拟列表(10%)
5. memo / useMemo(5%)
6. 微优化(5%)

不要:
  - 还没测就 memo 全部
  - useMemo 所有计算
  - useCallback 所有函数

工作流程

1. 测量基线
   - Lighthouse / RUM
   - 记录 Web Vitals

2. 找瓶颈
   - 网络(最常见)
   - 渲染(中等)
   - 计算(少)

3. 性能预算
   - 首屏 JS / CSS / 图片预算
   - LCP / INP / CLS 目标

4. 实施优化(按优先级)

5. 重新测量

6. 持续监控(RUM)

7. 性能退化告警
   - LCP P75 > 2.5s 持续 → 告警

配套模板

  • templates/performance-checklist.md — Web Vitals + 包大小 + 图片 + 字体 + 渲染 + 监控

质量自检

□ Lighthouse Performance ≥ 90
□ LCP < 2.5s(P75)
□ INP < 200ms(P75)
□ CLS < 0.1
□ 首屏 JS < 200KB(gzip)
□ 总 CSS < 100KB
□ 图片 webp/avif + 懒加载
□ 字体 woff2 + font-display: swap
□ 路由级 code splitting
□ 大列表虚拟化
□ Tree-shake 友好导入
□ 包分析检查
□ RUM 监控接入
□ 性能预算文档化

常见坑

  1. 图片不优化——LCP 直接挂
  2. 图片不限尺寸——CLS 爆炸
  3. 字体阻塞渲染——FOIT
  4. 整库引入——包翻倍
  5. 不 code splitting——首屏 1MB
  6. memo 全部——过度优化反而慢
  7. useEffect 滥用——无限重渲染
  8. 大列表不虚拟化——卡死
  9. 同步阻塞操作——长任务
  10. 不监控 RUM——线上才知道
  11. 第三方脚本同步加载——阻塞首屏
  12. CSS 大量 @import——串行加载
  13. 图片用 background-image——不能 lazy
  14. scroll handler 不节流——卡顿
  15. 不预加载关键字体——FOUT

与其他 skill 的协作

上游:
  ui-ux-designer 工作流 → 设计 / 图片资源
  api-designer → 接口性能 / 缓存策略

下游:
  build-deploy → 打包优化
  observability(前端)→ RUM 接入
  testing-frontend → 性能测试

相关参考

  • 项目根 references/frontend-tech-stack-guide.md — 性能工具

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

A/B 测试设计与分析时使用。适用于产品实验、功能验证、转化率优化。融合假设驱动 + 样本量计算 + 置信度判断。

日本語の概要は準備中です。原文の説明を表示しています。

zhaoxuya520/AI-Fullstack-Delivery-Workflow532026年5月19日 更新

上线前业务方/产品方验收时使用。适用于功能交付确认、UAT、发布会签。融合 BDD Given-When-Then、Specification by Example、ATDD。

日本語の概要は準備中です。原文の説明を表示しています。

zhaoxuya520/AI-Fullstack-Delivery-Workflow532026年5月19日 更新

设计无障碍可访问的界面时使用。适用于满足 WCAG 标准、键盘导航、屏幕阅读器支持。优先使用 WCAG 2.2 AA 级标准 + 键盘 + 焦点 + 对比度 + ARIA。

日本語の概要は準備中です。原文の説明を表示しています。

zhaoxuya520/AI-Fullstack-Delivery-Workflow532026年5月19日 更新

实现可访问性(无障碍)时使用。覆盖 WCAG 2.2 AA / ARIA / 键盘导航 / 屏幕阅读器 / 颜色对比 / 焦点管理。融合 React Aria / Radix UI / Headless UI 实践 + axe-core 自动化测试。

日本語の概要は準備中です。原文の説明を表示しています。

zhaoxuya520/AI-Fullstack-Delivery-Workflow532026年5月19日 更新

AI 模型部署时使用。适用于推理服务 / GPU / TensorRT / 监控 / 扩缩容。

日本語の概要は準備中です。原文の説明を表示しています。

zhaoxuya520/AI-Fullstack-Delivery-Workflow532026年5月19日 更新

数据分析报告输出时使用。适用于业务分析报告、周报、专项分析、决策支持。融合洞察 + 建议 + 行动项。

日本語の概要は準備中です。原文の説明を表示しています。

zhaoxuya520/AI-Fullstack-Delivery-Workflow532026年5月19日 更新

zhaoxuya520 のスキルをすべて見る

このスキルの問題を報告する