Perceived Performance
Принципы
MUST
- Мгновенная обратная связь на любое действие.
- Прогрессивная загрузка данных и UI.
- Плавные переходы между состояниями.
SHOULD
- Использовать optimistic UI там, где это безопасно.
- Показывать skeleton вместо "пусто".
React: useTransition
'use client';
import { useState, useTransition } from 'react';
export function Search() {
const [query, setQuery] = useState('');
const [isPending, startTransition] = useTransition();
return (
<>
<input
value={query}
onChange={(e) => startTransition(() => setQuery(e.target.value))}
/>
{isPending && <Spinner />}
</>
);
}
React: useOptimistic
'use client';
import { useOptimistic } from 'react';
export function LikeButton({ initial }: { initial: number }) {
const [optimisticLikes, addOptimistic] = useOptimistic(initial);
async function onLike() {
addOptimistic((n) => n + 1);
await likeOnServer();
}
return <button onClick={onLike}>Likes: {optimisticLikes}</button>;
}
Next.js (App Router): progressive UI
// app/products/loading.tsx
export default function Loading() {
return <ProductsSkeleton />;
}
Next.js (Pages Router): manual skeleton
export default function ProductsPage() {
const { data, isLoading } = useProducts();
if (isLoading) {
return <ProductsSkeleton />;
}
return <ProductsList items={data} />;
}
Astro: постепенная инициализация
---
import Reviews from '../components/Reviews.jsx';
---
<Reviews client:idle />
Процедуры контроля (Code Review)
Ревьюер должен убедиться, что:
- действия пользователя получают мгновенный отклик
- загрузка не блокирует весь интерфейс
- есть понятные skeleton/placeholder состояния