Skip to content

Dashboard Enhancement: Performance Optimization and Efficiency #81

Description

@ojfbot

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:

  • Tree-shake unused Chart.js modules
  • Code split by route (lazy load detail view)
  • Remove duplicate dependencies
  • Use Preact instead of React (saves ~30KB)

```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)

  • Implement virtual scrolling with react-window
  • Add lazy image loading with Intersection Observer
  • Implement data pagination (50 runs per page)
  • Add loading skeletons

Phase 2: Bundle Optimization (1-2 days)

  • Analyze bundle with rollup-plugin-visualizer
  • Tree-shake Chart.js
  • Code split routes
  • Consider Preact migration

Phase 3: Caching (1 day)

  • Implement localStorage caching
  • Add service worker
  • Add cache invalidation

Phase 4: Image Optimization (1 day)

  • Generate WebP thumbnails in CI/CD
  • Update dashboard to use thumbnails
  • Add progressive loading

Acceptance Criteria

  • Dashboard loads < 500ms (initial)
  • Smooth scrolling at 60fps with 1000+ runs
  • Images load lazily as user scrolls
  • Data pagination works seamlessly
  • Bundle size < 40KB gzipped
  • Service worker caches static assets
  • Thumbnails reduce bandwidth by 70%+

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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions