Галоўная / Артыкулы

Калі мемаізацыя ў React шкодзіць: чаму менш рэндэраў зрабіла праграму павольнейшай

Калі мемаізацыя ў React дае адваротны эфект: memo, useMemo і useCallback дадалі кошт і састарэлыя замыканні на вялікай старонцы. Дапамаглі перанос стану і прафіляванне.

Выдавец: REACTAPP.TOP13 хв чытання2888 слоў

Крыніцы: The React Optimization That Made Our App Slower

Прыцэп пра выправленне няправільнага

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

Заўсёды выкарыстоўваецца стандартны спосаб выправлення. Компаненты абгортваюцца за дапамогою memo, функцыі-обрабнікі — за дапамогою useCallback, вычысленні — за дапамогою useMemo, а селектары абзначаюцца спецыяльнымі функцыямі роўнасці. Компанент, які яшчэ перзапускаецца, абяроўнюецца большым чысцэннем своіх пропсаў. Об’ект, чыя рэферэнцыя зменяецца, стае мемуізаваным. Порэванне, якое не ўдаецца, заменяецца болей глыбокім.

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

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

Што на самай працоўцы значыць „непатрэбнае“

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

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

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

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

Какія насправды ёсць вітраты memo

Людзі часта опісваюць memo як захіст, які не дазволяе дзецявым компонентам паўторна атрыбутаўватыся, калі працэўныя параметры не зменіліся. У такам опісе не паказваецца адны крок: React спачатку павінен порэвануць старыя працэўныя параметры з новымі, перш чым ён зможа чыгнуць чым-небудзь.

За дапамою прымітных атрыбутаў парабяранне ўскладненняў ёсць простым. Калі ж выкарыстоўваюцца шырокія контракты компанентаў, кашты ўскладненняў стае важкім для прыбліжнага адліквідавання. Перадаваліся об’екты рэйкаў, масівы налаштаванняў, модэлі прав, калекцыі калбэкаў і вярнутыя опцыі. Абгортаванне прыймальніка ў memo не стабілізавала жадных з гэтых значэнняў; гэта проста дадаўала ўтварэнне ўтолькі ўжо аднаго ўзлока, дзе React пераканвалася, чы рэальная стабільнасць існуе.

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

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

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

Глыбокае порэвання

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

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

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

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

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

Зберагчыце значэнні

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

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

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

const label = useMemo(
  () => `${firstName} ${lastName}`,
  [firstName, lastName]
);

У часы выканання кэш дадаў практычна нічога, і гэта значыла, што вычысленні маюць настаткі для оптымізацыі. Што горэ, выкарыстоўванне useMemo паўсюду ускладнілае прайом паказання дадзеных. Распрацоўшчыкі падтрымалі стабільнасць кансаўтов об’ектаў не таму, што ўтворэнне такіх об’ектаў было дорогім, а таму, што іншы компоненты, якія былі запам’ятаны, завісілі ад іх ідэнтыфікатораў. Кожная оптымізацыя вымагала ўсё новых, і так ствараўся лес кэшаў, які функцыонаваў толькі тады, калі кожны зв’язак заставался цішчым.

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

Callback’ы і застарэлыя клозуры

Callback’ы, створаныя пад час атрыбутавання, кожны раз атрымліваюць новы ідэнтыфікатор. Калі іх перадаюць запам’ятаным дзецячым компонентам, гэтыя новыя кансаўты спрычыняюць, што порэванні дзецячых компонентаў не выходзяць. Рашэннем было абгортаваць практычна кожны хэндлер у useCallback.

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

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

