Latviešu

Apgūstiet React Profiler API. Iemācieties diagnosticēt veiktspējas problēmas, novērst nevajadzīgas pārzīmēšanas un optimizēt savu lietotni ar praktiskiem piemēriem.

Maksimālas veiktspējas atslēgšana: Padziļināts ieskats React Profiler API

Mūsdienu tīmekļa izstrādes pasaulē lietotāja pieredze ir vissvarīgākā. Plūstošs, atsaucīgs interfeiss var būt izšķirošais faktors starp apmierinātu un neapmierinātu lietotāju. Izstrādātājiem, kas izmanto React, sarežģītu un dinamisku lietotāja saskarņu veidošana ir pieejamāka nekā jebkad agrāk. Tomēr, lietojumprogrammām kļūstot sarežģītākām, pieaug arī veiktspējas problēmu risks — smalkas neefektivitātes, kas var izraisīt lēnu mijiedarbību, saraustītas animācijas un kopumā sliktu lietotāja pieredzi. Tieši šeit React Profiler API kļūst par neaizstājamu rīku izstrādātāja arsenālā.

Šis visaptverošais ceļvedis jūs aizvedīs padziļinātā React Profiler izpētē. Mēs izpētīsim, kas tas ir, kā to efektīvi izmantot gan ar React DevTools, gan ar tā programmatisko API, un, pats galvenais, kā interpretēt tā rezultātus, lai diagnosticētu un novērstu izplatītas veiktspējas problēmas. Līdz beigām jūs būsiet gatavs pārvērst veiktspējas analīzi no biedējoša uzdevuma par sistemātisku un atalgojošu daļu no jūsu izstrādes darba plūsmas.

Kas ir React Profiler API?

React Profiler ir specializēts rīks, kas izstrādāts, lai palīdzētu izstrādātājiem izmērīt React lietojumprogrammas veiktspēju. Tā galvenā funkcija ir apkopot laika informāciju par katru komponentu, kas tiek renderēts jūsu lietojumprogrammā, ļaujot jums identificēt, kuras lietotnes daļas ir dārgi renderēt un kas varētu radīt veiktspējas problēmas.

Tas atbild uz tādiem būtiskiem jautājumiem kā:

Ir svarīgi atšķirt React Profiler no vispārējiem pārlūkprogrammas veiktspējas rīkiem, piemēram, cilnes "Performance" Chrome DevTools vai Lighthouse. Lai gan šie rīki ir lieliski piemēroti kopējās lapas ielādes, tīkla pieprasījumu un skriptu izpildes laika mērīšanai, React Profiler sniedz jums fokusētu, komponentu līmeņa skatījumu uz veiktspēju React ekosistēmas ietvaros. Tas saprot React dzīves ciklu un var precīzi noteikt neefektivitātes, kas saistītas ar stāvokļa (state) izmaiņām, īpašībām (props) un kontekstu, ko citi rīki nevar redzēt.

Profiler ir pieejams divos galvenajos veidos:

  1. React DevTools paplašinājums: Lietotājam draudzīgs, grafisks interfeiss, kas integrēts tieši jūsu pārlūkprogrammas izstrādātāja rīkos. Šis ir visizplatītākais veids, kā sākt profilēšanu.
  2. Programmatiskais `` komponents: Komponents, ko varat pievienot tieši savam JSX kodam, lai programmatiski apkopotu veiktspējas mērījumus, kas ir noderīgi automatizētai testēšanai vai metrikas nosūtīšanai uz analītikas pakalpojumu.

Būtiski, ka Profiler ir paredzēts izstrādes vidēm. Lai gan pastāv īpašs produkcijas builds ar iespējotu profilēšanu, standarta React produkcijas builds izslēdz šo funkcionalitāti, lai bibliotēka būtu pēc iespējas vieglāka un ātrāka jūsu gala lietotājiem.

Darba sākšana: Kā lietot React Profiler

