Чаму фронтэнд складаны і пасля React: стан, эфекты, межы і AI-інструменты
React спрасціў стварэнне інтэрфейсаў, але не іх праектаванне. Дзе жыве стан, заблытаныя эфекты, межы сістэм і код ад AI — вось сапраўдная праца фронтэнду.
Крыніцы: React Isn’t the Hardest Part of Frontend Development
Дзеяныя над фронтэндам могу стварыць компонент на React за дваццаць хвілін, а потым пасвяціць наступныя тры гадзіны на выявленне прычын, чаму яго стае немагчымы рэмантаваць. Прычына не ў JSX, не ў useState, і нават не ў самам React. Тое, што робіць работу над фронтэндам складнай, — цэлкам іншыя аспекты: розумеў, як павінен працаваць продукт, выбір месца для зберагчыць стану, коордынацыя асінхронных запытоў, вызначэнне меж компонентоў, рашэнне проблем, прынесеных браузерам, падтрымка доступнасці і шырокаспектнасці інтэрфейсаў, а таксама стварэнне коду, які за паўгода застаецца зрозумелым.
React спрыяў спрошчэнню стварэння інтэрфейсаў. Але ён ніколі не спрыяў спрошчэнню працы над фронтэндам, і галузь занадта давго ведаецца так, нібы гэта можліва.
Што паспелі выправіць React, а што заліць без змян
Даўнае, перш чым з’явіўся React, было іншага роду. Распрацоўшчыкі рэгулярна рэдагавалі DOM вручную і па аднаму прыўязвалі апрацоўшчыкі змян, і ім было важка падтрымваць супараднасць межу экрана і дадзэнняў прыкладнення. Калі прыкладненні станавіліся большымі, стаўаўся ўсё складнейшым выявіць, як дзеянні корыстувальніка, дадзеныя і атрыбуты элементаў адно з іншым вазьмаліся.
React запропанаваў корыстную ментальную мадэль: інтэрфейс — гэта функцыя стану. Уместа таго, каб паказваць браузеру кожную зміну DOM, вы проста опісваеце, як выглядае інтэрфейс для певнага стану. Компаненты встановлівалі межы, пропсы задавалі чыстыя даны, стан выражаў дадзеныя, якія зміняюцца з часам, а дэкларатыўнае атрыбутаванне пазбавляла прыкладнення вельмі большай часткі віпадковай сложнасці. Гэта быў справжні крок уперад.
Адзін раз, фрэймворк рашыяе толькі тыя проблемы, для якіх ён быў створаны. React не мае дзеяння ў тым, чы роўнамерна аплікацыі патрэбны пяць елементаў глобальнага статаусу чы пяцдзесят. Ён не скажа, калі компонент выканае занадта многа задач, чы дызайн вашай API ўсвядомлены, чы індыкаторы загрузкі знаходзяцца у правым месцы, чы працэс платэжа ўсвядомлены пакупцу. І ён абавязкова не можа вырашыць, што павінен рабіць продукт, калі з’ўзек з’явіцца ў момант запуску запіту. Усе гэтыя проблемы таксама належаць да проблем фронтэнду.
Звычная функцыя і рэальнасць
Возьмім простую панель керування. Пользоватэль яе ачынае, аплікацыя запрашае даны, ён зміняе фільтр, рэзультаты апошневаюць, ён выбірае элемент, ачынаеся модальное вікно, ён рэдагуе і зберагае, сервер адпавядае, і панель керування апошневаецца. Ніч гэтага не здаецца складным.
Цяпер прыдзейце тое, што на самай працо выканаецца. Першы запіт не выйшаў. Фільтр змініўся, калі пакуль ў выпалоўцы быў паканейшы запіт, і старэйшая адпаведзь прыйшла пасля новейшай. Модальны аблака ачынілася з глыбокага спяваючага лінку. Староніца аднаавілася пад час рэдагавання. Ачыненыя два вікна. Сесія выйшла з часу. API аддаў частковыя даны. Сервер прыняў змяну, але кліент ніколі не бачыў адпаведы, і корыстнік два разы нажаў кнопку «Зберагчы». У спісе 10 000 радоў, з’яўленне медленнае і праз мобайльны прыстрой, інтэрфейс павінен працаваць з клавіатуры, а паведамленне пра аблуку павінна паведаміць людзям, што яны можаць зрабіць далей.
У такі момант код на React — гэта самая нецікавая частка. Усё гэта можна стварыць за дапамогою React, і усё гэта можна стварыць пасляўску. Багато распрацоўшчыкаў не бачаць гэтай разніцы.
Задача — кераванне складнасцю
Работа распрацоўшчыка фронтэнду не заключаецца главнокаляў у напісанні компанентаў. Гэта — абрабатка складнасці, каб корыстнік бачыў просты элемент, што ў дзесяткі разоў сложнейша. Хорашаўскапрацаваны компанент можа складацца з пяцідзесятых ліній коду, але дабыяцца да пяцідзесятых, а не да пяціхсот, трэба прыйняць рэшэнні ў роўнай меры:
- Звядзе гэтыя даны, хто імі керуе, як дуго яны застаюцца актуальнымі і хто можа іх зменіць
- Што будзе, калі запыт не будзе выкананы
- Чы рэжым павінен застацца актуальным пасля перэходу або апдэйта
- Чы гэта належыць у URL, у локальны рэжым компаненту або ў кэш сервера
- Чы два компаненты должны дзеліцца самымі данымі або проста вырахоўваць схожыя значэнні самостоятэльна
React не адказвае ні на адна з гэтых пытанняў. Распрацоўшчык адказвае, і адказы стаюць ўскладненымі. Слабая рашэнне рэдка калі застаецца толькі ў аднам компоненце. Яно ператвараецца на шаблон, іншы распрацоўшчыкі копіююць яго, і за некалькі часоў у прыкладненні з’яўляецца адносна стабільная архітэктура, якую ніхто ніколі не выбіраў. Самэ так кодбазы фронтэнду становяцца прыкметнымі: рашэнні накапліваюцца, а сложнасць React тут майжэ не павінна выказвацца.
Стан як проблема мадэлявання
Швыдкі спосаб разгледзець незрэлы дызайн фронтэнду — глядзець на яго стан. Актыўнае выкарыстоўванне useState сама по сабе не ёсць правальным. Проблема ў тым, што стан спрыяваць як месца для размешчэння значэнняў, а не як аб’ект, які трэба працаваць за мадэллю. Распрацоўшчык бачыць значэнне, якое змінілася, і вядомае да хука.
const [value, setValue] = useState(...)
Здаецца, ўсё готава, але справжній пытанне — не тое, як зберагчы цяе значэнне. Справжній пытанне — чы рэшта ўзагалі трэба існаваць. Паглядзіце на гэтую тройку:
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const [fullName, setFullName] = useState("");
Зараз трыя кантэксты ў сістэме зберагаюць інфармацыю, якая могла бы быць атрымана з двух. У гэтым случае вінда React не ў чыні. У чыні — ментальная мадэль.
То ж самае выходзіць, калі працюе вяліка колькасць элементаў. Команды зберагаюць адпаведзі API, фільтраваныя копіі гэтых адпаведзяў, пазнакі завантажэння, вырахаваныя колькасці, выбраныя запісі, пазнакі модальных вікон і дублікаты адной ентытэты ў розных месцах. З часам ніхто не можа сказаць, якая копія ёсць автантонічной, і пачынаюць з’являцца багі. Адна складовая зміняе копію, а іншая чытае іншую. Эфект сінхронізаціі прагне ўзравняць іх, а іншы эфект рэагуе на першы. Раптам браузер стае частынай маленькай распрацаванай сістэмы. React не стварыў гэтую архітэктуру, а ўсё гэта зробілі людзі, якія пішлі код.
Эфекты адкрываюць прыроду дызайну
Якшто якая-небудзь функцыя React прыме на сябе большэйшую частку крытыкі, чым іншыя, то гэта useEffect, і такая крытыка часта ўзгодзіцца з рэальнасцю. Але самэўчынкі зазвычай ўскладнююць архітэктурныя проблемы, а не ствараюць іх.
Уявіце компонент, які мае калькі такіх самэўчынкаў: адны з’яўляюць дадзеныя, іншы сінхронізуюць стан, трэці рэагуюць на змяну параметра, чэтырты запішуць даныя у локальную памяць, пяты адправляюць статыстыку, а шосты перазначае значэнні, калі змяніцца певная умова. Кожны з іх сам по сабе здаецца разумным. Але разам яны ствараюць граф са залежнасцямі, які важка адступіць. Распрацоўшчык дадае ўсё больш залежнасцяў, пакуль інструменты для перагляду коду не перэстануць паведамляць проблемы, альбо адменшыць іх, калі самэўчынкі запускаюцца занадта часта, альбо дадае булевы рэф, каб запобiec двойнаму запуску. У канцы канцоў компонент працуе для тэставанага сцэнарыю, але ніхто чытка не разумее прычыны.
Гэта не недагэнак React. Гэта неяснасць у відпаведальнасці і заплутаныя парадуктывныя эфекты, а React проста дае ўсё гэта месца для існавання.
Браузер — гэта адны з вузлоў большага сістэмы
Праца з фронтэндам продовжвае расшырвацца. Сучасныя дапыткі вярбуюцца з API і базамі дадзеных, сістэмамі аутантыкацыі і аналітыкі, а таксама з функцыямі тыпу feature flags, прадаўцамі платэжаў і іншымі сервісамі трэціх сторон. Да гэтага дадаюцца едж-функцыі, серверныя компаненты, задачы, якія выконваюцца у фоне, і, ў усё большай меры, сервісы, якія апыраюцца на ШЫ. Браузер — толькі адны з учаснікаў значна большай сістэмы, таму распрацоўшчыку фронтэнду неабходна разумець не толькі працэс атрыбутавання, але і тое, што відбываецца до і пасля таго, як запіт пакідае стораніцу.
Гэта не значыць, што кожны павінен стаць спецыялістам па бэкэндзе. Гэта значыць, што старая разлінія фронтэнд/бэкэнд становіцца менш корыстной. Людзі, якія не ведаюць HTTP, зрэшты будуць страждзець ад проблем з кэшаваннем. Тыя, хто не знае баз дадзеных, будуць мяркуваць ускладнена пра ўніверсальнасць, а тыя, хто не розумее механізмаў аўтэнтыфікацыі, будуць страждзець ад проблем з працэю сэсій. Умовы супернагонкі і прабавы занова плутаюць распрацоўшчыкаў, якія не маюць адпаведнага досвяду ў розпрацоўцы распраўленых сістэм, а тыя, хто не розумее патрэбаў корыстувачаў, ствараюць элегантныя інтэрфейсы, якія нікому не падабаюцца. Фрэймворк — гэта адна слойва.
Штучны інтэлект змінюе эканаміку, але не складныя аспекты
Падчырнікі коду на базе AI зменілі стоімасць працы над фронтэндам. Стварэнне компанентаў, форм, перакладу дызайну ў JSX, хуків і тэстаў стала дышэўней. Гэта можа здавацца абліканням. Лепша спачатку разглядаць гэта як тэст таго, дзе на самай працоўвалая цэннае. Калі ваша галоўная дапамога — быстрае набіранне коду на JSX, тады AI ёсць проблема. А калі гэта розумэнне сістэм, архітэктуры, прыемнасці продукту, компромісаў і корыстувальнікаў, тады AI змяніць ваш працоўны працэс, залішыць складныя часткі без змян і, верагатна, падвысіць ўпор на яны.
Памочнік можа за секунды стварыць тры правдападобныя версіі функцыі. Выбір між ямі ўжо не стосуецца сынтаксісу, а архітэктуры. Ён можа стварыць сістэму керавання станам, але чы гэты стан павінен быць глобальным? Ён можа напісаць оптымістычны код для апдэйта, але чы прыкладнэе праграма павінна справляцца оптымістычна? Ён можа дадаць кэш, але якая стратэгія анулювання даных? Ён можа напісаць код для рэагавання на змяны, але чы такі код павінен існаваць? Чым быстрэй з’яўляецца код, тым больш значэння мае правільны выбір, і гэта, верагатна, будзе вядомаць працу над фронтэндам прыбліжна на наступныя калькі гадоў.
Адаптаваныя распрацоўшчыкі фронтэнду зазвычай менш думаюць пра React, а больш — пра межы. Яны спытваюцься, дзе лежыць адпаведная адпаведнасць, і з’являюцься, калі компонент ператвараецца ў маленькое прыемленае рашэнне. Яны борацца з дублюваннем стану, плануюць сцэны неудачы ўсё раней, чым наступае успех, знаюць, што на самай працоўнае API гарантуе, і зважаюць на нечаканае паведанне корыстувальніка. Яны можаць адгакнуцца, калі абстракцыя дапамагае, а калі проста маскіруе складнасць. Яны розумеюць прыемленае рашэнне, налагоджуюць яго работу без прытэмнай оптымізацыі усяго, і, галоўнае, можаць паясніць, чаму сістэма працуе так, як працуе. Гэта набагато сложнейшая навык для автаматызацыі, і яна трывае дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўольскі дыяўоль
Распрацоўшчыкі недастаткова обсуждаюць гэта: знанні фрэймворкаў маюць певны тэрмін службы. Знанні API React, апранутыя пяць гадоў тыму, вучорашнія для сённяшняй сітуацыі. Найлепшыя практыкі зміняюцца, бібліятэкі знікаюць, інструменты для стварэння коду перастаюць дапамагаць, стратэгіі відраслівання змінююцца, можлівасці сервераў растуць, а прыходзяць новыя фрэймворкі. Сінтаксіс таксама змінюецца, але основныя інжынерныя проблемы застаюцься дыявольна стабільнымі:
- Мадэляванне стану і перадача дадзеных праз сістэму
- Распакоўка неудач і кераванне асінхроннымі задачамі
- Утрыманне ад непатрэбнага з’еднання
- Стварэнне сістэмы, якая можна спазіраваць, і інтэрфейса, які лёгка доступны
- Контроль за складнасцю
Гэтыя проблемы перазісталі jQuery, Angular і Backbone, а таксама перазісталі раннюю экасістэму React. Яны перазістану і все, што будзе пасля. Таму навчанне фронтэнду выключна праз фрэймворкі — гэта нестабільны план. Навчыцеся фрэймворку, але не плутайце яго з самай дысцыпіной.
Можаць наступнага дня React перастаць быць центрам размов. Ёго можа заменіць што-небудзь іншае, можа існаваць кальколька падходаў адночасна, а можа ён застацца домінуючым набагато дольш часу, чым чакалі. Гэта не так важна. Распрацоўшчыкі, чыя ідэнтычнасць залежыць ад API-ў React, будуць змушаны ўсё перабудаваць, тады калі тыя, хто выучыў, як на самае працуюць інтэрфейсы, прыстосуюцца.
React — гэта інструмент, а не мастацтва
Разработка фронтэнду ніколі не была прыгалоўна прыкладзеная да React. React — гэта дужа хорашы інструмент для стварэння фронтэнд-зялёз, і ён застаецца інструментам. Складная частка — гэта выбір таго, што трэба выразіць: як взаімаюцца разныя элементы, што выходзіць з ладу, дзе знаходзіцца стан, што запускаецца ў браузеры і ў серверы, як сістэма расце разам з продуктам і як спрытна сховаць усё гэта ад таго, хто яго выкарыстоўвае. Гэта і ёсць завада, а JSX — толькі спосаб прызначэння тыпаў для часткі гэтай завады.
Калі інструменты становяцца крашчымі у стварэнні коду, яго стварэнне становіцца менш цінным. Аднак гэта не завершае розрабоцу програмнага забезпечэння, хоць і змінюе тое, пра шта должны думаць разрабы. Людзі, якія можаць быстра стварыць компонент, ўжо і так корыстны, а тыя, якія можаць адначасова ацэніць, чыяму ён патрэбен, — ўжо ўсё болей. То ж самае стосуецца інтэграцый API: стварэнне такога інтэграцыйнага інструменту ёсць корыстным, але выявленне таго, што сам контракт некарэктны, мае ўжо большую цэннаць. Разраб, які можа прабачыць ШЫ перэрабіць кодавую базу, мае ценнасць, а той, хто можа сказаць, чы рэфакторынг павышае карыстнасць сістэмы, — ўжо мае ўсё болей.
Таму ніхто не павінен хварацца з таго, што React стае простэйшым. Гэта і ёсць мета, адколі мэтай фрэймворку ёсць скорачэнне непатрэбнай працы, а апытны разраб выкарыстоўвае заўсёды зэўсвоўваны час на рашэнне справ, якія дзейсна маюць значэнне.
Спадневанае чытанне
- Стварэнне агента ReAct у LangChain: выкананнікі, зошыты для запісаў і ўсі іх меры — Створыце агента ReAct, які выкарыстоўвае інструменты, пазнакоміцеся з тым, як агент і AgentExecutor дзеляць працу, і дазнаецеся, чаму LangGraph лепш справляецца з керуванням прагамам, цыкламі і станам.
- Калі оптымізацыя React пагубна: чаму меншая колькасць перрадароў спрацавала на шкоду працэсу працы дапытку — Як функцыі memo, useMemo і useCallback прызвелі да зростання вартасці выканання і паўстання бягаў у большай сторонцы на React, і чаму перанесенне стану і аналіз усіх взаімадзеянаў выправілі гэту сітуацыю.