Eesti

Õppige kasutama React Profiler API-d. Diagnoosige jõudluse kitsaskohti, parandage mittevajalikke uuesti renderdamisi ja optimeerige oma rakendust praktiliste näidete ja parimate praktikate abil.

Tippjõudluse avamine: süvitsiminek React Profiler API-sse

Tänapäeva veebiarenduse maailmas on kasutajakogemus esmatähtis. Sujuv ja reageeriv kasutajaliides võib olla otsustav tegur rahuloleva ja pettunud kasutaja vahel. Reacti kasutavatele arendajatele on keerukate ja dünaamiliste kasutajaliideste loomine kättesaadavam kui kunagi varem. Kuid rakenduste keerukuse kasvades suureneb ka jõudluse kitsaskohtade oht – peened ebatõhusused, mis võivad viia aeglaste interaktsioonide, katkendlike animatsioonide ja üldiselt halva kasutajakogemuseni. Siin muutub React Profiler API arendaja arsenalis asendamatuks tööriistaks.

See põhjalik juhend viib teid süvitsi React Profilerisse. Uurime, mis see on, kuidas seda tõhusalt kasutada nii React DevTools'i kui ka selle programmilise API kaudu ning mis kõige tähtsam, kuidas tõlgendada selle väljundit levinud jõudlusprobleemide diagnoosimiseks ja parandamiseks. Lõpuks olete valmis muutma jõudlusanalüüsi hirmutavast ülesandest süstemaatiliseks ja rahuldust pakkuvaks osaks oma arendustööst.

Mis on React Profiler API?

React Profiler on spetsialiseeritud tööriist, mis on loodud aitama arendajatel mõõta Reacti rakenduse jõudlust. Selle peamine ülesanne on koguda ajastusteavet iga teie rakenduses renderdatava komponendi kohta, võimaldades teil tuvastada, millised teie rakenduse osad on kulukad renderdada ja võivad põhjustada jõudlusprobleeme.

See vastab olulistele küsimustele, näiteks:

On oluline eristada React Profilerit üldotstarbelistest brauseri jõudlustööriistadest, nagu Chrome DevTools'i vahekaart Performance või Lighthouse. Kuigi need tööriistad on suurepärased lehe üldise laadimisaja, võrgupäringute ja skripti täitmisaja mõõtmiseks, annab React Profiler teile keskendunud, komponendi tasemel ülevaate jõudlusest Reacti ökosüsteemis. See mõistab Reacti elutsüklit ja suudab tuvastada olekumuutuste, props'ide ja kontekstiga seotud ebatõhususi, mida teised tööriistad ei näe.

Profiler on saadaval kahel põhivormil:

  1. React DevTools'i laiendus: kasutajasõbralik graafiline liides, mis on integreeritud otse teie brauseri arendaja tööriistadesse. See on kõige levinum viis profileerimise alustamiseks.
  2. Programmiline `` komponent: komponent, mille saate lisada otse oma JSX-koodi, et koguda jõudlusandmeid programmiliselt, mis on kasulik automatiseeritud testimiseks või mõõdikute saatmiseks analüütikateenusesse.

Oluline on märkida, et Profiler on mõeldud arenduskeskkondadele. Kuigi on olemas spetsiaalne profileerimisega tootmisversioon, eemaldab Reacti standardne tootmisversioon selle funktsionaalsuse, et hoida teek teie lõppkasutajate jaoks võimalikult kerge ja kiire.

Alustamine: Kuidas kasutada React Profilerit

Lähme praktiliseks. Rakenduse profileerimine on lihtne protsess ja mõlema meetodi mõistmine annab teile maksimaalse paindlikkuse.

Meetod 1: React DevTools'i profiili vahekaart

Enamiku igapäevaste jõudlusvigade silumiseks on React DevTools'i vahekaart Profiler teie peamine tööriist. Kui teil pole seda installitud, on see esimene samm – hankige laiendus oma valitud brauserile (Chrome, Firefox, Edge).

