З Бриджа да JSI: як выбраць час для перайшчыня да новай архітэктуры React Native
Як JSI, Fabric і TurboModules заменяюць стары мост React Native, што на практыцы означаюць адзінаванне, яке фіксуецца, і як безпечна аудытаваць і мігруваць існуючыя дапраўкі.
Крыніцы: React Native’s New Architecture Finally Stopped Being a Compromise
Кожны, хто калі-небудзь выкладваў не простую аплікацыю на React Native па старай архітэктуры, бачыл, як швайнае прасуванне спінавалася ў той момент, калі поток JavaScript пачынаў займаться чымось іншым, напрыклад, парсаваў адпаведзь з сеті чыста перадаваў змяну стану через вялікую дрэво-структуру компонентаў. Гэты спін не быў некаштальком; гэта была прымусовая наследка таго, як функціонаваў стары мост. Новая архітэктура, якая яго заменяе, ўжо з React Native 0.76 стала стандартной, але ўпрынцы паўнае часу багато командаў сцягнулі ёе на пазнейшы момент. У этай статыцэ поясняецца, што саме змінілася ў трох складовых Новай архітэктуры, як расумець тыя тверджэння пра ўрабоцкую спроможнась, і як вяскаваць, чы і як перайсці на новую архітэктуру для існуючай аплікацыі.
Чаму стары мост спрычыняў проблемы з прасуванням
У архітектуре паказанага типу кожная взаімадзейнасць между JavaScript і натыўным кодам адбывалася через асінхронны мост. Званне серыязавалася у формат JSON, ставілася ў чергу на мосты, дэсерыязавалася на стороне натыўнага коду і там выкананая, пры чым рэзультаты вярталіся там жа. З гэтага дизайну вывыходзяць два наследкі: кожная взаімадзейнасць коштавала за серыязаванне, а таксама, паколькі мост быў асінхронным і упорядкованым, кожна операцыя, якая мела працаваць з натыўным кодам, была вынушана чакаць, калі нитка JavaScript была зайнята. Таму зайнятая нітка JavaScript спамошчала прасуванне, форматаванне і жесты, якія залежалі ад нее.
Альтернатыва існуе ў якой-небудзь форме вялікі час, і з версіі 0.76 яна офіцыйна стала стандартной. Аднак быць стандартным і тым, на чым адзінчалавая команда будзе робіць ставку для продакшн-проекта, — гэта разныя рэчы. Выпускі першай паловы ў гэтым году, React Native 0.85, а пасля Expo SDK 56, шырока вважаюцца моментамі, калі гэты прыемак быў закрыты; деталях пісней.
Тры складовыя Новай архітектуры
Якшто не браць у расчытанне маркетынг, Новая архітектура складаецца з трох компонентаў, якія працуюць разам, кожны з яых заменяе конкрэтную частку «моста».
JSI: прымітныя вызовы заместо паведамленняў
Інтэрфейс JavaScript (JSI) являецца аднойчынай падставой. Цэх лёгкі інтэрфейс на C++, праз які JavaScript можа зберагаць кансэкты да натыўных об’ектаў і безпасяродна вызываць натыўныя функцыі, укладаючыся ў сінхронную роботу, калі гэта дапамагае. Не існуе серыявання JSON, ні калэндара для мосту, ні асінхронных перадзванаў для вызываў, якім гэта не патрэбна. Стары спосаб серыявання, калэндаравання, дезерыявання і распадзелу прыводзіць да таго, што па суты ёст калкі вызыв функцыі на C++.
Fabric: спяльны C++ „тэневы“ дрэв
Fabric — это система адрасавання, створаная на базе JSI. Яна адрасаваець раздзеляецца на трыя слоі: дрэво React fiber у JavaScript, «дрэва сеня» і дрэва аднатуральных відображэнняя хоста. Ключовая разліка закладзена ў тым, што «дрэва сеня» тепер знаходзяцца ў спільным коде на C++, а не працюе через мост з JavaScript. Распалоўка з адной дапамогай Yoga выраховвана ў гэтым спільным слоі, таму даныя пра распалоўку больш не пераводзяцца через мост.
Fabric таксама ёсьць тым, што дазволяе функцыям React, якія працуюць паралельна, такім как переходы, Suspense і useTransition, працаваць у React Native. Етап зберагання змян можа выконввацца сінхронна або паралельна, а рендэрар, заснованы на мосту, не меў можлівасці належна падтрымаць жаданы режым. Якщо ваша команда хоча паводлівае паралельнае адрасаванне, якое вона выкарыстоўвае ў інтэрнете, Fabric являецца неабходным умовай, а не оптымаізацыяй.
TurboModules: ледзь запускаемыя, типаваныя аднатуральныя модулі
TurboModules заменяюць застарэлую систему NativeModules для доступу да вялікодушных функцыяй. У цым афарызе прагледваюцца два падходы. У старым спосабе імпорт запоўнюе модуль з NativeModules, якія ініцыяваліся ў момент запуску і падлегалі расэрыяванню з кожным вызывам. Новы спосаб імпорту запоўнюе модуль, створаны на аднойчынных спефікацыях, падтрымваны JSI, ініцыяваліся толькі праз першы выкарыстоўванне і могуць быць вызваны сінхронна, калі гэта дапаможліва.
// Old NativeModules: loaded eagerly at startup, whether used or not,
// with every call paying the bridge's serialization cost
import { NativeModules } from 'react-native';
const { CameraModule } = NativeModules;
// TurboModules: JSI-backed, lazily loaded only when actually called,
// with type-safe interfaces generated by Codegen from your spec
import CameraModule from './specs/NativeCameraModule';
CameraModule.capturePhoto(); // direct, synchronous-capable call via JSI
Акцыя ленівага завантажэння мае большое значэнне, чым можа здавацца на першы погляд. У старых системах пры запуску дапрыгі, які мелі багато натыўных модуляў, падлегалі витратах на ініцыялізацыю кожнага з іх, нават якща пад час данай сесіі большасць з іх не выкарыстоўвалася. TurboModules платаюць толькі тады, калі модуль фактычна выкарыстоўваецца. Тыпаваная спэсыфікацыя — гэта другая частка прынадзей: Codegen ператварае яе на натыўныя інтэрфейсы, пра што дакладна пісана ў нашай статыце пра тое, чаму Codegen змушае спачатку ствараць спэсыфікацыю для TurboModules.
Актыўнае чытанне твароў пра выдатнасць
Чысыры, якія наводзяцца для Новай архітектуры, разлічаюцца залежна ад джерела та навантажэння, таму трэба спрыяглядаць на яе як на напрамак, а не як на конкрэтную цыфру, якая можа быць даная заўзятым сторонам. Уключаныя у звіты рэзультаты:
- прыблызна 10–30% лепшая працэсаваемасць UI-адраснай ниткі для стандартных прыкладоў практык, да 3 раза лепшая для прыкладоў практык, якія сильна выкарыстоўваюць натыўныя модулі
- на 20–50% быстрэйшыя вызовы з JavaScript у натыўны код
- на 20–40% корачэйшы час запуску, залежна ад таго, сколькі натыўных модулів ў прыкладе практык і якія операцыі вы мерзіце
Более корыстным показнікам, чым будь-які абсалютны процэнт, ўважаюцца тые катагоріі дапытак, якія перайшлі з категоріі «можна з варыянтамі» у категорію «выпанае проста». Дапытакі, якія активна выкарыстоўваюць камеру, візуалізацыя дадзэнняў у рэальны час, складныя анімаваныя інтерфейсы і ўсё, што выклікае патрэбу у працэсе вимеры лейауту ў сінхронным режыме, або трэбавалі сложных архітектурных рашэнняў, або ўзагалі не былі практычнымі. У новай архітектуре гэта стаў звычным інжынерным завданнем. Якщо ваш дапытак належыць да адной з гэтых катагорый, праблема міграцыі є супэрнатывная, незалежна ад сярэжных показнікаў; якщо ён пераважна складаецца з форм і спісаў, выгоды будуць рэальнымі, але менш значнымі. Якія-толькі показнікі должны каналізаваць вашае рашэнне — гэтыя, якія вы вимерыў у своем дапытаку до і пасля.
Што было выправлена ў пачатковым цыкле выданняў
Прычына, чаму гэты год вважаецца перакантным моментам, — не новыя можлівасці, а сэт карэктураў, прызначаных для рашэння конкрэтных проблем, якія змусілі аўтарывы чакаць. Для точных дапамогаў адзірніце офіцыяльныя зьвесткі пра выласць, адкуль падсумак нижэй ўзяты з газетаў, напісаных у час падготовкі тэксту.
- React Native 0.85, выданы ў красавіку, перабудаваў сістэму анімацый і усунуў давгачасны фактар падвяшвання кадраў. Паведамляецца, што пераходы з актыўнай анімацыяй на большасці падтрымваных прыстроёў дахоўваюць 60 кадраў за секунду, а не паслабляюцься пад навантажэнням.
Міграцыя на практыке: спачатку аудыт залежнасцяў
Усё гэта не значыць, што кожны існуючы дапыток павінен перайсці завтра. Няўыважлівы пункт, які трэба пераканацца перед тым, как здзейсніць змены, — це сумяжнасць бібліятак. На момент напісання, як паведамляецца, адо 85% популярных пакетаў React Native npm падтрымліваюць Новую архітектуру, тады як прыблізна 15% падтрымліваюць толькі моставыя рашэння або ў частковай меры. Міграцыі, якія застаюцься на месцы, практычна завжды застрэліваюцься саме ў гэтым залишку: не ў самай рамцы, а ў кальколькі трэціх-сторонніх натыўных модуляў, ад якіх залежыць дапыток.
Такія законамернасці ўспэшна пераходзячых на новую архітектуру командах:
- Аудыт пры пачатку. Спісавайце всіх натыўных залежнасцяў і пераканаўцеся, чы рэалізавана ў іх ныяй архітектуры падтрымка ў дапрацоўкі, якая є, а не тая, яку вы памятаеце з праз годзіну-две. Для кожнага пакета, які не падтрымваецца, выберыце: апгрэйдаваць яго, заменіць, стварыць свой варыянт чы самі ўпакаваць яго.
- Актуальваецеся за дапамогою Codegen. Колькі Codegen стварае інтэрфейсы на натыўным роўні з абавесцю пра типы на базе вашых спефікацый у TypeScript чы JavaScript, весь клас несувязоў межа JavaScript і натыўным кодам выкрываецца ў момент будавання, а не стварае крахі пад час выконання. Якщо вы пішаце сабе модулі, наша інструкцыя па падключэнню Turbo Module ў дапрацоўку за дапамогою Codegen паказвае весь процес.
Кансалтация ў залежнасці ад ситуацыі
Пачатак новага проекту
Няма значных прычын ухіліцца ад цього. Новая архітектура є стандартной, усе супутні інструменты, у тым лічыцца Expo SDK 56, прыпускаюць, што вы вжо на яй работаеце, а розніця ў сумаспадобнасці зараз настолькі мала, што вы вельмі малая верасць станесце на перакос, як толькі прыладзеўка не мае незвычных натыўных залежнасцей.
Падтрымка прыладзеўкі на старой архітектуры
Пачаткайце з аудыту сумяшчальнасці, пры тым выкарыстоўваючы ваш справжніяй список залежнасцей, прычаму не чапаючыся за нішто іншае. Частка сумяшчальных пакетаў стабільна расте, таму адлік з праз год, верагатывацельна, ўжо застарэў. Планавайце пошаговую міграцыю і спрыймайце бяды, якія выяўляе Codegen, як справжню захоцу падчас пераходу, а не як формальнасць.
Команды, якія адмацавалі ўсё гэта раней і западлівалі
Пахамованне на 2023 чы ў 2024 год было разумным рашэннем з уважанняю да тадышніх проблем. Перабудова анімэйшнаў і выправленні прасачання памяці ў версіі 0.85 адпаведаюць самэ проблемам стабільнасці, якія былі праблемай для чакання, таму гэты цыкл выданняў ёсць правільны момент, каб знову рассмотрыць гэты пытанне.
Ключовыя выводы
- Сяродні мосты серыязавалі кожны вызов і ставілі яго ў чергу пасля зайнятага потока JavaScript; самэ гэта, а не некашлёвае стацыя, было прычыной большай часткі історычных проблемаў з работай.
- JSI адмацавае прымітныя вызовы, Fabric пераносіць „цэнтральную дрэву структуры“ і макет у спяльны код на C++ і дазваляе паралельную работу React, а TurboModules завантажваюцца захоўна з типаваных спефікацый.
- Разлік у швальнасці ў разных сцэнарыях вельмі вялік; прымаюце рашэнне на адной з асноваў — катагорыі вашай прыкладнай програмы і сасобаў власных замероў.
- Няўялося змян у функцыях, а толькі ў стабільнасці і інструментах: надзеянасць анімацый, працаванне памяці працоўнай сесыі і швальнасць складання.
- Рызык міграцыі крыўдзіцца у сторонніх натыўных модулях, таму спачатку перагледзіце залежнасці, паверніцеся да Codegen і пераносіце по аднам экрану чы модулю за раз.