de Nayeem Reza

Cum să identificați și să rezolvați randările irosite în React

Cum sa identificati si sa rezolvati randarile irosite in React

Așadar, recent m-am gândit la profilarea performanței unei aplicații react la care lucram și m-am gândit brusc să stabilesc câteva valori de performanță. Și am dat peste faptul că primul lucru pe care trebuie să-l abordez este randuri irosite O fac în fiecare dintre paginile web. S-ar putea să vă gândiți la ce sunt randările irosite de altfel? Hai să ne scufundăm.

De la început, React a schimbat întreaga filozofie a construirii de aplicații web și, ulterior, modul de gândire al dezvoltatorilor front-end. Odată cu introducerea sa DOM virtual, React face ca actualizările UI să fie cât mai eficiente. Acest lucru face ca experiența aplicației web să fie îngrijită. V-ați întrebat vreodată cum să vă faceți aplicațiile React mai rapide? De ce aplicațiile web React de dimensiuni moderate tind să funcționeze slab? Problemele stau în modul în care folosim de fapt React!

Cum funcționează React

O bibliotecă modernă de tip front-end Reacţiona nu face ca aplicația noastră să fie mai rapidă în mod minunat. În primul rând, noi dezvoltatorii ar trebui să înțelegem cum funcționează React. Cum trăiesc componentele prin ciclurile de viață ale componentelor în durata de viață a aplicațiilor? Deci, înainte de a ne scufunda în orice tehnică de optimizare, trebuie să avem o mai bună înțelegere a modului în care React funcționează de fapt sub capotă.

La baza React, avem sintaxa JSX și capacitatea puternică a React de a construi și compara DOM-uri virtuale. De la lansare, React a influențat multe alte biblioteci front-end. De exemplu, Vue.js se bazează și pe ideea de DOM-uri virtuale.

Fiecare aplicație React începe cu o componentă rădăcină. Ne putem gândi la întreaga aplicație ca la o formație de copac în care fiecare nod este o componentă. Componentele din React sunt „funcții” care redau interfața de utilizare bazată pe date. Asta inseamna recuzită și stat primește; spune că este CF

UI = CF(data)

Utilizatorii interacționează cu interfața de utilizare și provoacă schimbarea datelor. Interacțiunile sunt orice poate face un utilizator în aplicația noastră. De exemplu, făcând clic pe un buton, glisând imaginile, glisând elementele din listă și solicitările AJAX care invocă API-urile. Toate acele interacțiuni schimbă doar datele. Nu provoacă niciodată schimbări în interfața de utilizare.

Aici, datele sunt tot ceea ce definește stat a unei cereri. Nu doar ceea ce am stocat în baza noastră de date. Chiar și diferite stări front-end, cum ar fi fila care este selectată în prezent sau dacă o casetă de selectare este bifată în prezent sau nu, fac parte din aceste date. Ori de câte ori există o modificare a datelor, React folosește funcțiile componentei pentru a reda UI-ul, dar numai virtual:

UI1 = CF(data1)UI2 = CF(data2)

React calculează diferențele dintre interfața curentă și noua interfață prin aplicarea unui algoritm de comparație pe cele două versiuni ale DOM-ului său virtual.

Changes = Difference(UI1, UI2)

React apoi trece la aplicarea doar a modificărilor UI la interfața reală a browserului. Când datele asociate cu o componentă se modifică, React determină dacă este necesară o actualizare DOM reală. Acest lucru permite React să evite operațiile de manipulare DOM potențial costisitoare în browser. Exemple precum crearea de noduri DOM și accesarea celor existente dincolo de necesitate.

Această diferențiere și redare repetată a componentelor poate fi una dintre sursele principale ale problemelor de performanță React în orice aplicație React. Construirea unei aplicații React în care algoritmul de diferențiere nu reușește reconcilia efectiv, provocând redarea repetată a întregii aplicații, ceea ce provoacă randamente irosite și care poate duce la o experiență frustrant de lentă.

În timpul procesului de redare inițială, React construiește un arbore DOM ca acesta –

1612030029 504 Cum sa identificati si sa rezolvati randarile irosite in React

