Verimli React Bileşenleri: React Performansını Optimize Etme Rehberi
Yayınlanan: 2022-03-11React, piyasaya sürülmesinden bu yana, ön uç geliştiricilerin web uygulamaları oluşturma düşüncesini değiştirdi. Sanal DOM ile React, UI güncellemelerini olabildiğince verimli hale getirerek web uygulamanızı daha hızlı hale getirir. Ancak orta büyüklükteki React web uygulamaları neden hala düşük performans gösteriyor?
İpucu, React'i nasıl kullandığınızda.
React gibi modern bir ön uç kitaplığı, uygulamanızı sihirli bir şekilde daha hızlı hale getirmez. Geliştiricinin, React'in nasıl çalıştığını ve bileşenlerin, bileşen yaşam döngüsünün çeşitli aşamalarında nasıl yaşadığını anlamasını gerektirir.
React ile, bileşenlerinizin nasıl ve ne zaman oluşturulduğunu ölçerek ve optimize ederek sunduğu birçok performans iyileştirmesini elde edebilirsiniz. Ve React, bunu kolaylaştırmak için gerekli araçları ve işlevleri sağlar.
Bu React eğitiminde, React bileşenlerinizin performansını nasıl ölçebileceğinizi ve çok daha performanslı bir React web uygulaması oluşturmak için bunları nasıl optimize edebileceğinizi öğreneceksiniz. Ayrıca, birkaç JavaScript en iyi uygulamasının React web uygulamanızın çok daha akıcı bir kullanıcı deneyimi sunmasına nasıl yardımcı olduğunu da öğreneceksiniz.
Tepki Nasıl Çalışır?
Optimizasyon tekniklerine dalmadan önce, React'in nasıl çalıştığını daha iyi anlamamız gerekiyor.
React geliştirmenin özünde, basit ve bariz JSX sözdizimine ve React'in sanal DOM'ler oluşturma ve karşılaştırma yeteneğine sahipsiniz. Piyasaya sürülmesinden bu yana, React diğer birçok ön uç kitaplığı etkiledi. Vue.js gibi kitaplıklar da sanal DOM fikrine güveniyor.
React şu şekilde çalışır:
Her React uygulaması bir kök bileşenle başlar ve bir ağaç oluşumundaki birçok bileşenden oluşur. React'teki bileşenler, aldığı verilere (sahneler ve durum) dayalı olarak kullanıcı arayüzünü oluşturan "işlevlerdir".
Bunu F
olarak sembolize edebiliriz.
UI = F(data)
Kullanıcılar UI ile etkileşime girer ve verilerin değişmesine neden olur. Etkileşim ister bir düğmeye tıklamayı, bir görüntüye dokunmayı, liste öğelerini etrafa sürüklemeyi, ister AJAX istekleri, API'leri çağırmayı vb. içeriyor olsun, tüm bu etkileşimler yalnızca verileri değiştirir. Kullanıcı arayüzünün doğrudan değişmesine asla neden olmazlar.
Burada veriler, yalnızca veritabanınızda depoladıklarınızı değil, web uygulamasının durumunu tanımlayan her şeydir. Hatta ön uç durumlarının bitleri (örneğin, şu anda hangi sekmenin seçili olduğu veya şu anda bir onay kutusunun işaretli olup olmadığı) bu verilerin bir parçasıdır.
Bu verilerde bir değişiklik olduğunda, React, kullanıcı arayüzünü yeniden oluşturmak için bileşen işlevlerini kullanır, ancak yalnızca sanal olarak:
UI1 = F(data1) UI2 = F(data2)
React, sanal DOM'nin iki versiyonuna bir karşılaştırma algoritması uygulayarak mevcut kullanıcı arayüzü ile yeni kullanıcı arayüzü arasındaki farkları hesaplar.
Changes = Diff(UI1, UI2)
React daha sonra yalnızca UI değişikliklerini tarayıcıdaki gerçek UI'ye uygulamaya devam eder.
Bir bileşenle ilişkili veriler değiştiğinde, React gerçek bir DOM güncellemesinin gerekli olup olmadığını belirler. Bu, React'in tarayıcıda DOM düğümleri oluşturma ve var olanlara gerekliliğin ötesinde erişme gibi potansiyel olarak pahalı DOM manipülasyon işlemlerinden kaçınmasını sağlar.
Bileşenlerin bu tekrarlanan farklılaşması ve oluşturulması, herhangi bir React uygulamasındaki React performans sorunlarının birincil kaynaklarından biri olabilir. Farklılaşma algoritmasının etkili bir şekilde uzlaşamadığı ve tüm uygulamanın tekrar tekrar oluşturulmasına neden olan bir React uygulaması oluşturmak, sinir bozucu derecede yavaş bir deneyime neden olabilir.
Optimizasyona Nereden Başlanmalı?
Peki optimize ettiğimiz şey tam olarak nedir?
Görüyorsunuz, ilk oluşturma işlemi sırasında React, aşağıdaki gibi bir DOM ağacı oluşturur:
Veri değişikliklerinin bir kısmı göz önüne alındığında, React'in yapmasını istediğimiz şey, yalnızca değişiklikten doğrudan etkilenen bileşenleri yeniden oluşturmak (ve muhtemelen bileşenlerin geri kalanı için fark sürecini bile atlamak):
Ancak, React'in sonunda yaptığı şey:
Yukarıdaki resimde, tüm sarı düğümler işlenir ve ayrılır, bu da zaman/hesaplama kaynaklarının boşa gitmesine neden olur. Optimizasyon çalışmalarımızı öncelikle buraya koyacağız. Her bileşeni yalnızca gerekli olduğunda render-diff için yapılandırmak, bu boşa harcanan CPU döngülerini geri kazanmamızı sağlayacaktır.
React kitaplığının geliştiricileri bunu dikkate aldı ve tam da bunu yapmamız için bize bir kanca sağladı: React'e bir bileşeni oluşturmayı atlamanın ne zaman uygun olduğunu söylememizi sağlayan bir işlev.
İlk Ölçüm
Rob Pike'ın programlama kurallarından biri olarak oldukça zarif bir şekilde belirttiği gibi:
Ölçüm. Ölçene kadar hız için ayarlama yapmayın ve o zaman bile kodun bir kısmı geri kalanını boğmadıkça yapmayın.
Uygulamanızı yavaşlattığını düşündüğünüz kodu optimize etmeye başlamayın. Bunun yerine, React performans ölçüm araçlarının size yol boyunca rehberlik etmesine izin verin.
React'in sadece bunun için güçlü bir aracı var. react-addons-perf
kitaplığını kullanarak, uygulamanızın genel performansına ilişkin bir genel bakış elde edebilirsiniz.
Kullanımı çok basittir:
Import Perf from 'react-addons-perf' Perf.start(); // use the app Perf.stop(); Perf.printWasted();
Bu, oluşturmada harcanan zaman bileşenlerinin miktarını içeren bir tablo yazdıracaktır.
Kitaplık, boşa harcanan zamanın farklı yönlerini ayrı ayrı yazdırmanıza (örneğin, printInclusive()
veya printExclusive()
işlevlerini kullanarak) ve hatta DOM işleme işlemlerini ( printOperations()
işlevini kullanarak) yazdırmanıza izin veren başka işlevler sağlar.
Kıyaslamayı Bir Adım Daha İleriye Taşımak
Görsel bir insansanız, o zaman react-perf-tool
tam ihtiyacınız olan şeydir.
react-perf-tool
, react-addons-perf
kitaplığını temel alır. React uygulamanızın performansında hata ayıklamanın daha görsel bir yolunu sunar. Ölçümleri almak için temeldeki kitaplığı kullanır ve ardından bunları grafikler olarak görselleştirir.
Çoğu zaman bu, darboğazları tespit etmenin çok daha uygun bir yoludur. Uygulamanıza bileşen olarak ekleyerek rahatlıkla kullanabilirsiniz.
React Bileşeni Güncellemeli mi?
Varsayılan olarak, React çalışacak, sanal DOM'yi oluşturacak ve ağaçtaki her bileşen için, donanım veya durumundaki herhangi bir değişiklik için farkı karşılaştıracaktır. Ama bunun mantıklı olmadığı açık.
Uygulamanız büyüdükçe, her eylemde tüm sanal DOM'yi yeniden oluşturmaya ve karşılaştırmaya çalışmak sonunda yavaşlayacaktır.
React, geliştiricinin bir bileşenin yeniden oluşturulması gerekip gerekmediğini belirtmesi için basit bir yol sağlar. İşte burada shouldComponentUpdate
yöntemi devreye girer.
function shouldComponentUpdate(nextProps, nextState) { return true; }
Bu işlev herhangi bir bileşen için true değerini döndürdüğünde, render-diff işleminin tetiklenmesine izin verir.
Bu size render-diff sürecini kontrol etmenin basit bir yolunu sunar. Bir bileşenin yeniden oluşturulmasını engellemeniz gerektiğinde, işlevden false
döndürmeniz yeterlidir. İşlevin içinde, yeniden oluşturmanın gerekli olup olmadığını belirlemek için mevcut ve sonraki sahne ve durum setini karşılaştırabilirsiniz:

function shouldComponentUpdate(nextProps, nextState) { return nextProps.id !== this.props.id; }
Bir React.PureComponent Kullanma
Bu optimizasyon tekniğini biraz kolaylaştırmak ve otomatikleştirmek için React, "saf" bileşen olarak bilinen şeyi sağlar. Bir React.PureComponent
, sığ bir destek ve durum karşılaştırması ile bir shouldComponentUpdate()
işlevini uygulayan bir React.Component
gibidir.
Bir React.PureComponent
aşağı yukarı şuna eşdeğerdir:
class MyComponent extends React.Component { shouldComponentUpdate(nextProps, nextState) { return shallowCompare(this.props, nextProps) && shallowCompare(this.state, nextState); } … }
Yalnızca yüzeysel bir karşılaştırma yaptığından, yalnızca şu durumlarda yararlı bulabilirsiniz:
- Destekleriniz veya durumlarınız ilkel veriler içeriyor.
- Donanımlarınız ve durumlarınız karmaşık verilere sahiptir, ancak bileşeninizi güncellemek için ne zaman
forceUpdate()
arayacağınızı bilirsiniz.
Verileri Değiştirilemez Hale Getirmek
Ya bir React.PureComponent
kullanabilseydiniz, ancak yine de herhangi bir karmaşık donanım veya durumun ne zaman otomatik olarak değiştiğini söylemenin etkili bir yolunu bulduysanız? Değişmez veri yapılarının hayatı kolaylaştırdığı yer burasıdır.
Değişmez veri yapılarını kullanmanın ardındaki fikir basittir. Karmaşık veriler içeren bir nesne değiştiğinde, o nesnede değişiklik yapmak yerine, o nesnenin değişikliklerle birlikte bir kopyasını oluşturun. Bu, verilerdeki değişiklikleri algılamayı, iki nesnenin referansını karşılaştırmak kadar basit hale getirir.
Object.assign
veya _.extend
kullanabilirsiniz (Underscore.js veya Lodash'tan):
const newValue2 = Object.assign({}, oldValue); const newValue2 = _.extend({}, oldValue);
Daha da iyisi, değişmez veri yapıları sağlayan bir kitaplık kullanabilirsiniz:
var map1 = Immutable.Map({a:1, b:2, c:3}); var map2 = map1.set('b', 2); assert(map1.equals(map2) === true); var map3 = map1.set('b', 50); assert(map1.equals(map3) === false);
Burada, Immutable.Map
, Immutable.js kitaplığı tarafından sağlanır.
Bir harita kendi yöntem set
her güncellendiğinde, yalnızca küme işlemi temel değeri değiştirdiğinde yeni bir harita döndürülür. Aksi takdirde, aynı harita döndürülür.
Değişmez veri yapılarını kullanma hakkında daha fazla bilgiyi buradan edinebilirsiniz.
Daha Fazla React Uygulama Optimizasyon Tekniği
Üretim Yapısını Kullanma
Bir React uygulaması geliştirirken size gerçekten faydalı uyarılar ve hata mesajları sunulur. Bunlar, geliştirme sırasındaki hataları ve sorunları tanımlamayı bir mutluluk haline getirir. Ama bir performans pahasına gelirler.
React'in kaynak koduna bakarsanız, birçok if (process.env.NODE_ENV != 'production')
denetimi görürsünüz. React'in geliştirme ortamınızda çalıştırdığı bu kod parçaları, son kullanıcının ihtiyaç duyduğu bir şey değildir. Üretim ortamları için bu gereksiz kodların tümü atılabilir.
Projenizi create-react-app
kullanarak önyüklediyseniz, bu ekstra kod olmadan üretim derlemesini üretmek için npm run build
. Webpack'i doğrudan kullanıyorsanız, webpack webpack -p
çalıştırabilirsiniz (bu, webpack --optimize-minimize --define process.env.NODE_ENV="'production'"
ile eşdeğerdir).
Bağlama İşlevleri Erken
Render işlevinin içindeki bileşenin bağlamına bağlı işlevleri görmek çok yaygındır. Bu, genellikle, alt bileşenlerin olaylarını işlemek için bu işlevleri kullandığımızda geçerlidir.
// Creates a new `handleUpload` function during each render() <TopBar onUpload={this.handleUpload.bind(this)} /> // ...as do inlined arrow functions <TopBar onUpload={files => this.handleUpload(files)} />
Bu, render()
işlevinin her işlemede yeni bir işlev oluşturmasına neden olur. Aynı şeyi yapmanın çok daha iyi bir yolu:
class App extends React.Component { constructor(props) { super(props); this.handleUpload = this.handleUpload.bind(this); } render() { … <TopBar onUpload={this.handleUpload} /> … } }
Birden Çok Parça Dosyası Kullanma
Tek sayfalı React web uygulamaları için, genellikle tüm ön uç JavaScript kodumuzu tek bir küçültülmüş dosyada topluyoruz. Bu, küçük ve orta ölçekli web uygulamaları için iyi çalışır. Ancak uygulama büyümeye başladıkça, paket halindeki bu JavaScript dosyasını tarayıcıya teslim etmek zaman alıcı bir süreç haline gelebilir.
React uygulamanızı oluşturmak için Webpack kullanıyorsanız, yerleşik uygulama kodunuzu birden fazla "parçaya" ayırmak ve bunları gerektiği gibi tarayıcıya teslim etmek için kod bölme özelliklerinden yararlanabilirsiniz.
İki tür bölme vardır: kaynak bölme ve isteğe bağlı kod bölme.
Kaynak bölme ile kaynak içeriğini birden çok dosyaya bölersiniz. Örneğin, CommonsChunkPlugin'i kullanarak ortak kodu (tüm harici kitaplıklar gibi) kendi "yığın" dosyasına ayıklayabilirsiniz. ExtractTextWebpackPlugin'i kullanarak tüm CSS kodunu ayrı bir CSS dosyasına çıkarabilirsiniz.
Bu tür bir bölme iki şekilde yardımcı olacaktır. Tarayıcının daha az sıklıkla değişen kaynakları önbelleğe almasına yardımcı olur. Ayrıca, yükleme süresini potansiyel olarak azaltmak için tarayıcının paralel indirmeden yararlanmasına yardımcı olacaktır.
Webpack'in daha dikkate değer bir özelliği, isteğe bağlı kod bölmedir. Kodu, isteğe bağlı olarak yüklenebilecek bir yığına bölmek için kullanabilirsiniz. Bu, ilk indirmeyi küçük tutabilir ve uygulamanın yüklenmesi için gereken süreyi azaltabilir. Tarayıcı daha sonra uygulamanın ihtiyaç duyduğu diğer kod parçalarını istek üzerine indirebilir.
Web paketi kod bölme hakkında daha fazla bilgiyi buradan edinebilirsiniz.
Web Sunucunuzda Gzip'i Etkinleştirme
React uygulamasının paket JS dosyaları genellikle çok büyüktür, bu nedenle web sayfasının daha hızlı yüklenmesini sağlamak için web sunucusunda (Apache, Nginx, vb.) Gzip'i etkinleştirebiliriz.
Modern tarayıcıların tümü, HTTP istekleri için Gzip sıkıştırmasını destekler ve otomatik olarak görüşür. Gzip sıkıştırmasını etkinleştirmek, aktarılan yanıtın boyutunu %90'a kadar azaltabilir, bu da kaynağı indirme süresini önemli ölçüde azaltabilir, istemci için veri kullanımını azaltabilir ve sayfalarınızın ilk kez oluşturulma süresini iyileştirebilir.
Sıkıştırmayı nasıl etkinleştireceğiniz konusunda web sunucunuzun belgelerine bakın:
- Apache: mod_deflate kullanın
- Nginx: ngx_http_gzip_module kullanın
Eslint-eklenti-tepkisini kullanma
Neredeyse tüm JavaScript projeleri için ESLint kullanmalısınız. Tepki de farklı değil.
eslint-plugin-react
ile, uzun vadede kodunuza fayda sağlayabilecek ve kötü yazılmış kod nedeniyle ortaya çıkan birçok yaygın sorunu ve sorunu önleyebilecek React programlamadaki birçok kurala uyum sağlamaya zorlarsınız.
React Web Uygulamalarınızı Yeniden Hızlı Hale Getirin
React'ten en iyi şekilde yararlanmak için araçlarından ve tekniklerinden yararlanmanız gerekir. Bir React web uygulamasının performansı, bileşenlerinin basitliğinde yatar. Render-diff algoritmasının ezici olması, uygulamanızın sinir bozucu şekillerde kötü performans göstermesine neden olabilir.
Uygulamanızı optimize etmeden önce, React bileşenlerinin nasıl çalıştığını ve tarayıcıda nasıl oluşturulduklarını anlamanız gerekir. React yaşam döngüsü yöntemleri, bileşeninizin gereksiz yere yeniden oluşturulmasını önlemenin yollarını sunar. Bu darboğazları ortadan kaldırın ve kullanıcılarınızın hak ettiği uygulama performansına sahip olacaksınız.
Bir React web uygulamasını optimize etmenin daha fazla yolu olsa da, bileşenleri yalnızca gerektiğinde güncellenecek şekilde hassas şekilde ayarlamak en iyi performans iyileştirmesini sağlar.
React web uygulaması performansınızı nasıl ölçer ve optimize edersiniz? Aşağıdaki yorumlarda paylaşın.