Лепшы вопыт — чы гэтам дзецяку ўзагалі патрэбны стабільныя калбэк-функцыі. Для дэшавога дзецяка, які не ўрахоўваецца ў мемаізацыі, useCallback даўа мало практычнага рэзультата. Калі калбэк-функцыя вікорыстоўваецца для падпісаў чы дорогіх, мемаізаваных дадзенняў, тады стабільнасць мае значэнне, а ўсе яе залежнасці часта можна скорачыць палягчэннем адпаведальнасці, перадачай болей вузкага спектру операцый чы розмішчэннем коду бліжэй да дадзенняў, якія ён чытае. Функцыя з фіксаваным ідэнтыфікатаром па сваей прыродзе не ёсць быстрэйшай; яна дапамагае толькі тады, калі яна вікорыстоўваецца знову для чагось значыцьвага.

Кэшы вікорыстоўваюць памяць

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

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

Аслівныя проблемы былі ў тым, дзе знаходзіліся станы

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

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

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

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

Менш выкладак, той самы навантажэння на браузер

Нават там, дзе мемаізацыя дазволяла ухіліцца ад выкладакоў у React, інтэрацыі іноды заставаліся медленнымі, таму што React не быў галоўным факторам вітрат.

Бібліятэка для стварэння дыяграм продаваліся рабіць дорогія імператыўныя абнаўленні. Вялікае дрэва DOM все ўсё патрабавала перзначэння распаду, калі зміняліся размеры. Адны з эфектаў CSS вымагалі масовых перрысаванняў, сінхронны запіс у памяць блакаваў галоўную нітку, а працоўнік обработкі вводу парасканаваў вялікі дакумент прытаму, калі ўжо не могла з’явіцца наступная графіка. Компаненты прывернулі ўвагу толькі таму, што іх і мерыў прафайлер, і калі выкладка стала танней, праца браузера за ёю стала відна.

Расыходы React на выконанне — гэта толькі частка расыходаў фронтэнду, а не ўсё, што яго складае. Нават з вікорыстаннем мемаізацыі, змена залежнасці Effect можа прычыніць перзапуск відэнту трэцьяго сторонньага. Пры прыховыцы рэндараўкі роднічага элемента час дэкодавання занадта вялікага зображэння не зменшыцца. Стабільны калебак не пазбавіць ап проблем з лейаутам, якія вынікаюць калі вярнюваныя значэння меры элементаў чытаныя і запісваныя не ў правым парадку. Неабходна праследаваць усі етапы: выконанне JavaScript, рэндарынг у React, мутацыі DOM, вычысленне стылю, формаванне лейауту, атрыбуты paint і сеткавыя запыты, адтолькі што адгуканне аднае з гэтых складовых можа не паўтарыцца ў усім ланцузе. React застаўся тыхім, пакуль браузер продаваў працу.

Код, які важкая змяніць

Расыходы на выконанне былі толькі паловай проблемы. Кроме таго, аплікацыя стала важкая для падтрымкі.

Кожныя межы компанентаў выклікалі новыя запытанні. Чы рэгіструецца компанент у памяці? Калькі пропаў трэбуе стабільных кансаектаў? Чы спецыяльны кампаратар падтрымлівае новы проп? Чы які-небудзь значэнне спецыяльна не было дадзенае ў лісты залежнасцяў? Чы змена структуры аднаго об’екта зробіць недзейнае калькі з кэша? Для стандартной працы над функцыямі трэба было разумець прынцыпы оптымізацыі, якія не мелі нічынага зяўляцца ў прыметах працы продукту.

Уявіце распрацоўшчыка, які дадае поле да об’екта налашчэння і віпадкова спрычыняе масовую перзапісь экрана. Колега „вылечвае“ гэта праблему за дапамогою болей глыбокага кампаратавання. Пазней хтось дадае функцыю да гэтага об’екта і адкрывае, што кампаратар спрыявае аднаковасці двух явна разных налашчэнняў. Код быў налаштаваны пад свою ныяю структуру, і будзь-яя змена наражала на рызык абліквітную сітку кансаектаў і масів залежнасцяў.