Să presupunem că o parte din date se schimbă. Ceea ce vrem să facă React este să redau doar componentele care sunt direct afectate de acea modificare specifică. Se poate sări chiar și procesul de diferențiere pentru restul componentelor. Să presupunem câteva modificări de date în componentă 2 în imaginea de mai sus și din care au fost transmise datele R la B și apoi 2. Dacă R redă redarea, atunci va reda din nou fiecărui copil, ceea ce înseamnă A, B, C, D și prin acest proces ceea ce face React este:

1612030029 336 Cum sa identificati si sa rezolvati randarile irosite in React

În imaginea de mai sus, toate nodurile galbene sunt redate și diferențiate. Acest lucru are ca rezultat pierderea timpului / resurselor de calcul. Aici ne vom pune în primul rând eforturile de optimizare. Configurarea fiecărei componente pentru a reda și diferenția numai atunci când este necesar. Acest lucru ne va permite să recuperăm acele cicluri de CPU irosite. În primul rând, vom arunca o privire asupra modului în care putem identifica randamentele irosite ale aplicației noastre.

Identificați randurile irosite

Există câteva modalități diferite de a face acest lucru. Cea mai simplă metodă este să comutați pe evidențiați actualizările opțiunea din preferința React dev tools.

1612030029 607 Cum sa identificati si sa rezolvati randarile irosite in React

În timp ce interacționați cu aplicația, actualizările sunt evidențiate pe ecran cu margini colorate. Prin acest proces, ar trebui să vedeți componente care s-au redat din nou. Acest lucru ne permite să detectăm redări care nu erau necesare.

Să urmăm acest exemplu.

Cum sa identificati si sa rezolvati randarile irosite in React

Rețineți că, atunci când introducem un al doilea lucru, primul „todo” clipește și pe ecran la fiecare apăsare de tastă. Aceasta înseamnă că este redat de React împreună cu intrarea. Aceasta este ceea ce numim o redare „irosită”. Știm că nu este necesar, deoarece primul conținut pentru toate nu s-a schimbat, dar React nu știe acest lucru.

Chiar dacă React actualizează doar nodurile DOM modificate, redarea încă durează ceva timp. În multe cazuri, nu este o problemă, dar dacă încetinirea este vizibilă, ar trebui să luăm în considerare câteva lucruri pentru a opri randările redundante.

Folosind metoda shouldComponentUpdate

În mod implicit, React va reda DOM-ul virtual și va compara diferența pentru fiecare componentă din arbore pentru orice modificare a elementelor de recuzită sau a stării sale. Dar acest lucru nu este evident rezonabil. Pe măsură ce aplicația noastră crește, încercarea de a reda din nou și de a compara întregul DOM virtual la fiecare acțiune va încetini în cele din urmă totul.

React oferă o metodă simplă a ciclului de viață pentru a indica dacă o componentă are nevoie de redare și, adică, shouldComponentUpdate care este declanșat înainte de începerea procesului de redare. Implementarea implicită a acestei funcții revine true.

1612030030 477 Cum sa identificati si sa rezolvati randarile irosite in React

Când această funcție revine adevărată pentru orice componentă, permite declanșarea procesului de diferențiere a redării. Acest lucru ne oferă puterea de a controla procesul de diferențiere a redării. Să presupunem că trebuie să împiedicăm redarea unei componente, trebuie doar să ne întoarcem false din acea funcție. După cum putem vedea din implementarea metodei, putem compara recuzita curentă și următoarea și starea pentru a determina dacă este necesară o redare:

1612030030 459 Cum sa identificati si sa rezolvati randarile irosite in React

Folosind componente pure

Pe măsură ce lucrați la React, cu siguranță știți React.Component dar cu ce e vorba React.PureComponent? Am discutat deja metoda shouldComponentUpdate a ciclului de viață, în componentele pure, există deja o implementare implicită a, shouldComponentUpdate() cu o recuzită superficială și o comparație de stare. Deci, o componentă pură este o componentă care se redă numai dacă props/state este diferit de precedent recuzită și stat.

1612030031 822 Cum sa identificati si sa rezolvati randarile irosite in React

În comparație superficială, tipurile de date primitive, cum ar fi șirul, booleanul, numărul sunt comparate prin valoare și tipurile de date complexe, cum ar fi matricea, obiectul, funcția sunt comparate prin referință

Dar, dacă avem o componentă funcțională apatridă în care trebuie să implementăm acea metodă de comparație înainte ca fiecare redare să se întâmple? React are o componentă de ordine superioară React.memo. Este ca React.PureComponent ci pentru componente funcționale în loc de clase.

