Галоўная / Артыкулы / Основы SSR у React 19.2: Activity, cacheSignal і часткова прадзерабатка (PPR) – поясненне.

Основы SSR у React 19.2: Activity, cacheSignal і часткова прадзерабатка (PPR) – поясненне.

Дазвольце даклэ научыцца, як новы компонент Activity, функцыя cacheSignal і тэхніка частковага прадзерабатвання ў React 19.2 даюць разработчыкам прымітны кантроль над выкарыстоўваннем сервера для прадзерабатвання контэнту.

2240 слоў

Работа над выкарыстоўваннемасцю React зазвычай дзеліцца на два аспекты: прышвыдкенне і оптымізацыя пачатковага сервернага адрасавання і запобежэнне непатрэбнаму адрасаванню на стороне кліента пасля яго запуску. У гэтым артыкуле кожны з аспектаў рассматрывае проблему з працоўна прыгаджаных краяў, але яны спакойна пашчыраняюць адну і тую ж філасофію — што выкарыстоўваннемасць даходзіць за счыткам таго, калі React точна ведае, якія задачы ўажлівы, якія можна адклаць, а якія ўжо ніколі не трэба выканаваць, а не за счыткам дадатковага кэшавання чы аблікованню большай колькасці апаратных ресурсаў. Першая частка прыдзельвана сервернаму адрасаванню і новым прымітівам, якія былі даданы ў React 19.2; другая частка прыдзельвана ўседневным тэхнікам на стороне кліента, якія падтрымліваюць чутлівасць запусканага дапрыемства.

Перэсвядчэнне ў выкарыстоўваннемасці сервернага адрасавання ў React 19.2

Большая частка інструкцыяў па „працэздатнасці SSR“ сводзіцца да нараблэння шароў кэшавання і надзеі на найкращы результат. У той час як React 19.2, выданы ў жаўтні 2025 года, даў вам спецыяльныя прымітівы для безпасэчнага кантролю роботы сервера. Адносленне да гэтага выдання як да незначнай патч-змены значыць пропуск рэальных паўстаноў скорасці — саме деталі, указаны нижэй, насправды вялікі паўтарынь у результатах.

Зберагаюце компоненты жывымі, а не знішчайце іх

Частыя проблемы ў дапрацоўкамах на базе SSR — цэ гэта, калі змена вкладак, ачыненне модальных вікон і переходы межа маршрутаў повнама знішчаюць компоненты, стираючы ўсё іх стан і вымушваючы зноў запрашаць данні. Новы компонент Activity створаны саме для рашэння гэтай проблемы.

// old way — full unmount, state gone, effects re-run
{activeTab === 'analytics' && <AnalyticsPanel />}

// React 19.2 — stays alive, just deprioritized
<Activity mode={activeTab === 'analytics' ? 'visible' : 'hidden'}>
  <AnalyticsPanel />
</Activity>

Зберагчы скрытыя контэнты, React можа падзейсцаваць ўпрымонтаванне таго, што знаходзіцца ў скрытым блаке Activity, яшчэ до таго, як корыстнік нажме на яго. Гэты падход спрыяе значным зменшэнню відчуваемой затрымкі навігацыі на панелях керування з інтэнсyўным SSR, адколі не выканана падзея перазапытку і не відбуваецца зміна лейауту, калі контэнт становіцца видным.

Дазвольце cacheSignal аўтаматычна пракінуць незавершаную роботу

До версіі 19.2, якщо серверная обробка була перарвана на паўпаце — напрыклад, корыстнік перайшоў на іншую сторону або запыт выйшаў за час — жадныя ў процесе запыткі данні і данні, якія былі зберагнутыя, не мелі можнасці дазнацца, што гэтая робота больш не патрэбна. cacheSignal вырашае гэту проблему, даўчы компонентам React Server Components справжні сигнал жыцёвага циклу, які можна викорыстоўваць для пракінування.