Эфектыва архітэктура дозволяе робіць звычныя змены дышэўней і не вымагае, каб кожныя змены паслухаліся схованых прыпускаў кэша. Гэта не значыць, што оптымізаваны код павінен застаўцца простым. Дзеякія даскладныя взаімадзеі дапраўды правяжуць неабходнасць спецыялізаванага мемоізавання і астаточнага керавання канкрэтнымі рэферэнсамі. Складнасць павінна быць прапорцыйнаю фактычнамым выгодам і сфокусаваная на вядомых «гарачых точках», тады калі тут яна была распрастранена паўсюду на адной тэзе, што будзь-які рэндэр можа стаць «гарачай точкай» калі-небудзь.

Аналіз взаімадзеі змяніў рашэнне

Перыядны момент быў аналізам всіх взаімадзеяў корыстніка заместа пільнення колькісці рэндэраў.

Быў запісаны і аналізаваны тыя дзеянні, якія корыстувальнікі адзначылі як повольныя, ўпынку куды паехала вёска часу. Некалькі компанентаў адрасаваліся часта, але практычна не выконвалі нічога. Некалькі вычыслаў і віджэты трэціх сторон домінавалі, а спецыяльныя порэвананні фіксаваліся як справжняя праца JavaScript. У дзеякіх месцах адменшэнне мемаізацыі спрычыніла лягкі адрыхтанне компанентаў, але меншыя загальныя часы.

Спачатку гэта здавалася некорэктным, таму што прыjęтыя уявныя мадэлі спрыймалі меншы колькасць адрыхтанняў як прагрэс. Браузер не пакушаеся, сколькі разоў вызываюцца функцыі компанентаў; яго цікавіць тое, сколькі працы выконваецца пры перадачы наступнага кадру.

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

Што засталося

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

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

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

Атрыбутавання — не вор

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

Мемацыя параганяе вхідныя даны, зберагае значэнні, сочыць за залежнасцямі і должна заставацца правільной праз змены ў кодзе. Аднасобная прыметка роўнасці можа коштаць больш, чым сам працэс выканання. Стабільныя калебэксы могу заморажваць застарэлы стан. Рэзультаты, збераганыя у кэшы, займаюць памяць. А суплетанка оптымаізацый можа зробіць дрэво компонентаў складным для змены без якіх-лібо выгод, якія б зазначылі корыстнікі.

Рэндэраванне ў React часта ўсё ж такі недорога праця. Слабая адпаведальнасць за стан, паўтаральныя дорогі вычысленні, множыцтва падпісаў, абнаўленні ад трэціх сторон і лейаут браузера часта маюць набагато большое значэнне. Найэфектывнейшы спосаб — дазволіць недорогім операцыям застацца недорогімі: перастаць паказваць звычныя компоненты ў кэшах і сфокусавацца на кальколькіх справжна дорогіх операцыях. Оптымізацыя павінна зменшыць загальную вартасць взаімадзея, а не проста колькісць разоў, калі React вызывае функцыю. Швальнасць прыходзіць тады, калі пытанне змініцца з таго, як запобiec рэндэраванню ў React, на тое, чаму кожны апдэйт стаў такім дорогім.

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

  • Чаму фронтэнд стаець складным пасля React: стан, эфекты, межы і інструменты AI — React спрыяе лёгкаму стварэнню інтэрфейсаў, але не ў спрошчэнні ўзглядовага дызайну. Там, дзе знаходзіцца стан, з’яўляюцца заплутаныя эфекты, межы сістэмы і код, створаны AI, і ўсё гэта ёсць справжняя праца над фронтэндам.
  • Дадаць экран запуску да аплікацыі React Native на iOS і Android — Паслядоўныя крокі для налаштавання экрана запуску для React Native на iOS і Android: экран запуску Xcode, тэмы і макеты для Android, а таксама пакет react-native-splash-screen для усунення белага вспышкі.
  • 30 прыкметак для React і Redux для масштабавання і адтрымання фронтэндаў — Трыццаць кораткіх парад на тэму React і Redux, прыменяваных да керавання станам, дадзейнасцю сервера, хуків, сэлектараў, структуры папак, тэставання і рэфакторавання, прызначаных для прыкладнасцей, у якіх колькасць компанентаў перасягае тыячу.