Стан URL, стан сервера і BFF: каскад Vite для внутрашніх додатакаў на React
Чаму аутентыфікованая внутршняя платформа на React може краща працаваць з Vite, TanStack Router, TanStack Query і окольным BFF, чым з Next.js, і калі гэта перестае быць правдой.
Крыніцы: Next.js is excellent. That’s exactly why you **shouldn’t** use it everywhere.
Калі пачынаецца новы проект на React, на запитанне «Чы гэта трэба использоваць Next.js?» зазвычай адпавядаюць «так», яшчэ перш чым хто-небудзь описае сам прыемлак. Для публічных сайтаў з великай колькасцю контэнту такая падходзь часта ўсуне. Аднак для платформы для аператывных задач, дзе корыстувальнікі весь час фільтруюць табелі і рэдагуюць данныя пасля абмовкі, багато з найсильнейшых функцыяй гэтага фрэймворку рашаюць проблемы, якіх у самам прыемлаку няма. У гэтым артыкуле расказваецца пра архітэктуру, якая на самай працоўцы трэбуе такой платформе, паказваецца, як компонуемы набор React, Vite, TanStack Router, TanStack Query і backend-for-frontend (BFF) падходзіць да ўсьго гэтага, і заканчваецца чарточкай для выбору, калі Next.js нарэшце будзе лепшым выборам.
Няма нічога, што падкрывае тэзу, чы что Next.js ў слабай форме. Це адны з найлепшых фреймворкаў React, якія існуюць. Аргументы спрыводзяцца проты ўжытку яго за замовчаннем, без пераканальствася, чы яго можлівасці падходзяць да выканання задакоў.
Конкрэтны сценарый
Разглядзім маленькую команду з пяці інжынераў, якія ствараюць внутршняю платформу з болейш чым 100 маршрутаў, болейш чым 300 точаках API і прыблізна мільйонам запытанняў API на месцы. Яны моглі бы стварыць яе з Next.js. Узамест таго яны выбралі React з Vite, TanStack Router для маршрутацыі, TanStack Query для обробкі дадзеных і окалічны BFF межы фронтэндам і бэкэнд-сервісамі. Чырэх месцаў пасля пачатку роботы гэты выбор застаецца актуальным, не таму, што Next.js не падыходзіў, а таму, што платформа ледве задзейнаецца ў тых сферах, дзе Next.js выказвае высокія якосці.
Для болей шырокага паяравання двух падходаў для разных типаў проектаў, адзірніце Next.js або просты React: падбіранне фрэймворку па вашаму проекту. Акцэнт тут болей вузкі: што патрэбна аплікацыі, якая працуе з большай колькасцю дадзэнняў і мае аутентыкацыю, з кожнага слоя.
Апісайце аплікацыю пры выборы фрэймворку
Next.js стаў стандартным рашэнням, таму што ён аб’едначае так много функцыяй: маршрутызацыю і лэйауты на адной заснове файлоў, SSR і Server Components, слой кэшавання, мідлвары, код бэкенду ў аднам проекте, оптымізаваныя зображэння і велікую экасистему. Для багато продуктов такое аб’едначэнне ўсёг яе ідеальна. Аднак болей корыстным першым пытаннем є тое, які тип аплікацыі вы ствараеце. Две аплікацыі на React можуць практычна не мятць нічага спаканнага з точкі зору архітектуры.
Публічны інтерфейс
Тыповая публічная інтернет-магазіна мае:
- тыячы сторанак, якіе можа адкрыць кожны
- трафік, які прыходзіць з пошуковых сэрвісаў
- практычныя трэбаванні SEO
- сторанкі продуктам, калі контэнт якіх павыгадвае ад обробкі на серверы
- URL-адрысы, якія можна паводзіць, і аператыўныя прэвью ў соціальных меражах
- большая частка статычнага або медленна змінююцагася контэнту
Внутршняя платформа для аператыў
Внутршній інструмент зазвычай мае:
- практычна кожны экран пасля автанацыі
- пошук кляўэнтав, фільтры і таблы з паградуваннем
- формы, панелі керавання і перакрычэння прав
- частыя змены і даны майже у рэальны час
- вялікі об’ём стану сервера
- высока інтэрактыўная інтарфейс
- шар API або BFF, які вялікай меры ўжо існуе
Оба являюцься дапытамі на React, але яны рашаюць разныя проблемы, і архітектура павинна гэта відбіваць.
Корыстувальнікі керуюць дапамогай, а не проста чытаюцы яе
На внутрэнней платформе пользователя прыходзіць у систему і працуе ў програме весь дзень. Ён не прайшоў з рэзультата пошуку, не чытае стацыю і не пераглядае спіс продуктав. Ён ведае пошук, фільтруе, сортавае, ачынае дыялогі, падае формы, зменяе данні, пераключаеся между вкладкамі, праскаквае па табліцах, апавярожнюе данні і пераходзіць между супакойнымі елементамі. Ён запускае програму, а не адвіцяюцца на веб-сайт, і гэта змена праблематызуе, якія функцыі фрэймворка є важлівымі.
SEO больш не ўваходзіць у прыямоўкі
Вазьміце маршрут на кшталт /customers/12345, які паказвае запис абонента, які прыняў автанацію, з чулымі дадзеннямі. Вы яшчэ больш не хачаце, каб пошуковыя системы індексавалі яго. Не ёсць патрэбы, каб краблеры яго знаходзілі, і не патрэбна, каб першы HTML-адказ быў прыемным для краблероў. Старонка ценная таму, што з яёю взаімаецца аўтарызаваны корыстнік, а не таму, што яе можна знайсці. Аднойчы з галоўных прычын выбору Next.js таму мае малая значымасць. Гэта несупаданне трэбаванняў, а не недагоднасць фреймворку.
Дзе падходяць серверныя компаненты, а дзе — ні
Серверныя компаненты ўсё-такі ёсць практычна корыстным модэлем, таму гэта пытанне заслуговае на адказ. Уявіце старонку керавання абонентамі з калькама роздзелаў:
Customer
├── Profile
├── Loans
├── Payments
├── Transactions
├── Documents
└── Activity
Як толькі старонка заваносится, корыстнік пачынае яе меняць. Напрыклад, ён фільтруе спіс платэжаў:
Status: Failed
Type: ACH
Date: Last 30 days
Потым яны переглядаюць сторні, сортаваюць, шукаюць, пачынаюць транзакцыю і рэдагуюць якісь данні. Відображэнне постаўна зменяецца пад вплывам дадзенаў корыстніка і новых дадзенняў сэрвера. Домінантны патэрн — гэта не цыкл у стылі дакумента:
Request → Render document → Read document
Гэта больш супамінае цыкл взаімадзеяў:
User interaction
↓
Application state
↓
Server state
↓
API
↓
Updated UI
Чым больш вашы экраны налягаюць на другі дыяграм, тым больш архітектура кліента вялічыць якасць: як зберагаецца стан, як кэшуюцься данні і як UI реагуе на змяны. Компаненты сэрвера все ўсё можу атрыбутаваць часткі такой сторні, але гэта не пазбавляе нас патрэбы ў моцным шаре дадзенняў на боку кліента.
Адносленне да URL як да стану прыемлівання
Падазроўваю, што корыстнік аперацый знаходзіцца на вікні з платамі кліента:
/customer/12345/payments
Яны застаўляюць набор фільтраў:
status=failed
type=ach
amountMin=500
page=2
Якщо гэтыя фільтры закодаваны ў адресе, URL стае такім:
/customer/12345/payments
?status=failed
&type=ach
&amountMin=500
&page=2
У такі моменты URL не ўсьмо толькі засоб для навігацыі; ён являе сабою частку стану прыкладнення. Адны інжынер можа пераклацці яго своему колеге, і той потрапляе на таго ж кліента, у тую ж вкладку, з тымі ж фільтрамі і на тую ж сторунку рэзультатаў. Ён таксама застаецца пасля перзавантажэння і змушвае кнопку «Назад» працаваць так, як чакаюць корыстувальнікі. Толькі правильна реалізацыя гэтага на багацько экранаў і є прычыной, чаму рутэр з падтрымкай типаў становіць сабою неабходнасць.
Што дагаўляе TanStack Router
TanStack Router спрэцыявае рутаванне як важлівую частку дизайну. Маршруты, параметры шляха і параметры пошуку можна выразіць у системе типаў, што мае значэнне, калі прыкладнення мае больш чым сто маршрутаў. Пры такой колькасці рутаванне вже не ўсьмо проста «які компонент будзе атрыбутаваны тут»; гэта частка архітектуры. Для маршруту на канцэ парады:
/customer/$customerId/payments
Вы хочаце:
- чыста апісаныя, типаваныя параметры шляха
Важна зазначыць, што нічога з гэтага не залежыць ад таго, чы рэндаруецца сторанка на сервере. Для внутранняй аплікацыі, якая цэлкам працуе ў браузеры, гэта ідеальна падходжанне.
Стан сервера — гэта справжняя важылка
Большая частка большай внутранняй аплікацыі стосуецца не столькі сторанак, сколькі даўняых дадзеных. Энтыты, якія вона постаўляе і запісвае, выглядаюць так:
Customers
Loans
Payments
Transactions
Documents
Users
Accounts
Reports
Для кожнага з іх фронтэнд должен адпаведзець на тыя ж пытанні:
- Чы гэтыя дадзеныя вже ў памяці?
- Чы яны сталі застарэлымі?
- Чы трэба іх зноў запрашаць, і калі?
Это і є калектываванне стану сервера, і самэ гэта ёсць проблема, для якой створаны TanStack Query: кэш, ключаваны запитамі, фонова перзапрашоўка, адмыванне ідэнтычных запитоў, хукі мутацый і цялевая анулявання. Калі рутэр керуе станам URL, а Query — станом сервера, кожны слой мае чыстаю адпаведальнасць, а стан локальных компонентоў скарачваецца да практычна локальных пытанняў інтэрфейса, такіх як чы відкрыты дыялог.
Заліквідаванне BFF як межы API
У такій схеме фронтэнд не запошчае дзесяткі мікросервісаў безпасяродна. Ён вялічыцца з BFF, які у свою чаргу вялічыцца з сервісамі. Такое раздзеленне не дазволяе фронтэнду знаць пра деталі реалізацыі бэкенду, уключаючы тое, чы рэспанс складаецца з адного сервіса чы з пяці. BFF керуе контрактом API.
Гэта таксама дапамагае стварыць чыстую структуру размешчэння. Фронтэнд — це статычныя ресурсы, якія выдаюцца з CDN чы статычнага хоста:
Frontend
↓
CDN / static hosting
тады калі BFF працюе як самастоятельны сервіс перад мікросервісамі:
BFF
↓
Microservices
Кожную частыню можна ствараць і запускать незалежна. Next.js абсалютна можа быть размешчаная празаўсёды разам з BFF. Справжній пытанне — чы роўнасабліва ваша фронтэнд-фрамворк таксама павінна выступаць як серверны межа. Калі ў організацыі вялікі час уже існуе бэкенд-шар, який забезпечвае гэтую межу, дадаць другі шар унутры фронтэнд-фрамворка прыводзіць да дуплікацыі адпаведнасцяў.
Аутэнтыкацыя застаецца на серверной стороне
Процес аутэнтыкацыі таксама паследуе гэтае раздзеленне. Пользователь нажымае «Увайсі» і пераправляецца на Okta. Пасля успешнага заходжання адбываецца калебак, які падае на бэкенд, який зберагае токен доступу на серверной стороне, а Redis адпаведна керуе збераганнем сесій. Браузер проста зберагае ідэнтыфікатор сесіі ў захіщанай куку. Канцэптуальна:
Browser
│
│ Sign in
▼
Okta
│
│ Callback
▼
BFF / Backend
│
▼
Redis
Рэакт-дзялоў не ёсць там, дзе знаходзіцца архітектура аутантыкацыі; яго задача — кераваць продуктам, тады как BFF абавяраеся безпекай і контрактам API. Корыстны пасляэфект — токены доступу ніколі не прабрацоўваюцца ў JavaScript браузера, што зменшае вплыв баго XSS. Выкананне гэтага ўнутрь Next.js не ёсць прыродна горшым, але калі такая архітектура вялікі час вучыцца ў організацыі, яе заставленне праза фронтэндам ёсць простым і ясным.
Так, Next.js можа зрабіць усё гэта
Ён можа. Вы можете стварыць дзялоў з Next.js, выкарыстоўваючы кліентскія компаненты, ў яму можна выкарыстоўваць TanStack Query, налаштавіць аутантыкацыю, пад’ясніць яе да BFF і разместіць як хочаце. Магчымасці не ёсць проблемай. Кращы вопыт — гэта, насколькі з фреймворку вы на самай працоўваце. Якщо большая частка дзялова будзе выглядаць так:
'use client'
↓
Client-side interactions
↓
API calls
↓
TanStack Query
Тады варта на момент зупініцца і запытацца, чы рэштаеўнікі сяроджонка сервера прабачаюць выбіранне Next.js як межы вашай аплікацыі, з усімі яе стандартамі, часам выконання і можлівасцямі апдэйта.
Кожны элемент складовай структуры мае свою задачу
Для такіх аплікацый разумны стандартны набор – React, Vite, TanStack Router і TanStack Query, а таксама BFF. Оось не значыць проста склеюванне бібліятакаў пакуль вы випадкова не створыце сабе сопны фрэймворк. Кожны элемент мае чыста визначаную ролю:
- Vite забезпечвае інструменты для кампіляцыі та сервер развіцця.
- React атрыбуе інтерфейс.
- TanStack Router керуе маршрутацыяй і станам URL.
- TanStack Query керуе станом на серверы.
- BFF являе сабою межу API та безпекі.
Паколькі адпаведальнасці чыста визначаныя, вы можете заменіць адну частку без неабяжна перэосмысленняў всей аплікацыі.
Недзеянкі з таго, калі не выкарыстоўваць Next.js
Композабельныя маршруты маюць своія наследкі. Вы тырчыце можлівасць выкарыстоўваць готавыя рашэння і самі прымайце рашэнні, якія зазвычай выкарыстоўвае Next.js: структуру проекта, правілы роздзелення коду, спосаб, яким статычны хост обрабоцвае маршруты з боку кліента, а таксама неабходнасць супяроўнавання колькіх бібліятэкаў адразу. Таксама можу змяніцца і спектар трэбаванняў. Якщо пазней палова дапрацоўкі будзе трэбавацца зробіць публічной, а SEO стане важлівым, Next.js стае значна прываблівей. Тое ж сама паслужыць прычыной, якщо вам трэбае сутэйна обробка на серверы або стварэнне статычных версіяў, якщо серверныя компаненты дадаюць рэальную ценнасць вашаму дизайну, або якщо вы насправды хочаце, каб код фронтэнда і сервера быў намерна з’едынены ў адной дапрацоўцы. Таму рашэнне не ў тым, "Next.js чы React", а ў тым, якая архітектура падходзіць для данай дапрацоўкі.
Спіс пунктав для выбору
Перад тым, як прыняць рашэнне, разглядзіце наступныя пытанні:
- Чы гэны ўжоць мае значны адкрытыя інтэфейсы? Гэта сильная сторона Next.js.
- Чы важна SEO? Next.js становіцца ўсё прываблівей.
- Чы вам патрэбна обработка на сервере чы статычная генерацыя? У гэтым таксама виграе Next.js.
- Чы Server Components чы Server Actions можа сутэйна паспрыяць пакращэнню дизайна? Тады трэба серьёзна рассмотріць Next.js.
- Чы ўжоць пераважна аутентифікуецца і є высока інтэрактыўнасць? Кращэ выбраць React з Vite.
- Чы організацыя вже выкарыстоўвае шар BFF чы API? Вартуе рассмотрзець самастоятельны кліентскі ўжоць, які размешчаецца окрема.
- Чы стан сервера ёсьць главным проблемам? TanStack Query становіцца дужа прываблівым выборам.
- Чы стан URL і складная маршрутазацыя є ключовымі аспектамі? TanStack Router таксама становіцца дужа прываблівым выборам.
З гэтых адказоў выліваецца простая правіла-памятка. Калі аплікацыя мае значны публічны інтерфейс, трэба серйозна рассмотрыць варыянт Next.js. Калі ж аплікацыя пераважна аутентифікуеся, боўш чым усё — цэна ўнутранняя або адміністратыўная платформа, трэба запускаться з React і Vite, дадаючы толькі тыя элементы, якія неабходны. Ні адна з гэтых стакоў не є кращай у загальным сенсе; адна з іх болей падходзіць для конкрэтнай задачы, а гэтае разлічэнне лёгка забываецца, калі фреймворк становіцца стандартным рашэнням.
Заключанне
Найлепшая архітектура — гэта не тая, якая мае самы дзьвінкі список функцый, а тая, чыя функцыйны рашаюць проблемы, якія у вас насправдзе ёсць. Для інструмента для аператыў, які працюе праз входзенне і мае сэрвысны шар, значны стан сервера, інтэнсыўныя взаімадзеі і мінімум публічнага кантэнту, React з Vite, TanStack Router і TanStack Query — гэта не компроміс; гэта свядомы выбор.
- Спачатку класіфікуюце прыемлень: сайт з адміністрацыйным кантэнтам чы робітка, якая выконвае аутентыкацыю.
- URL і данні сервера лячуце двума галоўными істочнікамі стану, і для кожнага з іх трэба выдзеліць спецыяльны інструмент.
- Зберагачуце межы безпекі і API там, дзе ў вашай організацыі яны вялікі.
- Перазглянуце гэта рашэнне, якщо публічныя старонкі, SEO чы рэндэраванне на сервере стануць рэальнымі трэбованнямі.