async function getUserOrders(userId, { signal }) {
  const res = await fetch(`/api/orders/${userId}`, { signal });
  return res.json();
}

Калі заканчываецца трымкі час кэша, асоўваны сігнал выклікае завершэнне роботы, што запобегае таму, каб залишаныя запиты продавалі CPU на сервере пад час сплескаў навантажэння.

Стварыце статычную шэлку і трансляюць решты

Частковая прадзеявка (PPR) — галоўная фіча SSR у гэтым выласце. Ідея заключаецца у тым, каб аднойчы стварыць статычную шэлку стораніцы — навігацыю, макет, футер — паслужыць яе безпосередна з CDN і трансляваць дынамічныя часткі праз межы Suspense.

<Suspense fallback={<ProductSkeleton />}>
  <PartialPreRender>
    <PersonalizedRecommendations userId={user.id} />
  </PartialPreRender>
</Suspense>

Адзначыце калькі Suspense адночасна

Раней, калі калькольныя межы Suspense рашыліваліся працайна ў аднаковы момент, інтэрфейс могаў страждзець ад «эфекту попкорна»: фрагменты кантэнту з’являліся адны за іншым, а не разам. React 19.2 групавае такія праказы, ўнаследке чаго повадкі кліента і сервера застаюцца аднаковымі, а таксама дадаў падтрымку для Web Streams у Node.js для команд, якім патрэбна болей тонкая кантроль над стрімаваннем.

Этыя API падымаюць стандарт, а не знижаюць яго

Нічыя з гэтых спосабоў не можа заменіць асновы. Вам яшчэ трэба пазбавіцца шаблонаў запрашання дадзеных типу N+1 і разбіць монолітныя пакеты, прычаму толькі тады гэтыя функцыі зможаць вам дапамогчы. React 19.2 не зменшае мінімальную колькасць неабходных работ з оптымаўвання — ён толькі паднімае верхнюю межу швальнасці добра оптымаўванага прыемніка. Таксама варта прачытаць афіцыйныя зместкі выходу React 19.2, а таксама стандартныя настройкі Turbopack, якія былі адкрытыя ў Next.js 16 і чырпаюць добра разам з PPR.

До 2026 года прысвойнасц SSR не стосуецца агрэсіўнейшага кэшавання — яна стосуецца таго, калі React можа чакаць, калі можа стрімаваць дадзеныя і калі можа грацыязна зносіць адказкі. React 19.2 нарэшце даў вам неабходныя засобы для выражэння гэтага.

Парал гэтымі механізмамі, спецыфічнымі для SSR, большая частка таго, што робіць додатак на React швыткім, залежыць ад повсякдзенных прычын, якія застаюцца незалежна ад стратэгіі атрыбутавання і версіі React. Якщо паказваныя раней раздзелы былі прысвечаны стрімінгу, прадзеяўленню і Suspense на боку сервера, то тут рассматрываюцца патэраны на боку кліента, якія дапамагаюць будзь-яму додатку на React застаўацца рэагіруючым у практыцы.

Практычныя методы для павышэння карыстоўнасці React у повсякдзеннай працы

React зазначна эфектываў атрыбутавае за замовчаннем. Адно час аплікацыя расте, і неабавесці пачынаюць накаплівацца непатрэбныя перезначэння, вельмі большыя спісы, занадта великі калібр JavaScript-кода і частыя запыткі да сеті. Для рашэння гэтых проблем рэдка патрабуецца выключныя хітрынкі — калькі дисцыплінованых прычын зазвычай даўнае даходзяць до меты.

Атрыбутаваць толькі тое, што дзеясно патрэбна аднавіць

Кожная перерэндарызацыя выклікае ў React павтарэнне адрысавання к корпусу функцыі компонента. Сама по сабе гэта не ўсегда являецца проблемай — аднак практычныя затраты выклікаюцца тады, калі павтараецца дорогі процес, калі на самай працэ нічаго значыцьнага не змянілася. Штодзе бы не стаўце неканэксуальны статус унутрь компонента, який атрыбуе вялікі частак вашага інтерфейсу, адноўленне гэтага статусу змушвае перерэндарызаваць усю паддрэву разам з ям. Узамест таго дзеліце компоненты, каб адноўленне паўтаралася толькі для той часткі інтерфейсу, якая насправды мае быць пад вплывам. Мета не ў тым, каб узнікла нуль перерэндарызацый, а ў тым, каб усунуць тыя, якія ўтрачаюць час.

Размістайте статус там, дзе яго насправды трэба

Утримваюцеся ад пераносу кожнага элемента статусу на вершыну дрэва компонентаў. Якщо толькі адзін компонент чытае даныя, то самэ гэтам месцу яны і належаць.

function SearchBox() {
  const [query, setQuery] = useState("");

  return (
    <input
      value={query}
      onChange={(e) => setQuery(e.target.value)}
    />
  );
}

Зберагчы стан локальна такім чынам обмежваеся тое, на якую вялічыну можа распрострацівацца апдэйт, што зменшае пасылковыя переробкі інфармацыі ў іншых частях структуры. Як правило, стан трэба размешчаць поблізу компонента, який яго викорыстоўвае, а не вышэй у іерархіі.

Вырахоўвайце значэння заместа ўтримвання іх

Не все паслужыць для зберагчыка useState. Якщо вы вже фіксуеце firstName і lastName, немае прычыны таксама окрема зберагчыць fullName. Неэфектыўная версія выглядае так:

const [fullName, setFullName] = useState("");
useEffect(() => {
  setFullName(`${firstName} ${lastName}`);
}, [firstName, lastName]);

Простыяй спосаб — гэта вырахоўванне значэння пад час рендара:

const fullName = `${firstName} ${lastName}`;

Это пазбавляе нас як дадатковай зменнай стану, так і непатрэбнага Effect. У загальным разе, якщо значэнне можна вырахаваць пад час рендара, яго, верагодна, не трэба зберагчыць у стане.

Караць вялікія лісты без перавантажэння DOM

Адрабатка тыяўкоў у адной час прынадзе быстрая высокія затраты. Уявіце экран чата, які мае 10 000 паведамленняў — няма прычыны, каб усе яны існавалі ў DOM адночасна. Для большых колекцыяў выкорыстоўваюць адна з наступных методаў:

  • Віртуалізацыя
  • Старонаведчасць
  • Бесканечнае прасуванне

Віртуалізацыя зберагае толькі тыя рядкі, якія зараз відображаюцца, плюс невялікі буфер, які ўстановляецца ў паводлі ситуацыі; бібліятэкі, такія як react-window, реалізуюць гэты падход замест нас. Тым не менш, не застаўляйце віртуалізацыю абавязкова — спіс з 50 элементаў практычна навядома не патрэбуе яе.

Адкладзіце завантажэнне коду да момента, калі ён патрэбен

Пользоватары не должны выкананаць завантажэння JavaScript для функцый, якія яны ўсё ўжо не ачынілі. API React lazy і Suspense дазволяюць выдзеліць гэты код з пачатковага пакета:

const Settings = lazy(() => import("./Settings"));

За дапамою гэтага компанент Settings запрашываецца толькі тады, калі ён фактычна атрымліваецца, а не ўключаецца праз першыя завантажэння сторонні. Гэта корыстна для важкіх або рэдка выкарыстоўваных функцыяй — графікаў, рэдагувальнікаў, карт, экранаў налашоўкі, большых панелей керування — і зазвычай спрыяе быстрэйшаму першаму завантажэнню.

Зберагчы інтэрактыўны UI чутлівым пад навантажэнням

