Перейти к основному содержимому

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 состояния