Skip to main content

performance-optimization

React re-render optimization, Three.js rendering performance, useMemo/useCallback, bundle size, 60 fps profiling, Lighthouse budgets

معلومات المصدر

المستودع
Hack23/game
آخر نشاط في المصدر
١٧ أبريل ٢٠٢٦ في ١٤:٠٥
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
١٣
التفرعات
٥

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
performance-optimization
description
React re-render optimization, Three.js rendering performance, useMemo/useCallback, bundle size, 60 fps profiling, Lighthouse budgets
license
MIT
# Performance Optimization Skill ## Context Applies when building performance-sensitive features, optimizing re-renders, reducing draw calls, minimizing bundle size, fixing memory leaks, profiling bottlenecks, or implementing game loops. ## Rules 1. **60 fps target** — 16.67 ms per frame max in game rendering 2. **Minimize re-renders** — `React.memo`, `useMemo`, `useCallback` used deliberately after profiling 3. **Refs for 60 Hz mutations** — never `useState` for per-frame updates 4. **Batch draw calls** — group similar geometries/materials in Three.js 5. **InstancedMesh** for > 10 similar objects (particles, enemies, bullets) 6. **Optimize geometry** — low polycounts; LOD for distant objects; frustum culling 7. **Lazy-load assets** — textures/models/sounds on demand; preload only critical 8. **Code-split** — dynamic `import()` by route/feature; `React.lazy` + `Suspense` 9. **Memoize expensive calculations** — `useMemo` with stable deps 10. **Debounce/throttle** resize, scroll, input handlers 11. **Profile first** — React DevTools Profiler + Chrome Performance + Spector.js before optimizing 12. **Bundle budget** — < 500 KB gzipped initial load (matches `budget.json`) 13. **Tree-shake** — import individual symbols, not whole modules 14. **Audio**: reuse Howler instances; unload unused sounds 15. **Memory**: dispose Three.js resources on unmount; break ref cycles ## Lighthouse Budget (aligned with `budget.json`) | Metric | Target | |---|---| | Performance score | ≥ 90 | | LCP | < 2.5 s | | TTI | < 3.5 s | | CLS | < 0.1 | | Initial JS gzipped | < 500 KB | ## Examples ### ✅ Memoized leaf component ```tsx import { memo, useCallback, useMemo } from 'react'; interface HUDProps { score: number; health: number; onPause: () => void; } function GameHUDInner({ score, health, onPause }: HUDProps): JSX.Element { const healthColor = useMemo(() => (health > 50 ? '#0f0' : '#f00'), [health]); const handlePause = useCallback(() => onPause(), [onPause]); return ( <div className="hud"> <span>Score: {score}</span> <span style={{ color: healthColor }}>Health: {health}%</span> <button onClick={handlePause}>Pause</button> </div> ); } export const GameHUD = memo(GameHUDInner); ``` ### ✅ Ref-based animation — zero re-renders ```tsx import { useRef } from 'react'; import { useFrame } from '@react-three/fiber'; import * as THREE from 'three'; function Spinner(): JSX.Element { const mesh = useRef<THREE.Mesh>(null); useFrame((_, delta) => { if (mesh.current) mesh.current.rotation.y += delta; }); return <mesh ref={mesh}><boxGeometry /><meshStandardMaterial /></mesh>; } ``` ### ✅ Stable references outside render ```tsx const ORIGIN = [0, 0, 0] as const; function At(): JSX.Element { return <mesh position={ORIGIN}><sphereGeometry /></mesh>; } ``` ### ✅ Code-splitting a heavy overlay ```tsx import { lazy, Suspense } from 'react'; const HelpOverlay = lazy(() => import('./HelpOverlay')); function App(): JSX.Element { return ( <Suspense fallback={null}> <HelpOverlay /> </Suspense> ); } ``` ### ❌ Anti-Patterns ```tsx // BAD: useState in useFrame — 60 re-renders/sec useFrame(() => setRotation(r => r + 0.01)); // BAD: new object every render <mesh position={[0, 0, 0]}>…</mesh> // BAD: unmemoized expensive calc inside render const sorted = data.sort((a, b) => a - b); // BAD: importing entire lodash import _ from 'lodash'; // BAD: forgetting to dispose geometry / material / texture ``` ## Profiling Workflow 1. **Measure before** — React Profiler (component renders), Performance panel (frame times), Spector.js (draw calls) 2. **Identify** the hottest component or the longest task 3. **Hypothesize** (re-render? layout thrash? draw calls? allocation?) 4. **Change one thing** and re-measure 5. **Record evidence** in the PR (screenshots, numbers, flamegraphs) ## Memory-Leak Patterns - Forgotten `setInterval` / subscriptions → cleanup in `useEffect` return - Undisposed `THREE.Geometry` / `Material` / `Texture` → dispose on unmount - Global event listeners → `removeEventListener` in cleanup - Closures capturing large data → `useRef` or restructure ## Validation Checklist - [ ] Profile shows no regression (or documented acceptable trade-off) - [ ] No `useState` in `useFrame`; 60 Hz updates use refs - [ ] `InstancedMesh` used for > 10 similar objects - [ ] Three.js resources disposed on unmount - [ ] Bundle within budget (`budget.json`) after changes - [ ] Lighthouse score ≥ 90 for changed paths - [ ] No memory leak in 5-minute soak test (DevTools Memory)
عرض على GitHub