Не кожная змяна павінна выконвацца супрацоўна з дзеяннямю пользователя. Поле пошуку павінна мгновенна рэагаваць на натыканне клавіш, нават калі фільтрацыя большага набору дадзеных выканана на меншай прыорітэце на фоне. Хукі React useTransition і useDeferredValue створаны самэ для такога типу компроміса. Абмежэнне часу на прыем дадзеных даходзіць да падобнага рэзультата:

const debouncedSearch = useDebounce(search, 500);

У зьвярзе з тым, каб не адправляць запит на кожны натиск клавішы, трэба чакаць, пакуль корыстнік не зупініцца. Такія падходы ўжыткаваны для полоў пошуку, фільтраў, дужа дзейнароўых спісоў і панелей керування з вельмі большым колам элементаў.

Зменшыць колькасць зайвых сетавых запитоў

Шырока швальнасць — толькі частка проблемы: занадта многа незавершэнных запитоў можу зробіць дапыт повольны, нават якшо сама ўработка дапыту ведзецца быстра. Залежна ад ситуацыі, варта рассмотрзець:

  • Зберагчыць адпаведзі
  • Усунуць дуплікацыю запитоў
  • Разбіць рэзультаты на сторні
  • Зменшыць частоту надсылкі даных у поле пошуку
  • Анулюваць запиты, якія больш не ўжытковы

Якшо корыстнік швабрасна пісае

react
react performance
react performance optimization

верагодна, вы не хачаце, каб тры аддзельныя запиты работалі адразу. Основная прынцып застаецца простым: утримвацца ад таго, каб сеть выканала роботу, якая на самай працы не трэбае.

Адзінакова выкарыстоўваць мемуазыю

React адаптава тры популярныя прыемы мемаізацыі:

  • useMemo зберагае рэзультат вычысленняў у кешы.
  • useCallback зберагае адрэс функцыі між перзапускамі компонента.
  • React.memo можа адмовіцца перзапускать компонент, калі яго пропсы не змяніліся.

Тыповы прыклад:

const filteredUsers = useMemo(() => {
  return users.filter(user =>
    user.name.includes(search)
  );
}, [users, search]);

Але мемаізацыя не ўжо безкоштовна — яна мае свой накладныя витраты і падвышае складнасць асоўнага коду. Яе трэба вжываць тады, калі вычыслення ўпрошаецца, калі компонент постаянна перзапускаецца без прычыны, або калі стабільны адрэс функцыі дзейсна мае значэнне пасля ўсіх наступных крокаў. Не витрачайце зусілля на оптымізацію коду, які не стварае значных проблем.

Дазвольце кампілятору взяць частку роботы

Нявекашнім дадзеннем у інструментальнай лінейцы React є React Compiler, який можа автаматычна застосаваць багато з гэтых оптымаізацый за вас — мемуяваць значэнні, функцыі і компаненты, не трэбаючы пісаць гэта вручную ў кожным случае. Гэта значыць, што вам больш не трэба прагчы да:

useMemo(...)
useCallback(...)
React.memo(...)

Протэму, React Compiler не пазбавляе значэння спачатку пераканацца, чы рэальна проблема з выдатнасцю. Правыя дзеянні — гэта спачатку парадактаваць, што існуе рэальная проблема, падаць на компілятора, каб ён застосаваў усе можлівыя оптымаізацыі, і перайсці да ручнай мемуявання толькі тады, калі є конкрэтныя прычыны.

Даеце React стабільныя ідэнтыфікаторы для работы

Ключы паведамляюць React, калькі элемент у лісте які ён є праз разныя рэндыраванні. Краща атрымваць ключ з стабільнага, унікальнага атрыбута дадзеных, а не з іх пазіцыі:

items.map(item => (
  <Item key={item.id} />
));

Ўважайце, каб не выкорыстоўваць індэкс масівы як ключ, адтакуе ўпорядкуванне, дадаўшчык або выдалення элементаў змінюе кожны індэкс нижэй за точку змены:

items.map((item, index) => (
  <Item key={index} />
));