Pievērsīsimies praksei. Jūsu lietojumprogrammas profilēšana ir vienkāršs process, un abu metožu izpratne sniegs jums maksimālu elastību.

1. metode: React DevTools Profiler cilne

Lielākajai daļai ikdienas veiktspējas atkļūdošanas Profiler cilne React DevTools ir jūsu galvenais rīks. Ja jums tas nav instalēts, tas ir pirmais solis — iegūstiet paplašinājumu savai izvēlētajai pārlūkprogrammai (Chrome, Firefox, Edge).

Šeit ir soli pa solim ceļvedis jūsu pirmās profilēšanas sesijas veikšanai:

  1. Atveriet savu lietojumprogrammu: Dodieties uz savu React lietojumprogrammu, kas darbojas izstrādes režīmā. Jūs zināsiet, ka DevTools ir aktīvi, ja redzēsiet React ikonu savas pārlūkprogrammas paplašinājumu joslā.
  2. Atveriet izstrādātāja rīkus: Atveriet savas pārlūkprogrammas izstrādātāja rīkus (parasti ar F12 vai Ctrl+Shift+I / Cmd+Option+I) un atrodiet cilni "Profiler". Ja jums ir daudz cilņu, tā var būt paslēpta aiz "»" bultiņas.
  3. Sāciet profilēšanu: Profiler saskarnē redzēsiet zilu apli (ierakstīšanas poga). Noklikšķiniet uz tās, lai sāktu ierakstīt veiktspējas datus.
  4. Mijiedarbojieties ar savu lietotni: Veiciet darbību, kuru vēlaties izmērīt. Tas varētu būt jebkas, sākot no lapas ielādes, pogas noklikšķināšanas, kas atver modālo logu, rakstīšanas formā vai liela saraksta filtrēšanas. Mērķis ir reproducēt lietotāja mijiedarbību, kas šķiet lēna.
  5. Pārtrauciet profilēšanu: Kad esat pabeidzis mijiedarbību, vēlreiz noklikšķiniet uz ierakstīšanas pogas (tagad tā būs sarkana), lai pārtrauktu sesiju.

Tas arī viss! Profiler apstrādās savāktos datus un parādīs jums detalizētu jūsu lietojumprogrammas renderēšanas veiktspējas vizualizāciju šīs mijiedarbības laikā.

2. metode: Programmatiskais `Profiler` komponents

Lai gan DevTools ir lieliski piemērots interaktīvai atkļūdošanai, dažreiz ir nepieciešams apkopot veiktspējas datus automātiski. `` komponents, kas eksportēts no `react` pakotnes, ļauj to izdarīt.

Jūs varat ietīt jebkuru sava komponentu koka daļu ar `` komponentu. Tam ir nepieciešami divi props:

Šeit ir koda piemērs:

import React, { Profiler } from 'react';

// onRender atsauces funkcija
function onRenderCallback(
  id, // Profiler koka "id" prop, kas tikko ir apstiprinājis
  phase, // "mount" (ja koks tikko tika ielādēts) vai "update" (ja tas tika pārzīmēts)
  actualDuration, // laiks, kas pavadīts, renderējot apstiprināto atjauninājumu
  baseDuration, // aptuvenais laiks, lai renderētu visu apakškoku bez memoizācijas
  startTime, // kad React sāka renderēt šo atjauninājumu
  commitTime, // kad React apstiprināja šo atjauninājumu
  interactions // mijiedarbību kopa, kas izraisīja atjauninājumu
) {
  // Jūs varat reģistrēt šos datus, nosūtīt tos uz analītikas galapunktu vai apkopot tos.
  console.log({
    id,
    phase,
    actualDuration,
    baseDuration,
    startTime,
    commitTime,
  });
}

function App() {
  return (
    
); }

`onRender` atsauces funkcijas parametru izpratne:

Profilera rezultātu interpretācija: Ceļvedis

Pēc ierakstīšanas sesijas pārtraukšanas React DevTools jums tiek parādīts milzīgs informācijas daudzums. Apskatīsim galvenās lietotāja saskarnes daļas.

