Performansın Optimallaşdırılması
These docs are old and won’t be updated. Go to react.dev for the new React docs.
These new documentation pages teach modern React:
Daxildə, React, bir neçə ağıllı texnikadan istifadə edərək UI-ı yeniləmək üçün ağır DOM əməliyyatlarının sayını azaldır. Bir çox applikasiyada performansı xüsusi optimallaşdırmadan React-dən istifadə etdikdə itifadəçi interfeysi tez işləyəcək. Buna baxmayaraq React applikasiyasını tezləşdirməyin bir neçə yolu var.
Produksiya Qurulmasından İstifadə Edin
React applikasiyalarında performans problemləri olduqda minimallaşdırılmış produksiya qurulmasının istifadə edildiyindən əmin olun.
Normalda, React-də faydalı xəbərdarlıqlar var. Bu xəbərdarlıqlar development zamanı faydalıdır. Lakin, bu xəbərdarlıqlar React-i böyüdür və yavaşladır. Bu səbəbdən, applikasiyanı yerləşdirdikdə produksiya versiyasının istifadəsindən əmin olun.
Qurulma prosesinin düzgün işlədiyindən əmin olmadıqda Chrome üçün React Developer Alətlərindən istifadə edin. Produksiya modunda olan React səhifəsini ziyarət etdikdə alətin ikonu tünd fonda olacaq:
Development modunda olan React səhifəsini ziyarət etdikdə isə alətin ikonu qırmızı fonda olacaq:
Applikasiyanı yazdıqda development modundan istifadə edin. Applikasiyanı istifadəçilər üçün yerləşdirdikdə isə produksiya modundan istifadə edin.
Applikasiyanın produksiya üçün qurulması üçün aşağıdakı təlimatlara baxın.
Create React App
Layihə Create React App üzərində qurulduqda aşağıdakı əmri icra etmək kifayətdir:
npm run build
Bu, applikasiyanın produksiya versiyasını layihənin build/
direktoriyasında yaradacaq.
Bunun yalnız produksiya zamanı işlədildiyini unutmayın. Normal development üçün npm start
əmrindən istifadə edin.
Tək Fayl Qurulmaları
Biz, React və React DOM-un produksiyaya hazır versiyalarını tək fayl ilə təmin edirik:
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
Produksiya üçün yalnız .production.min.js
ilə bitən faylların uyğun olduğunu unutmayın.
Brunch
Ən səmərəli Brunch produksiya qurulması üçün terser-brunch
plaginini yükləyin:
# npm işlədirsinizsə
npm install --save-dev terser-brunch
# Yarn işlədirsinizsə
yarn add --dev terser-brunch
Produksiya qurulması yaratmaq üçün build
əmrinə -p
arqumenti əlavə edin:
brunch build -p
Bunun yalnız produksiya zamanı işlədildiyini unutmayın. -p
arqumentini və ya plagini development zamanı işlətməyin. Çünki, bu, qurulma əməliyyatını çox yavaşladacaq və React-in faydalı xəbərdarlıqlarını gizlədəcək.
Browserify
Ən səmərəli Browserify produksiya qurulması üçün bir neçə plagin yükləmək lazımdır:
# npm işlədirsinizsə
npm install --save-dev envify terser uglifyify
# Yarn işlədirsinizsə
yarn add --dev envify terser uglifyify
Produksiya qurulması yaratmaq üçün aşağıdakı çevirmələri əlavə edin (sıra vacibdir):
envify
çevirməsi düzgün produksiya mühitinin təyin edilməsini siğortalayır. Bunu qlobal edin (-g
).uglifyify
çevirməsi development idxallarını silir. Bunu qlobal edin (-g
).- Sonda, nəticlənənən paket
terser
-ə korlanmaq üçün (mangling) göndərilir (səbəbini buraxan oxuyun).
Məsələn:
browserify ./index.js \
-g [ envify --NODE_ENV production ] \
-g uglifyify \
| terser --compress --mangle > ./bundle.js
Bunun yalnız produksiya zamanı işlədildiyini unutmayın. Bu plaginləri development zamanı işlətməyin. Çünki, bu, qurulma əməliyyatını çox yavaşladacaq və React-in faydalı xəbərdarlıqlarını gizlədəcək.
Rollup
Ən səmərəli Rollup qurulması üçün bəzi plaginləri yükləmək lazımdır:
# npm işlədirsinizsə
npm install --save-dev rollup-plugin-commonjs rollup-plugin-replace rollup-plugin-terser
# Yarn işlədirsinizsə
yarn add --dev rollup-plugin-commonjs rollup-plugin-replace rollup-plugin-terser
Produksiya qurulması yaratmaq üçün aşağıdakı plaginləri əlavə edin (sıra vacibdir):
replace
plagini düzgün produksiya mühitinin təyin edilməsini siğortalayır.commonjs
plagini Rollup-da CommonJS-in işlədilməsinə imkan yaradır.terser
plagini son paketi kompresləyir və korlayır (mangles).
plugins: [
// ...
require('rollup-plugin-replace')({
'process.env.NODE_ENV': JSON.stringify('production')
}),
require('rollup-plugin-commonjs')(),
require('rollup-plugin-terser')(),
// ...
]
Tam qurulma konfiqurasiyası üçün bu gist-ə baxın.
Bunun yalnız produksiya zamanı işlədildiyini unutmayın. Development zamanı terser
və ya replace
plaginini 'production'
dəyəri ilə tətbiq etməyin. Çünki, bu, qurulma əməliyyatını çox yavaşladacaq və React-in faydalı xəbərdarlıqlarını gizlədəcək.
webpack
Qeyd:
Create React App işlədirsinizsə, yuxarıdakı təlimatlara baxın.
Bu bölmə, webpack-in birbaşa konfiqurasiyası üçün uyğundur.
Webpack v4+ versiyasının produksiya modu yazılmış kodu avtomatik minimallaşdıracaq.
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
mode: 'production',
optimization: {
minimizer: [new TerserPlugin({ /* burada parametlər əlavə edə bilərsiniz */ })],
},
};
Əlavə məlumat üçün webpack sənədlərinə baxın.
Bunun yalnız produksiya zamanı işlədildiyini unutmayın. TerserPlugin
plaginini development zamanı işlətməyin. Çünki, bu, qurulma əməliyyatını çox yavaşladacaq və React-in faydalı xəbərdarlıqlarını gizlədəcək.
DevTools Profayleri ilə Komponentlərin Profayl Edilməsi
react-dom
16.5+ və react-native
0.57+ versiyalarında React DevTools Profaylerin DEV modunda daha inkişaf etmiş qabiliyyətləri var.
Profaylerin icmalına “React Profayler ilə Tanışlıq” bloq yazısından baxa bilərsiniz.
Profaylerin video izahatına Youtube-dan baxa bilərsiniz.
React DevTools yükləməmisinizsə, aşağıdakı linklərə baxın:
Qeyd
react-dom
-un produksiyada profayl edilməsireact-dom/profiling
paketində mövcuddur. Bu paketin istifadəsi üçün fb.me/react-profiling səhifəsinə baxın.
Qeyd
React 17-dən öncə biz standart Chrome brauzerinin performans təbi ilə User Timing API-dan istifadə edərək komponentlərin sürətini ölçürdük. Daha detallı məlumat üçün Ben Şvarzın məqaləsini oxuyun.
Böyük Siyahıların Virtuallaşdırılması
Applikasiya böyük siyahılı məlumatlar (100-lərlə və ya 1000-lərlə sətrdən ibarət) render etdikdə “windowing” adlı texnikadan istifadə etməyi tövsiyə edirik. Bu texnika ilə məlumatın yalnız kiçik hissəsi render olunaraq komponentlərin yenidən render edilməsi və yeni DOM nodların yaranması zamanını kəskin şəkildə azaldır.
react-window və react-virtualized paketləri populyar windowing kitabxanalarıdır. Bu kitabxanalar siyahılar, qridlər, və cədvəllər göstərmək üçün bir neçə komponent təmin edirlər. Applikasiyanın xüsusi istifadəsinə uyğun olan windowing lazım olduqda Twitter-in yolu ilə gedərək öz windowing komponentinizi yarada bilərsiniz.
Rekonsilyasiyadan Çəkinmək
React, render olunan UI-ın daxili təmsilini yaradır və saxlayır. Bu təmsilə komponentlərdən qaytarılan React elementləri daxildir. Bu təmsil, lazım olmadıqda DOM nodlarının yaranmasını və istifadəsini azaltmağa imkan yaradır. DOM nodlarındə edilən əməliyyatlar, sadə JavaScript obyektlərində edilən əməliyyatlardan çox yavaşdır. Bu daxili təmsilin “virtual DOM” adlanmasına baxmayaraq eyni təmsil React Native-də də işlənilir.
Komponent propları və ya state-i dəyişdikdə yeni element ilə köhnə render olunmuş element müqayisə olunur. Elementlər eyni olmadıqda DOM yenilənir.
Yalnız dəyişən DOM nodların yenilənməsinə baxmayaraq yenidən render etmə əməliyyatı zaman çəkə bilər. Bir çox ssenaridə bu problem deyil. Lakin, yavaşlama nəzərə çarpan olduqda shouldComponentUpdate
lifecycle funksiyasını (bu funksiya yenidən render etmə prosesi başlamamışdan öncə çağrılır) tətbiq edərək sürəti çoxalda bilərsiniz. Bu funksiyanın standart tətbiqi true
qaytarır. Bu zaman, yeniləmələr React tərəfindən icra olunur:
shouldComponentUpdate(nextProps, nextState) {
return true;
}
Əgər bildiyiniz bəzi situasiyalarda komponent yenilənməməlidirsə, shouldComponentUpdate
funksiyasından false
qaytara bilərsiniz. false
qaytarıldıqda yenilənən komponentin render()
funksiyası daxil olmaqla render etmə prosesi buraxılacaq.
Bir çox ssenaridə shouldComponentUpdate()
funksiyasını əl ilə yazmaq əvəzinə komponenti React.PureComponent
sinfindən gənişləndirə bilərsiniz. Bu, shouldComponentUpdate()
funksiyasında cari və əvvəlki proplar və state-in dayaz müqayisə edilməsinə bərabərdir.
shouldComponentUpdate Funksiyası Fəaliyyətdə
Aşağıda komponentlər ağacı göstərilib. Hər komponentdə SCU
dəyəri shouldComponentUpdate
funksiyasından qaytarılan dəyəri, vDOMEq
isə render olunan elementlərin bərabər olduğunu göstərir. Yumrunun rəngi komponentin rekonsilyasiya olacağını göstərir.
C2-nin shouldComponentUpdate
funksiyasının false
qaytardığından C2 komponenti render edilmir. Bu səbəbdən, C4 və C5-in shouldComponentUpdate
funksiyası çağrılmır.
C1 və C3-ün shouldComponentUpdate
funksiyasının true
qaytardığından komponentlərin bütün uşaqları yoxlanılır. C6-nın shouldComponentUpdate
funksiyasının true
qaytardığından və render olunan elementlərin eyni olmadığından DOM yenilənməli olur.
Ən sonuncu maraqlı komponent C8-dir. React bu komponenti render etməli olur. Lakin, qaytarılan React elementlərin əvvəlki render olunan elementlər ilə eyni olduğundan, DOM yenilənmir.
Nəzərə alın ki, React yalnız C6 üçün DOM-u yeniləyir. C8-də elementlər müqayisə edildikdən sonra DOM yenilənmir. C2 və C7-də isə shouldComponentUpdate
funksiyasının false
qaytardığından elementlərin müqayisəsi əməliyyatı baş vermir. Nəticədə, render
funksiyası çağrılmır.
Nümunələr
Əgər komponent yalnız props.color
və ya state.count
dəyişənləri dəyişdikdə yenilənirsə, bunu shouldComponentUpdate
ilə yoxlaya bilərsiniz:
class CounterButton extends React.Component {
constructor(props) {
super(props);
this.state = {count: 1};
}
shouldComponentUpdate(nextProps, nextState) {
if (this.props.color !== nextProps.color) {
return true;
}
if (this.state.count !== nextState.count) {
return true;
}
return false;
}
render() {
return (
<button
color={this.props.color}
onClick={() => this.setState(state => ({count: state.count + 1}))}>
Tıklama sayı: {this.state.count}
</button>
);
}
}
Bu kodda, shouldComponentUpdate
funksiyası props.color
və ya state.count
dəyərlərinin dəyişdiyini yoxlayır. Dəyərlər dəyişmədikdə komponent yenilənmir. Komponent mürəkkəbləşdikdə props
və state
-in bütün dəyərlərini eyni formada “dayaz müqayisə” edərək komponentin yenilənməsini müəyyənləşdirə bilərsiniz. Bu müqayisə prinsipinin çox işlədildiyindən bunun üçün React-də faydalı sinif var: React.PureComponent
. Aşağıdakı kod, yuxarıdakı kodun daha sadə formasıdır:
class CounterButton extends React.PureComponent {
constructor(props) {
super(props);
this.state = {count: 1};
}
render() {
return (
<button
color={this.props.color}
onClick={() => this.setState(state => ({count: state.count + 1}))}>
Count: {this.state.count}
</button>
);
}
}
Bir çox halda shouldComponentUpdate
əvəzinə React.PureComponent
-dən istifadə edə bilərsiniz. Bu sinif, proplar və state-i dayaz müqayisə edir. Bu səbəbdən, bu sinfi dayaz müqayisə ilə tam yoxlana bilməyən mürəkkəb dəyərləri yoxlamaq üçün istifadə etməyin.
Daha mürəkkəb məlumat strukturlarının dayaz müqayisəsi problem yarada bilər. Məsələn, vergül ilə ayrılmış sözləri render etmək üçün ListOfWords
komponentinin və siyahıya söz əlavə etmək üçün WordAdder
komponentinin olduğunu fikirləşin. Aşağıdakı kod düzgün işləməyəcək:
class ListOfWords extends React.PureComponent {
render() {
return <div>{this.props.words.join(',')}</div>;
}
}
class WordAdder extends React.Component {
constructor(props) {
super(props);
this.state = {
words: ['marklar']
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
// Bu bölmə səhvdir və baqlara səbəb olacaq
const words = this.state.words;
words.push('marklar');
this.setState({words: words});
}
render() {
return (
<div>
<button onClick={this.handleClick} />
<ListOfWords words={this.state.words} />
</div>
);
}
}
PureComponent
sinfi this.props.words
propunu sadə müqayisə edəcək. WordAdder
komponentinin handleClick
funksiyası words
massivini mutasiya etdiyindən massivdəki sözlərin fərqli olmasına baxmayaraq this.props.words
propu eyni qalacaq. Bu səbəbdən, yeni sözlərin render edilməli olmasına baxmayaraq ListOfWords
komponenti yenilənməyəcək.
Məlumatları Mutasiya Etməməyin Gücü
Bu problemi həll etməyin ən asan yolu props və state-in dəyərlərini mutasiya etməməkdir. Məsələn, handleClick
metodu concat
funksiyası ilə yazıla bilər:
handleClick() {
this.setState(state => ({
words: state.words.concat(['marklar'])
}));
}
ES6-ın massivlər üçün yayma sintaksisi ilə də massivə elementi əlavə etmək mümkündür. Create React App işlədirsinizsə bu sintaksis işləyəcək.
handleClick() {
this.setState(state => ({
words: [...state.words, 'marklar'],
}));
};
Siz, həmçinin obyektlərin mutasiya olunmaması üçün kodu dəyişə bilərsiniz. Məsələn, colormap
obyektinin olduğunu və bu obyektin colormap.right
dəyərini 'mavi'
-yə dəyişmək istədiyimizi fərz edək:
function updateColorMap(colormap) {
colormap.right = 'mavi';
}
Orijinal obyekti mutasiya etməmək üçün Object.assign funksiyasından istifadə edə bilərsiniz:
function updateColorMap(colormap) {
return Object.assign({}, colormap, {right: 'mavi'});
}
İndi, updateColorMap
funksiyası köhnə obyekti mutasiya etmək əvəzinə yeni obyekt qaytarır. Object.assign
ES6-da işləyir və polifil tələb edir.
Yayma sintaksisi ilə də obyektləri mutasiyasız yeniləmək mümkündür:
function updateColorMap(colormap) {
return {...colormap, right: 'mavi'};
}
Bu xüsusiyyət JavaScript-də ES2018-də əlavə olunub.
Create React App işlətdikdə Object.assign
funksiyası və obyekt yayma sintaksisi işləcəyək.
Dərin obyektlərin mutasiyasız yenilənməsi çətin ola bilər. Bu problem ilə qarşılaşdıqda Immer və ya immutability-helper kitabxanalarına baxın. Bu kitabxanalar mutasiyasızlığın faydalarını itirmədən rahat oxuna bilən kodun yazılmasına imkan yaradır.