# Streaming UI Patterns: Progressive Loading für moderne Web-Apps
**Meta-Description:** Design Patterns für Streaming UI mit React Suspense. Skeleton Loading, Progressive Enhancement und optimale User Experience bei langsamen Daten.
**Keywords:** Streaming UI, Suspense, Skeleton Loading, Progressive Loading, React Streaming, SSR Streaming, Loading States
---
## Einführung
Streaming UI bedeutet: **Zeige sofort was du hast, streame den Rest nach**. Statt einer leeren Seite oder einem Spinner sieht der User sofort Inhalte – während langsame Daten im Hintergrund laden.
---
## Das Streaming-Prinzip
```
┌─────────────────────────────────────────────────────────────┐
│ STREAMING VS. BLOCKING │
├─────────────────────────────────────────────────────────────┤
│ │
│ Blocking (Traditionell): │
│ ┌────────────────────────────────────────────────────┐ │
│ │ [Spinner 3s] → [Komplette Seite] │ │
│ └────────────────────────────────────────────────────┘ │
│ User wartet 3 Sekunden auf irgendetwas │
│ │
│ Streaming (Modern): │
│ ┌────────────────────────────────────────────────────┐ │
│ │ [Header] ─ sofort │ │
│ │ [Nav] ─ sofort │ │
│ │ [Hero] ─ 100ms │ │
│ │ [Stats] ─ [Skeleton] → [Daten] ─ 500ms │ │
│ │ [Chart] ─ [Skeleton] → [Daten] ─ 1s │ │
│ │ [Table] ─ [Skeleton] → [Daten] ─ 2s │ │
│ │ [Footer] ─ sofort │ │
│ └────────────────────────────────────────────────────┘ │
│ User sieht sofort Inhalte, Details laden progressiv │
│ │
└─────────────────────────────────────────────────────────────┘
```
---
## Pattern 1: Suspense Boundaries
### Strategische Platzierung
```tsx
// app/dashboard/page.tsx
import { Suspense } from 'react';
export default function DashboardPage() {
return (
{/* Sofort gerendert - keine Suspense */}
{/* Schnelle Daten */}
}>
{/* Mittlere Latenz - unabhängig voneinander */}
}>
}>
{/* Langsame Daten - lädt zuletzt */}
}>
{/* Statisch */}
);
}
```
### Nested Suspense für feinere Kontrolle
```tsx
function ProductSection() {
return (
}>
{/* Nested: Reviews laden nach Produkten */}
}>
);
}
```
---
## Pattern 2: Skeleton Components
### Anatomy-preserving Skeletons
```tsx
// components/skeletons/ProductCardSkeleton.tsx
export function ProductCardSkeleton() {
return (
{/* Bild */}
{/* Titel */}
{/* Beschreibung */}
{/* Preis + Button */}
);
}
// Grid Skeleton
export function ProductGridSkeleton({ count = 6 }) {
return (
{Array.from({ length: count }).map((_, i) => (
))}
);
}
```
### Shimmer Effect
```css
/* styles/skeleton.css */
.skeleton-shimmer {
background: linear-gradient(
90deg,
#f0f0f0 25%,
#e0e0e0 50%,
#f0f0f0 75%
);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
}
@keyframes shimmer {
0% {
background-position: 200% 0;
}
100% {
background-position: -200% 0;
}
}
```
```tsx
// Skeleton mit Shimmer
export function ShimmerSkeleton({ className }: { className: string }) {
return ;
}
```
---
## Pattern 3: Optimistic Updates
### Sofortige UI-Reaktion
```tsx
'use client';
import { useOptimistic, useTransition } from 'react';
import { addToFavorites } from './actions';
function FavoriteButton({ productId, initialFavorited }) {
const [isPending, startTransition] = useTransition();
// Optimistic State
const [optimisticFavorited, addOptimistic] = useOptimistic(
initialFavorited,
(current, newValue: boolean) => newValue
);
const handleClick = () => {
// Sofort UI updaten
addOptimistic(!optimisticFavorited);
// Server-Action im Hintergrund
startTransition(async () => {
await addToFavorites(productId, !optimisticFavorited);
});
};
return (
);
}
```
---
## Pattern 4: Loading Hierarchies
### loading.tsx für Route-Level
```tsx
// app/products/loading.tsx
export default function ProductsLoading() {
return (
{/* Header ist statisch */}
{/* Filter Bar Skeleton */}
{/* Product Grid Skeleton */}
);
}
```
### Hierarchische Loading States
```tsx
// Layout mit persistentem Skeleton
export default function ProductsLayout({
children
}: {
children: React.ReactNode
}) {
return (
{/* Immer sichtbar */}
{/* Content lädt */}
{children}
);
}
```
---
## Pattern 5: Streaming mit LLM
### AI-Response Streaming UI
```tsx
'use client';
import { useStreamingChat } from '@/hooks/useStreamingChat';
function ChatInterface() {
const { response, isStreaming, sendMessage } = useStreamingChat();
const [input, setInput] = useState('');
return (
{/* Streaming Response */}
{(response || isStreaming) && (
{response}
{isStreaming && (
)}
)}
);
}
```
### Partial Content während Streaming
```tsx
function AIAnalysisCard() {
const { analysis, isAnalyzing, sections } = useAIAnalysis();
return (
{/* Sections erscheinen progressiv */}
{sections.map((section, i) => (
{section.title}
{section.loaded ? (
{section.content}
) : (
)}
))}
{isAnalyzing && (
Analysiere... {sections.filter(s => s.loaded).length}/{sections.length}
)}
);
}
```
---
## Pattern 6: Error Boundaries mit Fallback
```tsx
// components/ErrorBoundary.tsx
'use client';
import { useEffect } from 'react';
export function ErrorBoundary({
error,
reset
}: {
error: Error;
reset: () => void;
}) {
useEffect(() => {
console.error('Error:', error);
}, [error]);
return (
Etwas ist schiefgelaufen
{error.message}
);
}
// error.tsx für Route-Level
export default function ProductsError({
error,
reset
}: {
error: Error;
reset: () => void;
}) {
return ;
}
```
---
## Performance-Metriken
| Metrik | Blocking | Streaming | Verbesserung |
|--------|----------|-----------|--------------|
| **FCP** | 3.2s | 0.8s | 75% schneller |
| **LCP** | 3.5s | 1.2s | 66% schneller |
| **TTI** | 4.0s | 2.0s | 50% schneller |
| **CLS** | 0.15 | 0.02 | 87% besser |
---
## Best Practices
### Do's
```tsx
// ✅ Unabhängige Suspense Boundaries
}>
}>
// ✅ Skeleton passt zur echten Komponente
}>
// ✅ Static Content außerhalb von Suspense
{/* Kein Suspense nötig */}
{/* Kein Suspense nötig */}
```
### Don'ts
```tsx
// ❌ Eine große Suspense für alles
}>
// ❌ Generischer Spinner statt Skeleton
}>
// ❌ Suspense um statischen Content
```
---
## Fazit
Streaming UI Patterns verbessern UX dramatisch:
1. **Sofortige Inhalte**: User sieht nie eine leere Seite
2. **Progressive Loading**: Wichtiges zuerst, Details später
3. **Perceived Performance**: App fühlt sich schneller an
4. **Resilience**: Langsame Teile blockieren nicht den Rest
Die Zukunft ist nicht "Laden oder Geladen" – es ist ein Spektrum.
---
## Bildprompts
1. "Website loading progressively in sections, waterfall effect, UI/UX concept"
2. "Skeleton screens transforming into real content, animation sequence"
3. "User happily browsing while content streams in background, modern web experience"
---
## Quellen
- [React Suspense Documentation](https://react.dev/reference/react/Suspense)
- [Next.js Loading UI](https://nextjs.org/docs/app/building-your-application/routing/loading-ui-and-streaming)
- [Vercel: Streaming SSR](https://vercel.com/blog/streaming-server-rendering-with-suspense)
- [Web.dev: Skeleton Screens](https://web.dev/articles/skeleton-screens)