"Commit" atlasītājs

Profilera augšpusē redzēsiet stabiņu diagrammu. Katrs stabiņš šajā diagrammā apzīmē vienu "commit" (apstiprinājumu), ko React veica DOM ierakstīšanas laikā. Stabiņa augstums un krāsa norāda, cik ilgs laiks bija nepieciešams šī commit renderēšanai — garāki, dzelteni/oranži stabiņi ir dārgāki nekā īsāki, zili/zaļi stabiņi. Jūs varat noklikšķināt uz šiem stabiņiem, lai pārbaudītu katra konkrētā renderēšanas cikla detaļas.

Liesmu diagramma (Flamegraph Chart)

Šī ir visspēcīgākā vizualizācija. Izvēlētajam commit, liesmu diagramma parāda, kuri komponenti jūsu lietojumprogrammā tika renderēti. Lūk, kā to lasīt:

Sarindotā diagramma (Ranked Chart)

Ja liesmu diagramma šķiet pārāk sarežģīta, varat pārslēgties uz sarindoto diagrammas skatu. Šis skats vienkārši uzskaita visus komponentus, kas tika renderēti atlasītā commit laikā, sakārtotus pēc tā, kurš aizņēma visilgāko laiku renderēšanai. Tas ir lielisks veids, kā nekavējoties identificēt savus dārgākos komponentus.

Komponenta detaļu panelis

Noklikšķinot uz konkrēta komponenta liesmu vai sarindotajā diagrammā, labajā pusē parādās detaļu panelis. Šeit jūs atradīsiet vispraktiskāko informāciju:

Biežākās veiktspējas problēmas un kā tās novērst

Tagad, kad jūs zināt, kā apkopot un lasīt veiktspējas datus, izpētīsim biežākās problēmas, ko Profiler palīdz atklāt, un standarta React modeļus to risināšanai.

1. problēma: Nevajadzīgas pārzīmēšanas (Re-renders)

Šī ir visizplatītākā veiktspējas problēma React lietojumprogrammās. Tā rodas, kad komponents tiek pārzīmēts, lai gan tā rezultāts būtu tieši tāds pats. Tas tērē CPU ciklus un var padarīt jūsu lietotāja saskarni lēnīgu.

Diagnoze:

1. risinājums: `React.memo()`

`React.memo` ir augstākās kārtas komponents (HOC), kas memoizē jūsu komponentu. Tas veic seklu (shallow) komponenta iepriekšējo un jauno props salīdzināšanu. Ja props ir vienādi, React izlaidīs komponenta pārzīmēšanu un atkārtoti izmantos pēdējo renderēto rezultātu.

Pirms `React.memo`:**

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

// Vecākkomponentā:
// Ja vecākkomponents tiek pārzīmēts jebkāda iemesla dēļ (piem., mainās tā paša stāvoklis),
// UserAvatar tiks pārzīmēts, pat ja userName un avatarUrl ir identiski.

Pēc `React.memo`:**

import React from 'react';

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

// Tagad UserAvatar tiks pārzīmēts TIKAI tad, ja userName vai avatarUrl props faktiski mainīsies.

2. risinājums: `useCallback()`

`React.memo` var tikt "uzvarēts" ar props, kas nav primitīvas vērtības, piemēram, objektiem vai funkcijām. JavaScript valodā `() => {} !== () => {}`. Katrā renderēšanas reizē tiek izveidota jauna funkcija, tādēļ, ja jūs nododat funkciju kā prop memoizētam komponentam, tas joprojām tiks pārzīmēts.

`useCallback` hook atrisina šo problēmu, atgriežot memoizētu atsauces funkcijas versiju, kas mainās tikai tad, ja ir mainījusies kāda no tās atkarībām.

