[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6H8BZ2E4FWTSPJF8H60YBDF":3,"skill-same:01M6H8BZ2E4FWTSPJF8H60YBDF":84},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":42,"linkOnly":43,"markdownContent":44,"markdownBody":45,"frontMatter":46,"refName":47,"commitSha":48,"skillDirectory":49,"forksCount":50,"repositoryHtmlUrl":51,"repositoryHomepageUrl":6,"ownerHtmlUrl":52,"ownerBlogUrl":53,"ownerDescription":54,"updatedAt":55,"install":56,"resources":69},"01M6H8BZ2E4FWTSPJF8H60YBDF","performance-optimizer",null,"Optimize web performance including Core Web Vitals, bundle size, and runtime efficiency. Analyze and improve LCP, FID, CLS metrics. Use when optimizing performance, reducing bundle size, or when the user mentions slow, performance, loading, lighthouse, or web vitals.","rotifer-protocol\u002Frotifer-playground","rotifer-protocol","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F262854335?v=4","01M6H88XQBWNQXVGHBCGZZCQVX","Rotifer Protocol","01M6H88XVXE7GHR06H8E1SP311",6,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Frotifer-protocol\u002Frotifer-playground\u002Fblob\u002Fmain\u002Fgenes\u002Fperformance-optimizer\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41],"performance optimizer","performance","optimizer","use","when","vitals","size","loading","optimizing performance","web vitals","optimize web","runtime","efficiency","optimize","bundle size","analyze","improve","Lighthouse","core web vitals","web performance","metrics","core","web","2026-11-10 10:12:30",false,"---\nname: performance-optimizer\ndescription: Optimize web performance including Core Web Vitals, bundle size, and runtime efficiency. Analyze and improve LCP, FID, CLS metrics. Use when optimizing performance, reducing bundle size, or when the user mentions slow, performance, loading, lighthouse, or web vitals.\n---\n\n# Performance Optimizer (性能优化师)\n\n**Goal**: 提升 Web 应用性能，确保良好用户体验和 SEO 表现。\n\n**核心指标**: Core Web Vitals (LCP, FID, CLS)\n\n---\n\n## 1. Core Web Vitals\n\n### 指标标准\n\n| 指标 | 含义 | Good | Needs Improvement | Poor |\n|------|------|------|-------------------|------|\n| **LCP** | 最大内容绘制 | \u003C 2.5s | 2.5s - 4s | > 4s |\n| **FID** | 首次输入延迟 | \u003C 100ms | 100ms - 300ms | > 300ms |\n| **CLS** | 累积布局偏移 | \u003C 0.1 | 0.1 - 0.25 | > 0.25 |\n| **INP** | 交互到下一次绘制 | \u003C 200ms | 200ms - 500ms | > 500ms |\n\n### 测量工具\n\n```bash\n# Lighthouse CLI\nnpx lighthouse https:\u002F\u002Fexample.com --view\n\n# Web Vitals 库\npnpm add web-vitals\n```\n\n```typescript\n\u002F\u002F 监控 Web Vitals\nimport { onLCP, onFID, onCLS, onINP } from 'web-vitals'\n\nonLCP(console.log)\nonFID(console.log)\nonCLS(console.log)\nonINP(console.log)\n```\n\n---\n\n## 2. Next.js Optimizations\n\n### Image 优化\n\n```tsx\n\u002F\u002F ❌ 未优化\n\u003Cimg src=\"\u002Fhero.png\" \u002F>\n\n\u002F\u002F ✅ 使用 next\u002Fimage\nimport Image from 'next\u002Fimage'\n\n\u003CImage\n  src=\"\u002Fhero.png\"\n  width={800}\n  height={400}\n  alt=\"Hero\"\n  priority  \u002F\u002F LCP 图片加 priority\n\u002F>\n```\n\n### Font 优化\n\n```typescript\n\u002F\u002F app\u002Flayout.tsx\nimport { Inter } from 'next\u002Ffont\u002Fgoogle'\n\nconst inter = Inter({\n  subsets: ['latin'],\n  display: 'swap',  \u002F\u002F 避免 FOIT\n  preload: true,\n})\n\nexport default function Layout({ children }) {\n  return (\n    \u003Chtml className={inter.className}>\n      \u003Cbody>{children}\u003C\u002Fbody>\n    \u003C\u002Fhtml>\n  )\n}\n```\n\n### Script 优化\n\n```tsx\nimport Script from 'next\u002Fscript'\n\n\u002F\u002F 非关键脚本延迟加载\n\u003CScript \n  src=\"https:\u002F\u002Fanalytics.com\u002Fscript.js\" \n  strategy=\"lazyOnload\" \n\u002F>\n\n\u002F\u002F 交互后加载\n\u003CScript \n  src=\"https:\u002F\u002Fwidget.com\u002Fchat.js\" \n  strategy=\"afterInteractive\" \n\u002F>\n```\n\n### 动态导入\n\n```tsx\nimport dynamic from 'next\u002Fdynamic'\n\n\u002F\u002F 客户端组件延迟加载\nconst HeavyChart = dynamic(() => import('.\u002FHeavyChart'), {\n  loading: () => \u003CSkeleton \u002F>,\n  ssr: false,\n})\n\n\u002F\u002F 条件导入\nconst AdminPanel = dynamic(() => import('.\u002FAdminPanel'), {\n  loading: () => null,\n})\n\nfunction Page() {\n  return (\n    \u003C>\n      {isAdmin && \u003CAdminPanel \u002F>}\n    \u003C\u002F>\n  )\n}\n```\n\n---\n\n## 3. Bundle Size Optimization\n\n### 分析 Bundle\n\n```bash\n# 安装分析工具\npnpm add -D @next\u002Fbundle-analyzer\n\n# next.config.js\nconst withBundleAnalyzer = require('@next\u002Fbundle-analyzer')({\n  enabled: process.env.ANALYZE === 'true',\n})\n\nmodule.exports = withBundleAnalyzer({\n  \u002F\u002F config\n})\n\n# 运行分析\nANALYZE=true pnpm build\n```\n\n### Tree Shaking\n\n```typescript\n\u002F\u002F ❌ 导入整个库\nimport _ from 'lodash'\n_.debounce(fn, 300)\n\n\u002F\u002F ✅ 按需导入\nimport debounce from 'lodash\u002Fdebounce'\ndebounce(fn, 300)\n\n\u002F\u002F ✅ 或使用 lodash-es\nimport { debounce } from 'lodash-es'\n```\n\n### 替换重型库\n\n| 重型库 | 轻量替代 | 节省 |\n|--------|----------|------|\n| moment.js | date-fns \u002F dayjs | ~95% |\n| lodash | lodash-es + 按需导入 | ~90% |\n| axios | fetch (原生) | 100% |\n| uuid | nanoid | ~75% |\n\n### 代码分割\n\n```tsx\n\u002F\u002F 路由级分割 (Next.js 自动)\n\u002F\u002F app\u002Fdashboard\u002Fpage.tsx → 单独 chunk\n\n\u002F\u002F 组件级分割\nconst Modal = dynamic(() => import('.\u002FModal'))\n\n\u002F\u002F 条件加载\nif (condition) {\n  const module = await import('.\u002Fheavy-module')\n}\n```\n\n---\n\n## 4. React Optimizations\n\n### 避免不必要的重渲染\n\n```tsx\n\u002F\u002F ❌ 每次渲染创建新对象\n\u003CChild style={{ color: 'red' }} \u002F>\n\n\u002F\u002F ✅ 使用 useMemo\nconst style = useMemo(() => ({ color: 'red' }), [])\n\u003CChild style={style} \u002F>\n```\n\n```tsx\n\u002F\u002F ❌ 每次渲染创建新函数\n\u003CButton onClick={() => handleClick(id)} \u002F>\n\n\u002F\u002F ✅ 使用 useCallback\nconst onClick = useCallback(() => handleClick(id), [id])\n\u003CButton onClick={onClick} \u002F>\n```\n\n### React.memo\n\n```tsx\n\u002F\u002F 纯展示组件用 memo\nconst UserCard = memo(function UserCard({ user }) {\n  return \u003Cdiv>{user.name}\u003C\u002Fdiv>\n})\n\n\u002F\u002F 对比函数 (复杂 props)\nconst UserCard = memo(function UserCard({ user }) {\n  return \u003Cdiv>{user.name}\u003C\u002Fdiv>\n}, (prev, next) => prev.user.id === next.user.id)\n```\n\n### 虚拟化长列表\n\n```tsx\nimport { useVirtualizer } from '@tanstack\u002Freact-virtual'\n\nfunction VirtualList({ items }) {\n  const parentRef = useRef(null)\n  \n  const virtualizer = useVirtualizer({\n    count: items.length,\n    getScrollElement: () => parentRef.current,\n    estimateSize: () => 50,\n  })\n\n  return (\n    \u003Cdiv ref={parentRef} style={{ height: '400px', overflow: 'auto' }}>\n      \u003Cdiv style={{ height: virtualizer.getTotalSize() }}>\n        {virtualizer.getVirtualItems().map((virtualItem) => (\n          \u003Cdiv\n            key={virtualItem.key}\n            style={{\n              position: 'absolute',\n              top: virtualItem.start,\n              height: virtualItem.size,\n            }}\n          >\n            {items[virtualItem.index]}\n          \u003C\u002Fdiv>\n        ))}\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n  )\n}\n```\n\n---\n\n## 5. Network Optimizations\n\n### 预加载关键资源\n\n```tsx\n\u002F\u002F app\u002Flayout.tsx\nexport default function Layout() {\n  return (\n    \u003Chtml>\n      \u003Chead>\n        \u003Clink rel=\"preconnect\" href=\"https:\u002F\u002Fapi.openai.com\" \u002F>\n        \u003Clink rel=\"dns-prefetch\" href=\"https:\u002F\u002Ffonts.googleapis.com\" \u002F>\n      \u003C\u002Fhead>\n    \u003C\u002Fhtml>\n  )\n}\n```\n\n### 缓存策略\n\n```typescript\n\u002F\u002F API 缓存头\nexport async function GET() {\n  return Response.json(data, {\n    headers: {\n      'Cache-Control': 'public, max-age=60, stale-while-revalidate=300',\n    },\n  })\n}\n\n\u002F\u002F Next.js fetch 缓存\nconst data = await fetch(url, {\n  next: { revalidate: 60 },  \u002F\u002F ISR\n})\n\n\u002F\u002F React Query 缓存\nconst { data } = useQuery({\n  queryKey: ['users'],\n  queryFn: fetchUsers,\n  staleTime: 60 * 1000,  \u002F\u002F 1 分钟内不重新请求\n})\n```\n\n### 压缩\n\n```javascript\n\u002F\u002F next.config.js\nmodule.exports = {\n  compress: true,  \u002F\u002F 默认开启\n  \n  \u002F\u002F 或使用更高压缩率\n  experimental: {\n    serverActions: {\n      bodySizeLimit: '2mb',\n    },\n  },\n}\n```\n\n---\n\n## 6. CLS Prevention\n\n### 图片尺寸\n\n```tsx\n\u002F\u002F ❌ 无尺寸，导致布局偏移\n\u003Cimg src=\"\u002Fphoto.jpg\" \u002F>\n\n\u002F\u002F ✅ 明确尺寸\n\u003CImage src=\"\u002Fphoto.jpg\" width={400} height={300} alt=\"\" \u002F>\n\n\u002F\u002F ✅ 占位容器\n\u003Cdiv style={{ aspectRatio: '16\u002F9' }}>\n  \u003CImage src=\"\u002Fphoto.jpg\" fill alt=\"\" \u002F>\n\u003C\u002Fdiv>\n```\n\n### 字体加载\n\n```css\n\u002F* 使用 font-display: swap *\u002F\n@font-face {\n  font-family: 'Custom';\n  src: url('\u002Ffont.woff2') format('woff2');\n  font-display: swap;\n}\n```\n\n### 动态内容\n\n```tsx\n\u002F\u002F ❌ 内容插入导致偏移\n{isLoaded && \u003CBanner \u002F>}\n\n\u002F\u002F ✅ 预留空间\n\u003Cdiv style={{ minHeight: '100px' }}>\n  {isLoaded ? \u003CBanner \u002F> : \u003CSkeleton \u002F>}\n\u003C\u002Fdiv>\n```\n\n---\n\n## 7. Performance Monitoring\n\n### Vercel Analytics\n\n```tsx\n\u002F\u002F app\u002Flayout.tsx\nimport { Analytics } from '@vercel\u002Fanalytics\u002Freact'\nimport { SpeedInsights } from '@vercel\u002Fspeed-insights\u002Fnext'\n\nexport default function Layout({ children }) {\n  return (\n    \u003Chtml>\n      \u003Cbody>\n        {children}\n        \u003CAnalytics \u002F>\n        \u003CSpeedInsights \u002F>\n      \u003C\u002Fbody>\n    \u003C\u002Fhtml>\n  )\n}\n```\n\n### 自定义监控\n\n```typescript\n\u002F\u002F 发送到自己的分析服务\nimport { onLCP, onFID, onCLS } from 'web-vitals'\n\nfunction sendToAnalytics(metric) {\n  fetch('\u002Fapi\u002Fanalytics', {\n    method: 'POST',\n    body: JSON.stringify(metric),\n  })\n}\n\nonLCP(sendToAnalytics)\nonFID(sendToAnalytics)\nonCLS(sendToAnalytics)\n```\n\n---\n\n## 8. Performance Checklist\n\n```markdown\n## 性能优化检查清单\n\n### 加载性能 (LCP)\n- [ ] 关键图片使用 next\u002Fimage + priority\n- [ ] 字体使用 next\u002Ffont\n- [ ] 首屏内容优先加载\n- [ ] 使用 CDN\n\n### 交互性能 (FID\u002FINP)\n- [ ] 减少主线程阻塞\n- [ ] 使用 React.memo 避免重渲染\n- [ ] 长列表虚拟化\n- [ ] 代码分割\n\n### 视觉稳定性 (CLS)\n- [ ] 图片有明确尺寸\n- [ ] 使用 font-display: swap\n- [ ] 动态内容预留空间\n\n### Bundle 优化\n- [ ] 按需导入\n- [ ] 动态导入非关键组件\n- [ ] 替换重型库\n- [ ] 分析 bundle 大小\n\n### 网络优化\n- [ ] 使用缓存策略\n- [ ] 预连接关键域名\n- [ ] 开启压缩\n```\n\n---\n\n## Quick Reference\n\n### Lighthouse 目标\n\n```\nPerformance: > 90\nAccessibility: > 90\nBest Practices: > 90\nSEO: > 90\n```\n\n### 常用命令\n\n```bash\n# 分析 bundle\nANALYZE=true pnpm build\n\n# Lighthouse\nnpx lighthouse https:\u002F\u002Fexample.com\n\n# Bundle 大小\nnpx bundlephobia lodash\n```\n\n### 性能预算\n\n```\nJS Bundle: \u003C 200KB (gzipped)\nFirst Load: \u003C 100KB\nLCP: \u003C 2.5s\nTTI: \u003C 3.5s\n```\n","# Performance Optimizer (性能优化师)\n\n**Goal**: 提升 Web 应用性能，确保良好用户体验和 SEO 表现。\n\n**核心指标**: Core Web Vitals (LCP, FID, CLS)\n\n---\n\n## 1. Core Web Vitals\n\n### 指标标准\n\n| 指标 | 含义 | Good | Needs Improvement | Poor |\n|------|------|------|-------------------|------|\n| **LCP** | 最大内容绘制 | \u003C 2.5s | 2.5s - 4s | > 4s |\n| **FID** | 首次输入延迟 | \u003C 100ms | 100ms - 300ms | > 300ms |\n| **CLS** | 累积布局偏移 | \u003C 0.1 | 0.1 - 0.25 | > 0.25 |\n| **INP** | 交互到下一次绘制 | \u003C 200ms | 200ms - 500ms | > 500ms |\n\n### 测量工具\n\n```bash\n# Lighthouse CLI\nnpx lighthouse https:\u002F\u002Fexample.com --view\n\n# Web Vitals 库\npnpm add web-vitals\n```\n\n```typescript\n\u002F\u002F 监控 Web Vitals\nimport { onLCP, onFID, onCLS, onINP } from 'web-vitals'\n\nonLCP(console.log)\nonFID(console.log)\nonCLS(console.log)\nonINP(console.log)\n```\n\n---\n\n## 2. Next.js Optimizations\n\n### Image 优化\n\n```tsx\n\u002F\u002F ❌ 未优化\n\u003Cimg src=\"\u002Fhero.png\" \u002F>\n\n\u002F\u002F ✅ 使用 next\u002Fimage\nimport Image from 'next\u002Fimage'\n\n\u003CImage\n  src=\"\u002Fhero.png\"\n  width={800}\n  height={400}\n  alt=\"Hero\"\n  priority  \u002F\u002F LCP 图片加 priority\n\u002F>\n```\n\n### Font 优化\n\n```typescript\n\u002F\u002F app\u002Flayout.tsx\nimport { Inter } from 'next\u002Ffont\u002Fgoogle'\n\nconst inter = Inter({\n  subsets: ['latin'],\n  display: 'swap',  \u002F\u002F 避免 FOIT\n  preload: true,\n})\n\nexport default function Layout({ children }) {\n  return (\n    \u003Chtml className={inter.className}>\n      \u003Cbody>{children}\u003C\u002Fbody>\n    \u003C\u002Fhtml>\n  )\n}\n```\n\n### Script 优化\n\n```tsx\nimport Script from 'next\u002Fscript'\n\n\u002F\u002F 非关键脚本延迟加载\n\u003CScript \n  src=\"https:\u002F\u002Fanalytics.com\u002Fscript.js\" \n  strategy=\"lazyOnload\" \n\u002F>\n\n\u002F\u002F 交互后加载\n\u003CScript \n  src=\"https:\u002F\u002Fwidget.com\u002Fchat.js\" \n  strategy=\"afterInteractive\" \n\u002F>\n```\n\n### 动态导入\n\n```tsx\nimport dynamic from 'next\u002Fdynamic'\n\n\u002F\u002F 客户端组件延迟加载\nconst HeavyChart = dynamic(() => import('.\u002FHeavyChart'), {\n  loading: () => \u003CSkeleton \u002F>,\n  ssr: false,\n})\n\n\u002F\u002F 条件导入\nconst AdminPanel = dynamic(() => import('.\u002FAdminPanel'), {\n  loading: () => null,\n})\n\nfunction Page() {\n  return (\n    \u003C>\n      {isAdmin && \u003CAdminPanel \u002F>}\n    \u003C\u002F>\n  )\n}\n```\n\n---\n\n## 3. Bundle Size Optimization\n\n### 分析 Bundle\n\n```bash\n# 安装分析工具\npnpm add -D @next\u002Fbundle-analyzer\n\n# next.config.js\nconst withBundleAnalyzer = require('@next\u002Fbundle-analyzer')({\n  enabled: process.env.ANALYZE === 'true',\n})\n\nmodule.exports = withBundleAnalyzer({\n  \u002F\u002F config\n})\n\n# 运行分析\nANALYZE=true pnpm build\n```\n\n### Tree Shaking\n\n```typescript\n\u002F\u002F ❌ 导入整个库\nimport _ from 'lodash'\n_.debounce(fn, 300)\n\n\u002F\u002F ✅ 按需导入\nimport debounce from 'lodash\u002Fdebounce'\ndebounce(fn, 300)\n\n\u002F\u002F ✅ 或使用 lodash-es\nimport { debounce } from 'lodash-es'\n```\n\n### 替换重型库\n\n| 重型库 | 轻量替代 | 节省 |\n|--------|----------|------|\n| moment.js | date-fns \u002F dayjs | ~95% |\n| lodash | lodash-es + 按需导入 | ~90% |\n| axios | fetch (原生) | 100% |\n| uuid | nanoid | ~75% |\n\n### 代码分割\n\n```tsx\n\u002F\u002F 路由级分割 (Next.js 自动)\n\u002F\u002F app\u002Fdashboard\u002Fpage.tsx → 单独 chunk\n\n\u002F\u002F 组件级分割\nconst Modal = dynamic(() => import('.\u002FModal'))\n\n\u002F\u002F 条件加载\nif (condition) {\n  const module = await import('.\u002Fheavy-module')\n}\n```\n\n---\n\n## 4. React Optimizations\n\n### 避免不必要的重渲染\n\n```tsx\n\u002F\u002F ❌ 每次渲染创建新对象\n\u003CChild style={{ color: 'red' }} \u002F>\n\n\u002F\u002F ✅ 使用 useMemo\nconst style = useMemo(() => ({ color: 'red' }), [])\n\u003CChild style={style} \u002F>\n```\n\n```tsx\n\u002F\u002F ❌ 每次渲染创建新函数\n\u003CButton onClick={() => handleClick(id)} \u002F>\n\n\u002F\u002F ✅ 使用 useCallback\nconst onClick = useCallback(() => handleClick(id), [id])\n\u003CButton onClick={onClick} \u002F>\n```\n\n### React.memo\n\n```tsx\n\u002F\u002F 纯展示组件用 memo\nconst UserCard = memo(function UserCard({ user }) {\n  return \u003Cdiv>{user.name}\u003C\u002Fdiv>\n})\n\n\u002F\u002F 对比函数 (复杂 props)\nconst UserCard = memo(function UserCard({ user }) {\n  return \u003Cdiv>{user.name}\u003C\u002Fdiv>\n}, (prev, next) => prev.user.id === next.user.id)\n```\n\n### 虚拟化长列表\n\n```tsx\nimport { useVirtualizer } from '@tanstack\u002Freact-virtual'\n\nfunction VirtualList({ items }) {\n  const parentRef = useRef(null)\n  \n  const virtualizer = useVirtualizer({\n    count: items.length,\n    getScrollElement: () => parentRef.current,\n    estimateSize: () => 50,\n  })\n\n  return (\n    \u003Cdiv ref={parentRef} style={{ height: '400px', overflow: 'auto' }}>\n      \u003Cdiv style={{ height: virtualizer.getTotalSize() }}>\n        {virtualizer.getVirtualItems().map((virtualItem) => (\n          \u003Cdiv\n            key={virtualItem.key}\n            style={{\n              position: 'absolute',\n              top: virtualItem.start,\n              height: virtualItem.size,\n            }}\n          >\n            {items[virtualItem.index]}\n          \u003C\u002Fdiv>\n        ))}\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n  )\n}\n```\n\n---\n\n## 5. Network Optimizations\n\n### 预加载关键资源\n\n```tsx\n\u002F\u002F app\u002Flayout.tsx\nexport default function Layout() {\n  return (\n    \u003Chtml>\n      \u003Chead>\n        \u003Clink rel=\"preconnect\" href=\"https:\u002F\u002Fapi.openai.com\" \u002F>\n        \u003Clink rel=\"dns-prefetch\" href=\"https:\u002F\u002Ffonts.googleapis.com\" \u002F>\n      \u003C\u002Fhead>\n    \u003C\u002Fhtml>\n  )\n}\n```\n\n### 缓存策略\n\n```typescript\n\u002F\u002F API 缓存头\nexport async function GET() {\n  return Response.json(data, {\n    headers: {\n      'Cache-Control': 'public, max-age=60, stale-while-revalidate=300',\n    },\n  })\n}\n\n\u002F\u002F Next.js fetch 缓存\nconst data = await fetch(url, {\n  next: { revalidate: 60 },  \u002F\u002F ISR\n})\n\n\u002F\u002F React Query 缓存\nconst { data } = useQuery({\n  queryKey: ['users'],\n  queryFn: fetchUsers,\n  staleTime: 60 * 1000,  \u002F\u002F 1 分钟内不重新请求\n})\n```\n\n### 压缩\n\n```javascript\n\u002F\u002F next.config.js\nmodule.exports = {\n  compress: true,  \u002F\u002F 默认开启\n  \n  \u002F\u002F 或使用更高压缩率\n  experimental: {\n    serverActions: {\n      bodySizeLimit: '2mb',\n    },\n  },\n}\n```\n\n---\n\n## 6. CLS Prevention\n\n### 图片尺寸\n\n```tsx\n\u002F\u002F ❌ 无尺寸，导致布局偏移\n\u003Cimg src=\"\u002Fphoto.jpg\" \u002F>\n\n\u002F\u002F ✅ 明确尺寸\n\u003CImage src=\"\u002Fphoto.jpg\" width={400} height={300} alt=\"\" \u002F>\n\n\u002F\u002F ✅ 占位容器\n\u003Cdiv style={{ aspectRatio: '16\u002F9' }}>\n  \u003CImage src=\"\u002Fphoto.jpg\" fill alt=\"\" \u002F>\n\u003C\u002Fdiv>\n```\n\n### 字体加载\n\n```css\n\u002F* 使用 font-display: swap *\u002F\n@font-face {\n  font-family: 'Custom';\n  src: url('\u002Ffont.woff2') format('woff2');\n  font-display: swap;\n}\n```\n\n### 动态内容\n\n```tsx\n\u002F\u002F ❌ 内容插入导致偏移\n{isLoaded && \u003CBanner \u002F>}\n\n\u002F\u002F ✅ 预留空间\n\u003Cdiv style={{ minHeight: '100px' }}>\n  {isLoaded ? \u003CBanner \u002F> : \u003CSkeleton \u002F>}\n\u003C\u002Fdiv>\n```\n\n---\n\n## 7. Performance Monitoring\n\n### Vercel Analytics\n\n```tsx\n\u002F\u002F app\u002Flayout.tsx\nimport { Analytics } from '@vercel\u002Fanalytics\u002Freact'\nimport { SpeedInsights } from '@vercel\u002Fspeed-insights\u002Fnext'\n\nexport default function Layout({ children }) {\n  return (\n    \u003Chtml>\n      \u003Cbody>\n        {children}\n        \u003CAnalytics \u002F>\n        \u003CSpeedInsights \u002F>\n      \u003C\u002Fbody>\n    \u003C\u002Fhtml>\n  )\n}\n```\n\n### 自定义监控\n\n```typescript\n\u002F\u002F 发送到自己的分析服务\nimport { onLCP, onFID, onCLS } from 'web-vitals'\n\nfunction sendToAnalytics(metric) {\n  fetch('\u002Fapi\u002Fanalytics', {\n    method: 'POST',\n    body: JSON.stringify(metric),\n  })\n}\n\nonLCP(sendToAnalytics)\nonFID(sendToAnalytics)\nonCLS(sendToAnalytics)\n```\n\n---\n\n## 8. Performance Checklist\n\n```markdown\n## 性能优化检查清单\n\n### 加载性能 (LCP)\n- [ ] 关键图片使用 next\u002Fimage + priority\n- [ ] 字体使用 next\u002Ffont\n- [ ] 首屏内容优先加载\n- [ ] 使用 CDN\n\n### 交互性能 (FID\u002FINP)\n- [ ] 减少主线程阻塞\n- [ ] 使用 React.memo 避免重渲染\n- [ ] 长列表虚拟化\n- [ ] 代码分割\n\n### 视觉稳定性 (CLS)\n- [ ] 图片有明确尺寸\n- [ ] 使用 font-display: swap\n- [ ] 动态内容预留空间\n\n### Bundle 优化\n- [ ] 按需导入\n- [ ] 动态导入非关键组件\n- [ ] 替换重型库\n- [ ] 分析 bundle 大小\n\n### 网络优化\n- [ ] 使用缓存策略\n- [ ] 预连接关键域名\n- [ ] 开启压缩\n```\n\n---\n\n## Quick Reference\n\n### Lighthouse 目标\n\n```\nPerformance: > 90\nAccessibility: > 90\nBest Practices: > 90\nSEO: > 90\n```\n\n### 常用命令\n\n```bash\n# 分析 bundle\nANALYZE=true pnpm build\n\n# Lighthouse\nnpx lighthouse https:\u002F\u002Fexample.com\n\n# Bundle 大小\nnpx bundlephobia lodash\n```\n\n### 性能预算\n\n```\nJS Bundle: \u003C 200KB (gzipped)\nFirst Load: \u003C 100KB\nLCP: \u003C 2.5s\nTTI: \u003C 3.5s\n```\n",{"name":5,"description":7},"main","4a618da5d2528627c4728e9aab7d602f9d00b649","genes\u002Fperformance-optimizer",1,"https:\u002F\u002Fgithub.com\u002Frotifer-protocol\u002Frotifer-playground","https:\u002F\u002Fgithub.com\u002Frotifer-protocol","https:\u002F\u002Frotifer.dev","Open-source evolution framework for AI agents","2026-11-12 13:46:27",{"source":8,"skillName":5,"commands":57,"prompt":67,"zipAvailable":68},[58,61,64],{"tool":59,"command":60},"npx","npx skills add rotifer-protocol\u002Frotifer-playground --skill performance-optimizer",{"tool":62,"command":63},"bunx","bunx skills add rotifer-protocol\u002Frotifer-playground --skill performance-optimizer",{"tool":65,"command":66},"pnpm","pnpm dlx skills add rotifer-protocol\u002Frotifer-playground --skill performance-optimizer","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Frotifer-protocol\u002Frotifer-playground\u002Fblob\u002Fmain\u002Fgenes\u002Fperformance-optimizer\u002FSKILL.md",true,[70,76,80],{"path":71,"resourceType":72,"resourceTypeDesc":73,"sizeBytes":74,"sourceHtmlUrl":75},".cloud-manifest.json","REFERENCE","参考文档",156,"https:\u002F\u002Fgithub.com\u002Frotifer-protocol\u002Frotifer-playground\u002Fblob\u002Fmain\u002Fgenes\u002Fperformance-optimizer\u002F.cloud-manifest.json",{"path":77,"resourceType":72,"resourceTypeDesc":73,"sizeBytes":78,"sourceHtmlUrl":79},".gene-manifest.json",285,"https:\u002F\u002Fgithub.com\u002Frotifer-protocol\u002Frotifer-playground\u002Fblob\u002Fmain\u002Fgenes\u002Fperformance-optimizer\u002F.gene-manifest.json",{"path":81,"resourceType":72,"resourceTypeDesc":73,"sizeBytes":82,"sourceHtmlUrl":83},"phenotype.json",2416,"https:\u002F\u002Fgithub.com\u002Frotifer-protocol\u002Frotifer-playground\u002Fblob\u002Fmain\u002Fgenes\u002Fperformance-optimizer\u002Fphenotype.json",[85,104,132,162,185,205],{"skillNo":86,"name":87,"nameZh":6,"description":88,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":89,"categories":90,"keywords":96,"publishedAt":42},"01M6H8FTYPK400JGQDW57GM49R","fixture-skill","A synthetic ClawHub skill for wrap --from-clawhub tests","https:\u002F\u002Fgithub.com\u002Frotifer-protocol\u002Frotifer-playground\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fclawhub\u002Ffixture-skill\u002FSKILL.md",[91],{"categoryNo":92,"categoryName":93,"taxonomyType":94,"taxonomyTypeDesc":95},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[97,98,99,100,101,102,103],"fixture","fixture skill","wrap","tests","clawhub","for","synthetic",{"skillNo":105,"name":106,"nameZh":6,"description":107,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":108,"categories":109,"keywords":111,"publishedAt":42},"01M6H8FPX91FF5FH8PPEW7HQSZ","rotifer-self-evolving-agent","Rank an Agent's Rotifer Genes against the Arena and swap in stronger ones, and create and run the local Agents built from those Genes. Invoked explicitly via \u002Fevolve — scan local capabilities, compare Genes, inspect fitness scores, replace weak ones with user approval (each replacement can be rolled back), write an Agent definition into the project (\u002Fevolve create-agent), and execute a local Agent's Genes in the WASM sandbox (\u002Fevolve run-agent). Not for capabilities outside Rotifer.","https:\u002F\u002Fgithub.com\u002Frotifer-protocol\u002Frotifer-playground\u002Fblob\u002Fmain\u002Fskills\u002Frotifer-self-evolving-agent\u002FSKILL.md",[110],{"categoryNo":92,"categoryName":93,"taxonomyType":94,"taxonomyTypeDesc":95},[112,113,114,115,116,117,118,119,120,121,122,123,124,125,102,126,59,127,128,129,130,131],"rotifer self evolving agent","self","self evolving","inspect","local","MCP","access","capabilities","server","run","gene","evolve","network","arena","scan","compare","swap","with","mcp-server","fitness",{"skillNo":133,"name":134,"nameZh":6,"description":135,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":136,"categories":137,"keywords":143,"publishedAt":42},"01M6H8FGNKE933Q2JAAB7JY43V","rotifer-guide","Entry point for Rotifer Protocol. Onboards a user to Rotifer Genes, scaffolds a Gene from a description, diagnoses a Gene's F(g) score or compile failure, searches the Rotifer Gene registry, upgrades a Gene's fidelity from Wrapped to Native, and submits a Gene to the Arena and follows its ranking. It works by proposing `rotifer` CLI commands; the ones that install software, send work to Rotifer's servers, publish a Gene or overwrite files wait for the user's approval. Meant to be invoked explicitly when working with Rotifer, or when unsure which Rotifer capability fits. Its scope is Rotifer Genes and the Rotifer CLI; onboarding, tutorials, troubleshooting or search for anything else are outside it.","https:\u002F\u002Fgithub.com\u002Frotifer-protocol\u002Frotifer-playground\u002Fblob\u002Fmain\u002Fskills\u002Frotifer-guide\u002FSKILL.md",[138],{"categoryNo":139,"categoryName":140,"taxonomyType":141,"taxonomyTypeDesc":142},"01JBSEEDCAT000000000000038","人力资源","PROFESSION","适用职业",[144,145,146,147,148,149,150,122,151,152,102,153,154,22,129,155,156,157,158,159,23,160,161],"rotifer guide","guide","which","scaffolding","search","cli","native","registry","do","compile","general","protocol","troubleshooting","onboarding","rotifer gene","invoke","capability","point",{"skillNo":163,"name":164,"nameZh":6,"description":165,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":166,"categories":167,"keywords":171,"publishedAt":42},"01M6H8FBXGQM2RH27G0S6XMQ34","rotifer-gene","The Gene manual for Rotifer Protocol — write a Gene's express function and phenotype schema, run the four-layer security audit before publishing, and migrate a Gene's fidelity from Wrapped to Hybrid or Native. Invoke explicitly when building, auditing, or upgrading a Rotifer Gene. Do NOT use for general code review, dependency auditing, or framework migration — every procedure here operates on Rotifer Genes, their phenotype schemas, and the Rotifer CLI, and nothing else.","https:\u002F\u002Fgithub.com\u002Frotifer-protocol\u002Frotifer-playground\u002Fblob\u002Fmain\u002Fskills\u002Frotifer-gene\u002FSKILL.md",[168],{"categoryNo":169,"categoryName":170,"taxonomyType":94,"taxonomyTypeDesc":95},"01JBSEEDCAT000000000000007","代码审查",[158,122,152,125,172,102,173,174,154,175,176,177,59,22,118,178,179,180,181,182,183,184,159,23],"security audit","code review","manual","publishing","yes","schema","version","migrate","code","express","review","hybrid","submission",{"skillNo":186,"name":187,"nameZh":6,"description":188,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":189,"categories":190,"keywords":192,"publishedAt":42},"01M6H8F7DZPN54N2AQC32BWEKV","rotifer-arena","Benchmark Rotifer Genes against each other in the Arena — import from ClawHub \u002F local \u002F scratch, compile, match opponents, run Arena evaluation, and produce a Markdown report with F(g) fitness and V(g) security grades. Invoke explicitly to compare or benchmark Rotifer Genes. Do NOT use for general benchmarking, load testing, or comparing anything that is not a Rotifer Gene or Agent.","https:\u002F\u002Fgithub.com\u002Frotifer-protocol\u002Frotifer-playground\u002Fblob\u002Fmain\u002Fskills\u002Frotifer-arena\u002FSKILL.md",[191],{"categoryNo":92,"categoryName":93,"taxonomyType":94,"taxonomyTypeDesc":95},[193,125,152,194,102,153,195,116,154,101,196,22,197,127,129,198,199,200,121,122,158,159,201,202,131,203,204],"rotifer arena","import","testing","produce","load","benchmarking","load testing","markdown","Evaluation","benchmark","security","scratch",{"skillNo":206,"name":207,"nameZh":6,"description":208,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":209,"categories":210,"keywords":212,"publishedAt":42},"01M6H8F0WWXMTDWXQMQYC3PGPW","rotifer-agent","Build a Rotifer Agent from Genes — decompose intent into capability units, pick Genes by Arena F(g), compose a Rotifer Genome, create the Agent and test it. Use when the user is working with Rotifer specifically: \"Rotifer Agent\", \"compose Genes\", \"Rotifer Genome\", \"Gene composition\", \"rotifer agent create\". Do NOT use for general agent frameworks, or when the words Seq \u002F Par \u002F Cond \u002F Try appear as ordinary programming terms — in Rotifer those name Genome composition strategies, and this Skill applies only when the user is composing Rotifer Genes.","https:\u002F\u002Fgithub.com\u002Frotifer-protocol\u002Frotifer-playground\u002Fblob\u002Fmain\u002Fskills\u002Frotifer-agent\u002FSKILL.md",[211],{"categoryNo":92,"categoryName":93,"taxonomyType":94,"taxonomyTypeDesc":95},[213,214,215,216,217,218,219,122,220,221,222,152,125,223,102,224,154,22,225,129,23,226,160],"rotifer agent","Composition","pick","only","create","strategies","intent","seq","decompose","as","compose","frameworks","programming","agent frameworks"]