| name | performance-engineer |
| description | Otimiza performance do CYPHER V3 — bundle size, lazy loading, React rendering, WebSocket, cache |
| version | 2.0 |
| tags | ["performance","bundle","lazy-loading","react","websocket","cache"] |
SKILL: Performance Engineer — CYPHER V3
Targets de Performance
| Métrica | Target | Crítico se |
|---|
| First Load JS | < 300KB | > 500KB |
| Build time | < 60s | > 120s |
| LCP | < 2.5s | > 4s |
| CLS | < 0.1 | > 0.25 |
| API response (cached) | < 200ms | > 500ms |
| API response (fresh) | < 1s | > 3s |
| WebSocket latency | < 100ms | > 500ms |
Análise de Bundle
npm run build 2>&1 | grep "First Load JS"
npm install -g @next/bundle-analyzer
ANALYZE=true npm run build
Lazy Loading Obrigatório
Bibliotecas Pesadas (NUNCA importar diretamente)
import * as tf from '@tensorflow/tfjs'
import ccxt from 'ccxt'
import { Chart } from 'chart.js'
const TensorFlow = dynamic(() => import('@tensorflow/tfjs'), { ssr: false })
async function runMLModel(data: number[]) {
const tf = await import('@tensorflow/tfjs')
}
const TradingChart = dynamic(
() => import('@/components/charts/TradingChart'),
{
ssr: false,
loading: () => <div className="animate-pulse bg-[#1a1a1a] h-64 rounded" />
}
)
async function loadExchange(exchangeId: string) {
const ccxt = await import('ccxt')
const ExchangeClass = ccxt[exchangeId as keyof typeof ccxt]
return new ExchangeClass({ enableRateLimit: true })
}
Componentes Abaixo do Fold
const PortfolioAnalytics = dynamic(() => import('./PortfolioAnalytics'))
const TradingHistory = dynamic(() => import('./TradingHistory'))
const RareSatsGallery = dynamic(() => import('./RareSatsGallery'))
React Performance
Evitar Re-renders Desnecessários
<Component config={{ key: 'value' }} />
const config = useMemo(() => ({ key: 'value' }), [])
<Component config={config} />
const handleClick = useCallback((id: string) => {
}, [])
const ExpensiveList = React.memo(({ items }: { items: Item[] }) => {
return <ul>{items.map(/* ... */)}</ul>
})
React Query Config Otimizado
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 30_000,
gcTime: 5 * 60 * 1000,
retry: 2,
retryDelay: (attempt) => Math.min(1000 * 2 ** attempt, 30000),
refetchOnWindowFocus: false,
refetchOnReconnect: 'always',
},
},
})
Virtualização de Listas Longas
import { useVirtualizer } from '@tanstack/react-virtual'
function OrdinalsList({ items }: { items: Ordinal[] }) {
const parentRef = useRef<HTMLDivElement>(null)
const virtualizer = useVirtualizer({
count: items.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 80,
overscan: 5,
})
return (
<div ref={parentRef} className="h-[600px] overflow-auto">
<div style={{ height: virtualizer.getTotalSize() }}>
{virtualizer.getVirtualItems().map(({ index, start }) => (
<div key={index} style={{ transform: `translateY(${start}px)`, position: 'absolute' }}>
<OrdinalCard item={items[index]} />
</div>
))}
</div>
</div>
)
}
WebSocket Performance
class WebSocketBatcher {
private queue: PriceUpdate[] = []
private flushInterval: NodeJS.Timeout
constructor(private onFlush: (updates: PriceUpdate[]) => void) {
this.flushInterval = setInterval(() => this.flush(), 100)
}
push(update: PriceUpdate) {
this.queue.push(update)
}
private flush() {
if (this.queue.length === 0) return
this.onFlush([...this.queue])
this.queue = []
}
destroy() {
clearInterval(this.flushInterval)
}
}
Redis Cache Strategy
const CACHE_STRATEGY = {
async get<T>(key: string, fetcher: () => Promise<T>, ttl: number): Promise<T> {
const cached = await redis.get(key)
if (cached) return JSON.parse(cached) as T
const fresh = await fetcher()
await redis.setex(key, ttl, JSON.stringify(fresh))
return fresh
}
}
Comandos de Diagnóstico
ANALYZE=true npm run build
npx depcheck
npx lhci autorun --config=lighthouserc.js
node --expose-gc -e "setInterval(() => { gc(); console.log(process.memoryUsage()) }, 5000)" &
npm run dev