Pirms `useCallback`:**

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

  // Šī funkcija tiek atkārtoti izveidota katrā ParentComponent renderēšanas reizē
  const handleItemClick = (id) => {
    console.log('Clicked item', id);
  };

  return (
    
{/* MemoizedListItem tiks pārzīmēts katru reizi, kad mainās count, jo handleItemClick ir jauna funkcija */}
); }

Pēc `useCallback`:**

import { useState, useCallback } from 'react';

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

  // Šī funkcija tagad ir memoizēta un netiks atkārtoti izveidota, ja vien nemainīsies tās atkarības (tukšs masīvs).
  const handleItemClick = useCallback((id) => {
    console.log('Clicked item', id);
  }, []); // Tukšs atkarību masīvs nozīmē, ka tā tiek izveidota tikai vienu reizi

  return (
    
{/* Tagad MemoizedListItem NETIKS pārzīmēts, kad mainīsies count */}
); }

3. risinājums: `useMemo()`

Līdzīgi kā `useCallback`, `useMemo` ir paredzēts vērtību memoizēšanai. Tas ir ideāli piemērots dārgiem aprēķiniem vai sarežģītu objektu/masīvu izveidei, kurus nevēlaties atjaunot katrā renderēšanas reizē.

Pirms `useMemo`:**