Siin on samm-sammuline juhend esimese profileerimisseansi läbiviimiseks:

  1. Avage oma rakendus: navigeerige oma Reacti rakendusse, mis töötab arendusrežiimis. Teate, et DevTools on aktiivne, kui näete brauseri laienduste ribal Reacti ikooni.
  2. Avage arendaja tööriistad: avage oma brauseri arendaja tööriistad (tavaliselt F12 või Ctrl+Shift+I / Cmd+Option+I) ja leidke vahekaart "Profiler". Kui teil on palju vahekaarte, võib see olla peidetud "»" noole taha.
  3. Alustage profileerimist: näete Profiler'i kasutajaliideses sinist ringi (salvestusnupp). Klõpsake seda, et alustada jõudlusandmete salvestamist.
  4. Suhelge oma rakendusega: tehke toiming, mida soovite mõõta. See võib olla mis tahes tegevus alates lehe laadimisest, modaalakna avavale nupule klõpsamisest, vormi sisestamisest või suure loendi filtreerimisest. Eesmärk on reprodutseerida kasutaja interaktsioon, mis tundub aeglane.
  5. Lõpetage profileerimine: kui olete interaktsiooni lõpetanud, klõpsake uuesti salvestusnuppu (see on nüüd punane), et seanss lõpetada.

See on kõik! Profiler töötleb kogutud andmeid ja esitab teile üksikasjaliku visualiseeringu teie rakenduse renderdamise jõudlusest selle interaktsiooni ajal.

Meetod 2: Programmiline `` komponent

Kuigi DevTools on suurepärane interaktiivseks silumiseks, on mõnikord vaja koguda jõudlusandmeid automaatselt. `` komponent, mida eksporditakse `react` paketist, võimaldab teil just seda teha.

Saate mähkida mis tahes osa oma komponendipuust `` komponendiga. See nõuab kahte prop'i:

Siin on koodinäide:

import React, { Profiler } from 'react';

// onRender tagasikutse funktsioon
function onRenderCallback(
  id, // äsja "commit'inud" Profiler'i puu "id" prop
  phase, // "mount" (kui puu just laeti) või "update" (kui see uuesti renderdati)
  actualDuration, // "commit'itud" uuenduse renderdamiseks kulunud aeg
  baseDuration, // hinnanguline aeg kogu alampuu renderdamiseks ilma memoiseerimiseta
  startTime, // millal React alustas selle uuenduse renderdamist
  commitTime, // millal React selle uuenduse "commit'is"
  interactions // uuenduse käivitanud interaktsioonide kogum
) {
  // Saate need andmed logida, saata analüütika teenusesse või koondada.
  console.log({
    id,
    phase,
    actualDuration,
    baseDuration,
    startTime,
    commitTime,
  });
}

function App() {
  return (
    
); }

`onRender` tagasikutse parameetrite mõistmine:

Profileri väljundi tõlgendamine: giidiga ringkäik

Pärast salvestusseansi peatamist React DevTools'is esitatakse teile rikkalikult teavet. Vaatame läbi kasutajaliidese peamised osad.

"Commit'i" valija

Profileri ülaosas näete tulpdiagrammi. Iga tulp selles diagrammis tähistab ühte "commit'i", mille React tegi DOM-i teie salvestuse ajal. Tulba kõrgus ja värv näitavad, kui kaua selle "commit'i" renderdamine aega võttis – kõrgemad, kollased/oranžid tulbad on kulukamad kui lühemad, sinised/rohelised tulbad. Saate klõpsata nendel tulpadel, et uurida iga konkreetse renderdustsükli detaile.

Leekgraafiku diagramm

See on kõige võimsam visualiseering. Valitud "commit'i" jaoks näitab leekgraafik, millised komponendid teie rakenduses renderdati. Siin on, kuidas seda lugeda:

Edetabeli diagramm

Kui leekgraafik tundub liiga keeruline, saate lülituda edetabeli vaatele. See vaade loetleb lihtsalt kõik valitud "commit'i" ajal renderdatud komponendid, sorteerituna selle järgi, milline neist võttis kõige kauem aega. See on suurepärane viis oma kõige kulukamate komponentide koheseks tuvastamiseks.

Komponendi detailide paan

Kui klõpsate leekgraafikus või edetabelis konkreetsele komponendile, ilmub paremale detailide paan. Siit leiate kõige praktilisema teabe:

Levinud jõudluse kitsaskohad ja nende parandamine

Nüüd, kui teate, kuidas jõudlusandmeid koguda ja lugeda, uurime levinud probleeme, mida Profiler aitab avastada, ja standardseid Reacti mustreid nende lahendamiseks.

Probleem 1: mittevajalikud uuesti renderdamised

See on kaugelt kõige levinum jõudlusprobleem Reacti rakendustes. See tekib siis, kui komponent renderdatakse uuesti, kuigi selle väljund oleks täpselt sama. See raiskab protsessori tsükleid ja võib muuta teie kasutajaliidese loiuks.

Diagnoos:

Lahendus 1: `React.memo()`

`React.memo` on kõrgema järgu komponent (HOC), mis memoiseerib teie komponendi. See teostab komponendi eelmiste ja uute props'ide pealiskaudse võrdluse. Kui props'id on samad, jätab React komponendi uuesti renderdamata ja kasutab uuesti viimati renderdatud tulemust.

Enne `React.memo`'t:

function UserAvatar({ userName, avatarUrl }) {
  console.log(`Rendering UserAvatar for ${userName}`)
  return {userName};
}

// In parent:
// If the parent re-renders for any reason (e.g., its own state changes),
// UserAvatar will re-render, even if userName and avatarUrl are identical.

Pärast `React.memo`'t:

import React from 'react';

const UserAvatar = React.memo(function UserAvatar({ userName, avatarUrl }) {
  console.log(`Rendering UserAvatar for ${userName}`)
  return {userName};
});

// Now, UserAvatar will ONLY re-render if the userName or avatarUrl props actually change.

Lahendus 2: `useCallback()`

`React.memo`'d võivad nurjata props'id, mis ei ole primitiivsed väärtused, nagu objektid või funktsioonid. JavaScriptis `() => {} !== () => {}`. Iga renderdamisega luuakse uus funktsioon, nii et kui edastate funktsiooni prop'ina memoiseeritud komponendile, renderdatakse see ikkagi uuesti.

`useCallback` hook lahendab selle, tagastades tagasikutse funktsiooni memoiseeritud versiooni, mis muutub ainult siis, kui mõni selle sõltuvustest on muutunud.

Enne `useCallback`'i:

function ParentComponent() {
  const [count, setCount] = useState(0);

  // This function is recreated on every render of ParentComponent
  const handleItemClick = (id) => {
    console.log('Clicked item', id);
  };

  return (
    
{/* MemoizedListItem will re-render every time count changes, because handleItemClick is a new function */}
); }

Pärast `useCallback`'i:

import { useState, useCallback } from 'react';

function ParentComponent() {
  const [count, setCount] = useState(0);

  // This function is now memoized and will not be recreated unless its dependencies (empty array) change.
  const handleItemClick = useCallback((id) => {
    console.log('Clicked item', id);
  }, []); // Empty dependency array means it's created only once

  return (
    
{/* Now, MemoizedListItem will NOT re-render when count changes */}
); }

Lahendus 3: `useMemo()`

Sarnaselt `useCallback`'ile on `useMemo` mõeldud väärtuste memoiseerimiseks. See on ideaalne kulukate arvutuste tegemiseks või keeruliste objektide/massiivide loomiseks, mida te ei soovi iga renderdamise korral uuesti genereerida.

Enne `useMemo`'d:

function ProductList({ products, filterTerm }) {
  // This expensive filtering operation runs on EVERY render of ProductList,
  // even if only an unrelated prop changed.
  const visibleProducts = products.filter(p => p.name.includes(filterTerm));

  return (
    
    {visibleProducts.map(p =>
  • {p.name}
  • )}
); }

Pärast `useMemo`'d:

import { useMemo } from 'react';

function ProductList({ products, filterTerm }) {
  // This calculation now only runs when `products` or `filterTerm` changes.
  const visibleProducts = useMemo(() => {
    return products.filter(p => p.name.includes(filterTerm));
  }, [products, filterTerm]);

  return (
    
    {visibleProducts.map(p =>
  • {p.name}
  • )}
); }

Probleem 2: Suured ja kulukad komponendipuu struktuurid