1612030031 180 Cum sa identificati si sa rezolvati randarile irosite in React

În mod implicit, face la fel ca shouldComponentUpdate (), care compară doar superficial obiectul recuzită. Dar, dacă vrem să avem controlul asupra acestei comparații? De asemenea, putem oferi o funcție de comparație personalizată ca al doilea argument.

1612030031 862 Cum sa identificati si sa rezolvati randarile irosite in React

Făcând datele imuabile

Dacă am putea folosi un React.PureComponent dar totuși aveți un mod eficient de a spune când orice recuzită complexă sau stări precum un tablou, un obiect etc. s-au schimbat automat? Aici structura imuabilă a datelor facilitează viața.

Ideea din spatele utilizării structurilor de date imuabile este simplă. Așa cum am discutat mai devreme, pentru tipurile de date complexe, comparația este mai bună decât referința lor. Ori de câte ori un obiect care conține date complexe se schimbă, în loc să facem modificări în acel obiect, putem crea o copie a acelui obiect cu modificările care vor crea o nouă referință.

ES6 are un operator de răspândire a obiectelor pentru ca acest lucru să se întâmple.

1612030031 880 Cum sa identificati si sa rezolvati randarile irosite in React

Putem face același lucru și pentru tablouri:

1612030032 850 Cum sa identificati si sa rezolvati randarile irosite in React

Evitați să transmiteți o referință nouă pentru aceleași date vechi

Știm că ori de câte ori props pentru modificările unei componente, se produce o redare. Dar uneori props nu s-a schimbat. Scriem cod într-un mod în care React crede că s-a schimbat și asta va provoca, de asemenea, o redare, dar de data aceasta este o redare irosită. Deci, practic, trebuie să ne asigurăm că trecem o referință diferită ca elemente de recuzită pentru date diferite. De asemenea, trebuie să evităm să trecem o nouă referință pentru aceleași date. Acum, vom analiza unele cazuri în care creăm această problemă. Să ne uităm la acest cod.

1612030032 409 Cum sa identificati si sa rezolvati randarile irosite in React

Iată conținutul pentru BookInfo componentă în care redăm două componente, BookDescription și BookReview. Acesta este codul corect și funcționează bine, dar există o problemă. BookDescription va fi redat din nou ori de câte ori vom primi noi date de recenzii drept recuzită. De ce? De îndată ce BookInfo componenta primește recuzită nouă, render funcția este chemată să-și creeze arborele elementelor. Funcția de redare creează un nou book constantă care înseamnă că se creează o nouă referință. Asa de, BookDescription va primi acest lucru book ca referință de știri, care va provoca redarea BookDescription. Deci, putem refactura această bucată de cod în acest sens:

1612030032 617 Cum sa identificati si sa rezolvati randarile irosite in React

Acum, referința este întotdeauna aceeași, this.book iar un nou obiect nu este creat în momentul redării. Această filozofie de redare se aplică tuturor prop inclusiv gestionari de evenimente, cum ar fi:

1612030032 900 Cum sa identificati si sa rezolvati randarile irosite in React

Aici, am folosit două moduri diferite (metode de legare și utilizarea funcției săgeată în randare) pentru a invoca metodele de gestionare a evenimentelor, dar ambele vor crea o nouă funcție de fiecare dată când componenta se redă din nou. Deci, pentru a remedia aceste probleme, putem lega metoda în constructor și folosind proprietăți de clasă care sunt încă în experiment și încă nu sunt standardizate, dar atât de mulți dezvoltatori folosesc deja această metodă de a transfera funcții către alte componente în aplicații pregătite pentru producție:

1612030032 291 Cum sa identificati si sa rezolvati randarile irosite in React

Înfășurându-se

Pe plan intern, React utilizează mai multe tehnici inteligente pentru a minimiza numărul de operațiuni DOM costisitoare necesare pentru actualizarea interfeței de utilizare. Pentru multe aplicații, utilizarea React va duce la o interfață rapidă a utilizatorului, fără a face multă muncă pentru a optimiza performanța în mod specific. Cu toate acestea, dacă putem urma tehnicile pe care le-am menționat mai sus pentru a rezolva randamentele irosite, atunci pentru aplicațiile mari vom obține, de asemenea, o experiență foarte bună în ceea ce privește performanța.