function ProductList({ products, filterTerm }) {
  // Šī dārgā filtrēšanas operācija tiek izpildīta KATRĀ ProductList renderēšanas reizē,
  // pat ja mainījās tikai nesaistīts prop.
  const visibleProducts = products.filter(p => p.name.includes(filterTerm));

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

Pēc `useMemo`:**

import { useMemo } from 'react';

function ProductList({ products, filterTerm }) {
  // Šis aprēķins tagad tiek veikts tikai tad, ja mainās `products` vai `filterTerm`.
  const visibleProducts = useMemo(() => {
    return products.filter(p => p.name.includes(filterTerm));
  }, [products, filterTerm]);

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

2. problēma: Lieli un dārgi komponentu koki

Dažreiz problēma nav nevajadzīgas pārzīmēšanas, bet gan tas, ka viena renderēšana ir patiesi lēna, jo komponentu koks ir milzīgs vai veic smagus aprēķinus.

Diagnoze:

  • Liesmu diagrammā jūs redzat vienu komponentu ar ļoti platu, dzeltenu vai sarkanu joslu, kas norāda uz augstu `baseDuration` un `actualDuration`.
  • Lietotāja saskarne sasalst vai kļūst saraustīta, kad šis komponents parādās vai tiek atjaunināts.

Risinājums: "Windowing" / Virtualizācija

Gariem sarakstiem vai lielām datu tabulām visefektīvākais risinājums ir renderēt tikai tos elementus, kas pašlaik ir redzami lietotājam skatlogā. Šo tehniku sauc par "windowing" vai "virtualizāciju". Tā vietā, lai renderētu 10 000 saraksta elementu, jūs renderējat tikai tos 20, kas ietilpst ekrānā. Tas krasi samazina DOM mezglu skaitu un renderēšanai pavadīto laiku.

To ieviest no nulles var būt sarežģīti, bet ir lieliskas bibliotēkas, kas to atvieglo:

  • `react-window` un `react-virtualized` ir populāras, jaudīgas bibliotēkas virtualizētu sarakstu un tabulu izveidei.
  • Nesenākas bibliotēkas, piemēram, `TanStack Virtual`, piedāvā "headless", uz hooks balstītas pieejas, kas ir ļoti elastīgas.

3. problēma: Context API slazdi

React Context API ir spēcīgs rīks, lai izvairītos no "prop drilling", bet tam ir būtisks veiktspējas trūkums: jebkurš komponents, kas patērē kontekstu, tiks pārzīmēts ikreiz, kad mainās jebkura vērtība šajā kontekstā, pat ja komponents neizmanto šo konkrēto datu daļu.

Diagnoze:

  • Jūs atjaunināt vienu vērtību savā globālajā kontekstā (piem., tēmas pārslēdzēju).
  • Profiler rāda, ka liels skaits komponentu visā jūsu lietojumprogrammā tiek pārzīmēts, pat komponenti, kas ir pilnīgi nesaistīti ar tēmu.
  • Panelis "Why did this render?" šiem komponentiem rāda "Context changed".

Risinājums: Sadaliet savus kontekstus

Labākais veids, kā to atrisināt, ir izvairīties no viena milzīga, monolīta `AppContext` izveides. Tā vietā sadaliet savu globālo stāvokli vairākos, mazākos, granulētākos kontekstos.

Pirms (sliktā prakse):**

// AppContext.js
const AppContext = createContext({ 
  currentUser: null, 
  theme: 'light', 
  language: 'en',
  setTheme: () => {}, 
  // ... un vēl 20 citas vērtības
});

// MyComponent.js
// Šim komponentam ir nepieciešams tikai currentUser, bet tas tiks pārzīmēts, kad mainīsies tēma!
const { currentUser } = useContext(AppContext);

Pēc (labā prakse):**

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

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

// MyComponent.js
// Šis komponents tagad tiek pārzīmēts TIKAI tad, ja mainās currentUser.
const currentUser = useContext(UserContext);

Papildu profilēšanas tehnikas un labākās prakses

Produkcijas profilēšanas būvēšana

Pēc noklusējuma `` komponents produkcijas buildā nedara neko. Lai to iespējotu, jums ir jābūvē jūsu lietojumprogramma, izmantojot īpašo `react-dom/profiling` buildu. Tas izveido produkcijai gatavu pakotni, kas joprojām ietver profilēšanas instrumentāciju.

Kā to iespējot, ir atkarīgs no jūsu būvēšanas rīka. Piemēram, ar Webpack jūs varētu izmantot aizstājvārdu (alias) savā konfigurācijā:

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

Tas ļauj jums izmantot React DevTools Profiler jūsu publicētajā, produkcijai optimizētajā vietnē, lai atkļūdotu reālās pasaules veiktspējas problēmas.

Proaktīva pieeja veiktspējai

Negaidiet, kamēr lietotāji sūdzēsies par lēnumu. Integrējiet veiktspējas mērīšanu savā izstrādes darba plūsmā:

  • Profilējiet agri, profilējiet bieži: Regulāri profilējiet jaunas funkcijas, kad tās veidojat. Ir daudz vieglāk novērst problēmu, kad kods ir svaigs jūsu prātā.
  • Izveidojiet veiktspējas budžetus: Izmantojiet programmatisko `` API, lai iestatītu budžetus kritiskām mijiedarbībām. Piemēram, jūs varētu apgalvot, ka galvenā paneļa ielādei nekad nevajadzētu aizņemt vairāk par 200 ms.
  • Automatizējiet veiktspējas testus: Jūs varat izmantot programmatisko API kopā ar testēšanas ietvariem, piemēram, Jest vai Playwright, lai izveidotu automatizētus testus, kas neizdodas, ja renderēšana aizņem pārāk ilgu laiku, novēršot veiktspējas regresiju apvienošanu.

Noslēgums

Veiktspējas optimizācija nav pēcpārdoma; tā ir augstas kvalitātes, profesionālu tīmekļa lietojumprogrammu veidošanas pamatā. React Profiler API, gan tā DevTools, gan programmatiskajā formā, demistificē renderēšanas procesu un nodrošina konkrētus datus, kas nepieciešami, lai pieņemtu pamatotus lēmumus.

Apgūstot šo rīku, jūs varat pāriet no minējumiem par veiktspēju uz sistemātisku problēmu identificēšanu, mērķtiecīgu optimizāciju, piemēram, `React.memo`, `useCallback` un virtualizācijas, piemērošanu un galu galā veidot ātras, plūstošas un apburošas lietotāja pieredzes, kas izceļ jūsu lietojumprogrammu. Sāciet profilēšanu jau šodien un atslēdziet nākamo veiktspējas līmeni savos React projektos.