Mõnikord ei ole probleemiks mittevajalikud uuesti renderdamised, vaid see, et üks renderdamine on tõesti aeglane, kuna komponendipuu on massiivne või teostab raskeid arvutusi.

Diagnoos:

Lahendus: aknastamine / virtualiseerimine

Pikkade loendite või suurte andmevõrkude puhul on kõige tõhusam lahendus renderdada ainult need elemendid, mis on kasutajale hetkel vaateaknas nähtavad. Seda tehnikat nimetatakse "aknastamiseks" või "virtualiseerimiseks". Selle asemel, et renderdada 10 000 loendi elementi, renderdate ainult need 20, mis ekraanile mahuvad. See vähendab drastiliselt DOM-sõlmede arvu ja renderdamisele kuluvat aega.

Selle nullist rakendamine võib olla keeruline, kuid on olemas suurepäraseid teeke, mis muudavad selle lihtsaks:

Probleem 3: Context API lõksud

React Context API on võimas tööriist prop'ide edastamise vältimiseks, kuid sellel on oluline jõudlusalane puudus: iga komponent, mis tarbib konteksti, renderdatakse uuesti, kui mis tahes väärtus selles kontekstis muutub, isegi kui komponent seda konkreetset andmeosa ei kasuta.

Diagnoos:

Lahendus: jagage oma kontekstid osadeks

Parim viis selle lahendamiseks on vältida ühe hiiglasliku, monoliitse `AppContext`'i loomist. Selle asemel jagage oma globaalne olek mitmeks väiksemaks ja teralisemaks kontekstiks.

Enne (halb praktika):

// AppContext.js
const AppContext = createContext({ 
  currentUser: null, 
  theme: 'light', 
  language: 'en',
  setTheme: () => {}, 
  // ... and 20 other values
});

// MyComponent.js
// This component only needs currentUser, but will re-render when the theme changes!
const { currentUser } = useContext(AppContext);

Pärast (hea praktika):

// UserContext.js
const UserContext = createContext(null);

// ThemeContext.js
const ThemeContext = createContext({ theme: 'light', setTheme: () => {} });

// MyComponent.js
// This component now ONLY re-renders when currentUser changes.
const currentUser = useContext(UserContext);

Täiustatud profileerimistehnikad ja parimad praktikad

Tootmiskeskkonna profileerimiseks ehitamine

Vaikimisi ei tee `` komponent tootmisversioonis midagi. Selle lubamiseks peate oma rakenduse ehitama spetsiaalse `react-dom/profiling` versiooniga. See loob tootmisvalmis paketi, mis sisaldab endiselt profileerimise instrumentatsiooni.

Kuidas te selle lubate, sõltub teie ehitustööriistast. Näiteks Webpacki puhul võite oma konfiguratsioonis kasutada aliast:

// webpack.config.js
module.exports = {
  // ... other config
  resolve: {
    alias: {
      'react-dom$': 'react-dom/profiling',
    },
  },
};

See võimaldab teil kasutada React DevTools Profilerit oma avaldatud, tootmiseks optimeeritud saidil, et siluda reaalseid jõudlusprobleeme.

Proaktiivne lähenemine jõudlusele

Ärge oodake, kuni kasutajad kaebavad aegluse üle. Integreerige jõudluse mõõtmine oma arendusprotsessi:

Kokkuvõte

Jõudluse optimeerimine ei ole järelmõte; see on kvaliteetsete ja professionaalsete veebirakenduste loomise põhiaspekt. React Profiler API, nii oma DevTools'i kui ka programmilises vormis, demüstifitseerib renderdamisprotsessi ja pakub konkreetseid andmeid, mis on vajalikud teadlike otsuste tegemiseks.

Selle tööriista valdamisega saate liikuda jõudluse kohta oletamiselt süstemaatilisele kitsaskohtade tuvastamisele, sihipäraste optimeerimiste rakendamisele nagu `React.memo`, `useCallback` ja virtualiseerimine ning lõpuks kiirete, sujuvate ja nauditavate kasutajakogemuste loomisele, mis eristavad teie rakendust teistest. Alustage profileerimisega juba täna ja avage oma Reacti projektides järgmine jõudluse tase.