Стабільны ключ дазволяе React правильна выявіць, якія элементы былі даданы, выдалены або апдэйтаваны, замест таго каб прымусіць програму рабіць вываркі на адпаведнасць пазіцыі. Той жа прынцып застосоўваецца і да об’ектаў і функцый, якія вы пасылайце як пропсы: стварэнне абсалютна новага об’екта або калебэка ў кожны раз, калі відбываецца рендэр, паслабляе цыль мемуізаванага дочынскага компонента, адтакуе пропсы будуць разныя ў кожны раз, нават якщо ніч глыбокага не змянілася.

Знайдзіце рэальную прычыну спаду эфектыўнасці перш чым прыняць рашэнне

Калі вы вже адаптаваліся да гэтых тэхнік, не паследвайце інтуіцыі ў выборы таго, што трэба пасправіць. Ачыніце React DevTools Profiler, каб точна пазначыць, якія компоненты атрыбуеюцца і сколькі часу кожны з іх застаёць. Для проблем, якія стосуюцца не толькі самага React, панель Performance прыбрамоўця можа адкрываць дліткі заведаменні, медленную выконванне скрыптав, дорогія задачы лейауту чы прычыны спамтання атрыбуеў. У зменшэнне на "гэты компонент выглядае медленным", вядзіце за дапамогою гэтых інструментав, каб з’ясаваць, чаму ён такі.

Паказванне, чы правільна была пасправка

Пасля застосавання оптымізацыі зноў перамеряйце рэзультаты, а не проста гадайце, што ўсё заработала. Пераканаўцеся, чы час атрыбуеў дзейсна зменіўся, чы розмер пакета стаў меньшы і чы взаімадзеянні стало адпаведальней. Якшто нічага з гэтага не павысилася, можа, змены ўзагалі не былі неабходныя.

Спіс пераконтрацый пры падачы продукту

Перад выкліканням дапрацоўкі на React, пераканайцеся, чы не адрасаваеце вы интерфейс, які вам не патрэбен, чы стан знаходзится у правильным месцы, чы вы не зберагаеце значэнняя, якія можна было б вырахаваць заместа таго, чы великія спісы обробляюцца эфективна, чы важкі код завантажаецца толькі тады, калі цэя неабходна, чы пошук і взаімадзеяння застаюцца рэагіруючымі, чы вы не адправляеце непатрэбныя запиты API, чы мемаізацыя рашае рэальную проблему, чы компілятор React можа взяць на сябе задачу оптымізацыі, чы вашы ключы ўстойкія, чы вы вимерылі рэальную прычыну затрохкання і чы пасля цьго пераканаліся ў павышэнні каркаснасці.

У падсумку, найкращая оптымізацыя — цэлая, якая не дадае занадто многа коду — а тая, якая прымусвае React виконваць менш непатрэбной роботы.

Спадні матэрыялы

  • Адказанне пра частковай прадзеяве і адночаснай дзеяве — Дазвольце вы дазведацеся, як функцыя частковай прадзеяве у Next.js і функцыя адночаснай дзеяве у React выправляюць проблему медленных прыстроек, дазваляючы фрамворкам планаваць і адправляць задачі замест таго, каб дзеявы былі рассматрываны як адна блакучая елемента.
  • Прыявы TC39 у 2026 годзе: адказанне пра декоратары, Temporal і Signals — Практычны аналіз трох прыяваў TC39 — натыўных декоратароў, API Temporal і Signals — і таго, што яны значаць для разработчыкаў JavaScript і TypeScript у фул-стак-сераўсе.
  • React 19.2: Адказанне пра новым элементам, хукам і методам — Дазвольце дазнацца, як новы элемент Activity, хук useEffectEvent і частковая статычная рэндарызацыя ў React 19.2 скасоўваюць захаваныя проблемы з выдаткамі ресурсаў у сучасных інтерфейсах.