Overview
Optimize dashboard performance for large datasets and improve data loading efficiency.
Goal: Handle 1000+ test runs with smooth performance and fast initial load times.
Performance Targets
| Metric |
Current |
Target |
Improvement |
| Initial Load |
~1s |
< 500ms |
2x faster |
| Screenshot Load |
Eager |
Lazy |
On-demand |
| List Render |
All |
Virtual |
10x+ faster |
| Data Transfer |
Full |
Paginated |
Bandwidth savings |
| Bundle Size |
50KB |
< 40KB |
20% smaller |
Features
1. Virtual Scrolling (Priority: High)
Problem: Rendering 1000+ test cards tanks performance
Solution: Only render visible cards using virtual scrolling
```typescript
import { FixedSizeList } from 'react-window';
export function TestListVirtualized({ runs }: Props) {
return (
{({ index, style }) => (
)}
);
}
```
Expected: 60fps scrolling even with 10,000+ runs
2. Lazy Image Loading (Priority: High)
Problem: Loading all screenshots at once is slow
Solution: Use Intersection Observer for lazy loading
```typescript
export function LazyImage({ src, alt }: Props) {
const [isVisible, setIsVisible] = useState(false);
const imgRef = useRef(null);
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setIsVisible(true);
observer.disconnect();
}
},
{ threshold: 0.1 }
);
if (imgRef.current) {
observer.observe(imgRef.current);
}
return () => observer.disconnect();
}, []);
return (
<img
ref={imgRef}
src={isVisible ? src : undefined}
alt={alt}
loading="lazy"
/>
);
}
```
3. Data Pagination (Priority: High)
Problem: Loading entire index.json (1000+ runs) is slow
Solution: Implement server-side pagination
Index Structure:
```json
{
"totalRuns": 1000,
"pages": {
"1": "/data/index/page-1.json",
"2": "/data/index/page-2.json",
...
},
"latest": [ /* First 50 runs */ ]
}
```
API:
```typescript
async function loadTestRuns(page: number = 1): Promise<TestRun[]> {
const index = await fetch('/data/index.json');
const pageUrl = index.pages[page];
return fetch(pageUrl);
}
```
4. Bundle Optimization (Priority: Medium)
Current bundle analysis:
- react-vendor: 141KB (45KB gzipped)
- chart-vendor: 1KB (0.6KB gzipped)
- app code: 14KB (4KB gzipped)
Optimizations:
```typescript
// Code splitting
const TestRunDetail = lazy(() => import('./components/TestRunDetail'));
function App() {
return (
<Suspense fallback={}>
);
}
```
5. Caching Strategy (Priority: Medium)
Service Worker for offline support:
```typescript
// sw.js
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((response) => {
return response || fetch(event.request);
})
);
});
// Cache: index.json, manifests (TTL: 1 hour)
// Network-first: screenshots
```
localStorage caching:
- Cache index.json for 15 minutes
- Cache manifests for 1 hour
- Clear on manual refresh
6. Image Optimization (Priority: Medium)
Screenshot compression:
- Current: PNG (lossless, large)
- Proposed: WebP (lossy, 30-50% smaller)
Thumbnail generation:
- Create 200x150px thumbnails
- Full size on click
- Saves bandwidth on list view
Implementation:
```bash
During CI/CD:
convert screenshot.png -resize 200x150 thumbnail.webp
```
Implementation Plan
Phase 1: Core Performance (2-3 days)
Phase 2: Bundle Optimization (1-2 days)
Phase 3: Caching (1 day)
Phase 4: Image Optimization (1 day)
Acceptance Criteria
Technical Notes
Dependencies to add:
- react-window (virtual scrolling)
- workbox-webpack-plugin (service worker)
Monitoring:
- Use Lighthouse for performance audits
- Track Core Web Vitals (LCP, FID, CLS)
- Monitor bundle size in CI/CD
Part of #71 (Visual Regression Testing Pipeline)
Follows #76 (GitHub Pages Dashboard)
Overview
Optimize dashboard performance for large datasets and improve data loading efficiency.
Goal: Handle 1000+ test runs with smooth performance and fast initial load times.
Performance Targets
Features
1. Virtual Scrolling (Priority: High)
Problem: Rendering 1000+ test cards tanks performance
Solution: Only render visible cards using virtual scrolling
```typescript
import { FixedSizeList } from 'react-window';
export function TestListVirtualized({ runs }: Props) {
return (
{({ index, style }) => (
)}
);
}
```
Expected: 60fps scrolling even with 10,000+ runs
2. Lazy Image Loading (Priority: High)
Problem: Loading all screenshots at once is slow
Solution: Use Intersection Observer for lazy loading
```typescript
export function LazyImage({ src, alt }: Props) {
const [isVisible, setIsVisible] = useState(false);
const imgRef = useRef(null);
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setIsVisible(true);
observer.disconnect();
}
},
{ threshold: 0.1 }
);
}, []);
return (
<img
ref={imgRef}
src={isVisible ? src : undefined}
alt={alt}
loading="lazy"
/>
);
}
```
3. Data Pagination (Priority: High)
Problem: Loading entire index.json (1000+ runs) is slow
Solution: Implement server-side pagination
Index Structure:
```json
{
"totalRuns": 1000,
"pages": {
"1": "/data/index/page-1.json",
"2": "/data/index/page-2.json",
...
},
"latest": [ /* First 50 runs */ ]
}
```
API:
```typescript
async function loadTestRuns(page: number = 1): Promise<TestRun[]> {
const index = await fetch('/data/index.json');
const pageUrl = index.pages[page];
return fetch(pageUrl);
}
```
4. Bundle Optimization (Priority: Medium)
Current bundle analysis:
Optimizations:
```typescript
// Code splitting
const TestRunDetail = lazy(() => import('./components/TestRunDetail'));
function App() {
return (
<Suspense fallback={}>
);
}
```
5. Caching Strategy (Priority: Medium)
Service Worker for offline support:
```typescript
// sw.js
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((response) => {
return response || fetch(event.request);
})
);
});
// Cache: index.json, manifests (TTL: 1 hour)
// Network-first: screenshots
```
localStorage caching:
6. Image Optimization (Priority: Medium)
Screenshot compression:
Thumbnail generation:
Implementation:
```bash
During CI/CD:
convert screenshot.png -resize 200x150 thumbnail.webp
```
Implementation Plan
Phase 1: Core Performance (2-3 days)
Phase 2: Bundle Optimization (1-2 days)
Phase 3: Caching (1 day)
Phase 4: Image Optimization (1 day)
Acceptance Criteria
Technical Notes
Dependencies to add:
Monitoring:
Part of #71 (Visual Regression Testing Pipeline)
Follows #76 (GitHub Pages Dashboard)