Türkçe

React Profiler API'sinde ustalaşın. Pratik örnekler ve en iyi uygulamalarla performans darboğazlarını teşhis etmeyi, gereksiz yeniden render'ları düzeltmeyi ve uygulamanızı optimize etmeyi öğrenin.

Zirve Performansın Kilidini Açmak: React Profiler API'sine Derinlemesine Bir Bakış

Modern web geliştirme dünyasında, kullanıcı deneyimi her şeyden önemlidir. Akıcı, duyarlı bir arayüz, memnun bir kullanıcı ile hayal kırıklığına uğramış bir kullanıcı arasındaki belirleyici faktör olabilir. React kullanan geliştiriciler için karmaşık ve dinamik kullanıcı arayüzleri oluşturmak her zamankinden daha erişilebilir. Ancak, uygulamaların karmaşıklığı arttıkça, performans darboğazları riski de artar—yavaş etkileşimlere, takılan animasyonlara ve genel olarak kötü bir kullanıcı deneyimine yol açabilen ince verimsizlikler. İşte bu noktada React Profiler API, bir geliştiricinin cephaneliğinde vazgeçilmez bir araç haline gelir.

Bu kapsamlı kılavuz, sizi React Profiler'a derinlemesine bir yolculuğa çıkaracak. Ne olduğunu, hem React DevTools hem de programatik API'si aracılığıyla nasıl etkili bir şekilde kullanılacağını ve en önemlisi, yaygın performans sorunlarını teşhis etmek ve düzeltmek için çıktısını nasıl yorumlayacağınızı keşfedeceğiz. Sonunda, performans analizini göz korkutucu bir görevden geliştirme iş akışınızın sistematik ve ödüllendirici bir parçası haline getirmek için donanımlı olacaksınız.

React Profiler API Nedir?

React Profiler, geliştiricilerin bir React uygulamasının performansını ölçmelerine yardımcı olmak için tasarlanmış özel bir araçtır. Birincil işlevi, uygulamanızda render edilen her bileşen hakkında zamanlama bilgisi toplamak, uygulamanızın hangi bölümlerinin render edilmesinin maliyetli olduğunu ve performans sorunlarına neden olabileceğini belirlemenize olanak tanımaktır.

Şu gibi kritik soruları yanıtlar:

React Profiler'ı Chrome DevTools'daki Performans sekmesi veya Lighthouse gibi genel amaçlı tarayıcı performans araçlarından ayırmak önemlidir. Bu araçlar genel sayfa yüklemesini, ağ isteklerini ve betik yürütme süresini ölçmek için mükemmel olsa da, React Profiler size React ekosistemi içinde odaklanmış, bileşen düzeyinde bir performans görünümü sunar. React yaşam döngüsünü anlar ve state değişiklikleri, prop'lar ve context ile ilgili diğer araçların göremediği verimsizlikleri tespit edebilir.

Profiler başlıca iki biçimde mevcuttur:

  1. React DevTools Uzantısı: Doğrudan tarayıcınızın geliştirici araçlarına entegre edilmiş, kullanıcı dostu, grafiksel bir arayüz. Profil oluşturmaya başlamanın en yaygın yolu budur.
  2. Programatik `` Bileşeni: Performans ölçümlerini programatik olarak toplamak için doğrudan JSX kodunuza ekleyebileceğiniz bir bileşen. Bu, otomatik testler veya metrikleri bir analitik hizmetine göndermek için kullanışlıdır.

En önemlisi, Profiler geliştirme ortamları için tasarlanmıştır. Profil oluşturmanın etkinleştirildiği özel bir production build'i mevcut olsa da, React'in standart production build'i bu işlevselliği kaldırarak kütüphaneyi son kullanıcılarınız için olabildiğince yalın ve hızlı tutar.

Başlarken: React Profiler Nasıl Kullanılır

Pratiğe geçelim. Uygulamanızın profilini çıkarmak basit bir süreçtir ve her iki yöntemi de anlamak size maksimum esneklik sağlayacaktır.

Yöntem 1: React DevTools Profiler Sekmesi

Günlük performans hata ayıklamalarının çoğu için, React DevTools'daki Profiler sekmesi başvuracağınız araçtır. Eğer kurulu değilse, ilk adım budur—tercih ettiğiniz tarayıcı (Chrome, Firefox, Edge) için uzantıyı edinin.

İşte ilk profil oluşturma oturumunuzu çalıştırmak için adım adım bir kılavuz:

  1. Uygulamanızı Açın: Geliştirme modunda çalışan React uygulamanıza gidin. Tarayıcınızın uzantı çubuğunda React simgesini görürseniz DevTools'un aktif olduğunu anlarsınız.
  2. Geliştirici Araçlarını Açın: Tarayıcınızın geliştirici araçlarını açın (genellikle F12 veya Ctrl+Shift+I / Cmd+Option+I ile) ve "Profiler" sekmesini bulun. Çok sayıda sekmeniz varsa, bir "»" okunun arkasında gizlenmiş olabilir.
  3. Profil Oluşturmaya Başlayın: Profiler kullanıcı arayüzünde mavi bir daire (kayıt düğmesi) göreceksiniz. Performans verilerini kaydetmeye başlamak için tıklayın.
  4. Uygulamanızla Etkileşime Geçin: Ölçmek istediğiniz eylemi gerçekleştirin. Bu, bir sayfa yüklemekten, bir modal açan bir düğmeye tıklamaktan, bir forma yazmaktan veya büyük bir listeyi filtrelemekten herhangi bir şey olabilir. Amaç, yavaş hissettiren kullanıcı etkileşimini yeniden üretmektir.
  5. Profil Oluşturmayı Durdurun: Etkileşimi tamamladıktan sonra, oturumu durdurmak için kayıt düğmesine (şimdi kırmızı olacaktır) tekrar tıklayın.

İşte bu kadar! Profiler topladığı verileri işleyecek ve size o etkileşim sırasındaki uygulamanızın render performansının ayrıntılı bir görselleştirmesini sunacaktır.

Yöntem 2: Programatik `Profiler` Bileşeni

DevTools etkileşimli hata ayıklama için harika olsa da, bazen performans verilerini otomatik olarak toplamanız gerekir. `react` paketinden dışa aktarılan `` bileşeni tam olarak bunu yapmanıza olanak tanır.

Bileşen ağacınızın herhangi bir bölümünü `` bileşeniyle sarmalayabilirsiniz. İki prop gerektirir:

İşte bir kod örneği:

import React, { Profiler } from 'react';

// onRender callback fonksiyonu
function onRenderCallback(
  id, // az önce "commit" edilen Profiler ağacının "id" prop'u
  phase, // "mount" (ağaç yeni mount edildiyse) veya "update" (yeniden render edildiyse)
  actualDuration, // commit edilen güncellemeyi render etme süresi
  baseDuration, // memoization olmadan tüm alt ağacı render etme tahmini süresi
  startTime, // React'in bu güncellemeyi render etmeye başladığı zaman
  commitTime, // React'in bu güncellemeyi commit ettiği zaman
  interactions // güncellemeyi tetikleyen etkileşimler kümesi
) {
  // Bu verileri loglayabilir, bir analitik uç noktasına gönderebilir veya toplayabilirsiniz.
  console.log({
    id,
    phase,
    actualDuration,
    baseDuration,
    startTime,
    commitTime,
  });
}

function App() {
  return (
    
); }

`onRender` Callback Parametrelerini Anlamak:

Profiler Çıktısını Yorumlama: Rehberli Bir Tur

React DevTools'da bir kayıt oturumunu durdurduktan sonra, size zengin bir bilgi sunulur. Arayüzün ana bölümlerini inceleyelim.

Commit Seçici

Profiler'ın en üstünde bir çubuk grafik göreceksiniz. Bu grafikteki her çubuk, kaydınız sırasında React'in DOM'a yaptığı tek bir "commit"i temsil eder. Çubuğun yüksekliği ve rengi, o commit'in render edilmesinin ne kadar sürdüğünü gösterir—daha uzun, sarı/turuncu çubuklar, daha kısa, mavi/yeşil çubuklardan daha maliyetlidir. Her bir render döngüsünün ayrıntılarını incelemek için bu çubuklara tıklayabilirsiniz.

Alev Grafiği (Flamegraph)

Bu en güçlü görselleştirmedir. Seçilen bir commit için alev grafiği, uygulamanızda hangi bileşenlerin render edildiğini gösterir. İşte nasıl okunacağı:

Sıralı Grafik (Ranked Chart)

Alev grafiği çok karmaşık geliyorsa, Sıralı grafik görünümüne geçebilirsiniz. Bu görünüm, seçilen commit sırasında render edilen tüm bileşenleri, render edilmesi en uzun sürenden başlayarak sıralar. En maliyetli bileşenlerinizi anında belirlemenin harika bir yoludur.

Bileşen Ayrıntıları Paneli

Alev Grafiği veya Sıralı Grafikte belirli bir bileşene tıkladığınızda, sağda bir ayrıntılar paneli belirir. En eyleme geçirilebilir bilgileri bulacağınız yer burasıdır:

Yaygın Performans Darboğazları ve Nasıl Düzeltilir

Artık performans verilerini nasıl toplayacağınızı ve okuyacağınızı bildiğinize göre, Profiler'ın ortaya çıkarmaya yardımcı olduğu yaygın sorunları ve bunları çözmek için standart React desenlerini keşfedelim.

Sorun 1: Gereksiz Yeniden Render'lar

Bu, React uygulamalarındaki en yaygın performans sorunudur. Bir bileşenin, çıktısı tamamen aynı olacak olmasına rağmen yeniden render olması durumunda ortaya çıkar. Bu, CPU döngülerini boşa harcar ve kullanıcı arayüzünüzün yavaşlamasına neden olabilir.

Teşhis:

Çözüm 1: `React.memo()`

`React.memo`, bileşeninizi hafızaya alan (memoize eden) bir higher-order component'tir (HOC). Bileşenin önceki ve yeni prop'larının yüzeysel (shallow) bir karşılaştırmasını yapar. Prop'lar aynıysa, React bileşeni yeniden render etmeyi atlar ve son render edilen sonucu yeniden kullanır.

`React.memo` Öncesi:**

function UserAvatar({ userName, avatarUrl }) {
  console.log(`${userName} için UserAvatar render ediliyor`)
  return {userName};
}

// Üst bileşende:
// Eğer üst bileşen herhangi bir nedenle (örneğin, kendi state'i değişirse) yeniden render olursa,
// userName ve avatarUrl aynı olsa bile UserAvatar yeniden render edilir.

`React.memo` Sonrası:**

import React from 'react';

const UserAvatar = React.memo(function UserAvatar({ userName, avatarUrl }) {
  console.log(`${userName} için UserAvatar render ediliyor`)
  return {userName};
});

// Artık, UserAvatar SADECE userName veya avatarUrl prop'ları gerçekten değişirse yeniden render edilir.

Çözüm 2: `useCallback()`

`React.memo`, nesneler veya fonksiyonlar gibi ilkel olmayan değerlere sahip prop'lar tarafından bozulabilir. JavaScript'te, `() => {} !== () => {}`. Her render'da yeni bir fonksiyon oluşturulur, bu nedenle hafızaya alınmış bir bileşene prop olarak bir fonksiyon geçirirseniz, yine de yeniden render olacaktır.

`useCallback` hook'u, bu sorunu, callback fonksiyonunun yalnızca bağımlılıklarından biri değiştiğinde değişen hafızaya alınmış bir sürümünü döndürerek çözer.

`useCallback` Öncesi:**

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

  // Bu fonksiyon ParentComponent'in her render'ında yeniden oluşturulur
  const handleItemClick = (id) => {
    console.log('Tıklanan öğe', id);
  };

  return (
    
{/* MemoizedListItem, handleItemClick yeni bir fonksiyon olduğu için count her değiştiğinde yeniden render edilir */}
); }

`useCallback` Sonrası:**

import { useState, useCallback } from 'react';

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

  // Bu fonksiyon artık hafızaya alınmıştır ve bağımlılıkları (boş dizi) değişmedikçe yeniden oluşturulmaz.
  const handleItemClick = useCallback((id) => {
    console.log('Tıklanan öğe', id);
  }, []); // Boş bağımlılık dizisi, yalnızca bir kez oluşturulduğu anlamına gelir

  return (
    
{/* Artık, MemoizedListItem count değiştiğinde yeniden render EDİLMEZ */}
); }

Çözüm 3: `useMemo()`

`useCallback`'e benzer şekilde, `useMemo` değerleri hafızaya almak içindir. Maliyetli hesaplamalar veya her render'da yeniden oluşturmak istemediğiniz karmaşık nesneler/diziler oluşturmak için mükemmeldir.

`useMemo` Öncesi:**

function ProductList({ products, filterTerm }) {
  // Bu pahalı filtreleme işlemi, ProductList'in HER render'ında çalışır,
  // alakasız bir prop değişse bile.
  const visibleProducts = products.filter(p => p.name.includes(filterTerm));

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

`useMemo` Sonrası:**

import { useMemo } from 'react';

function ProductList({ products, filterTerm }) {
  // Bu hesaplama artık yalnızca `products` veya `filterTerm` değiştiğinde çalışır.
  const visibleProducts = useMemo(() => {
    return products.filter(p => p.name.includes(filterTerm));
  }, [products, filterTerm]);

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

Sorun 2: Büyük ve Maliyetli Bileşen Ağaçları

Bazen sorun gereksiz yeniden render'lar değil, bileşen ağacının çok büyük olması veya ağır hesaplamalar yapması nedeniyle tek bir render'ın gerçekten yavaş olmasıdır.

Teşhis:

  • Alev Grafiği'nde, çok geniş, sarı veya kırmızı bir çubuğa sahip tek bir bileşen görürsünüz, bu da yüksek bir `baseDuration` ve `actualDuration` olduğunu gösterir.
  • Bu bileşen göründüğünde veya güncellendiğinde kullanıcı arayüzü donar veya takılır.

Çözüm: Windowing / Sanallaştırma (Virtualization)

Uzun listeler veya büyük veri tabloları için en etkili çözüm, yalnızca kullanıcının o anda görüntü alanında görebildiği öğeleri render etmektir. Bu tekniğe "windowing" veya "sanallaştırma" denir. 10.000 liste öğesini render etmek yerine, yalnızca ekrana sığan 20 tanesini render edersiniz. Bu, DOM düğümlerinin sayısını ve render için harcanan zamanı büyük ölçüde azaltır.

Bunu sıfırdan uygulamak karmaşık olabilir, ancak bunu kolaylaştıran mükemmel kütüphaneler vardır:

  • `react-window` ve `react-virtualized`, sanallaştırılmış listeler ve tablolar oluşturmak için popüler, güçlü kütüphanelerdir.
  • Daha yakın zamanda, `TanStack Virtual` gibi kütüphaneler, son derece esnek olan arayüzsüz (headless), hook tabanlı yaklaşımlar sunar.

Sorun 3: Context API Tuzakları

React Context API, prop drilling'den (prop'ları derinlemesine aktarma) kaçınmak için güçlü bir araçtır, ancak önemli bir performans uyarısı vardır: bir context'i tüketen herhangi bir bileşen, o context'teki herhangi bir değer değiştiğinde yeniden render edilir, bileşen o belirli veri parçasını kullanmasa bile.

Teşhis:

  • Genel context'inizde tek bir değeri güncellersiniz (örneğin, bir tema değiştirici).
  • Profiler, temanızla tamamen alakasız bileşenler de dahil olmak üzere tüm uygulamanızdaki çok sayıda bileşenin yeniden render edildiğini gösterir.
  • "Why did this render?" paneli bu bileşenler için "Context değişti" gösterir.

Çözüm: Context'lerinizi Bölün

Bunu çözmenin en iyi yolu, devasa, monolitik bir `AppContext` oluşturmaktan kaçınmaktır. Bunun yerine, genel state'inizi birden çok, daha küçük, daha ayrıntılı context'lere bölün.

Önce (Kötü Uygulama):**

// AppContext.js
const AppContext = createContext({ 
  currentUser: null, 
  theme: 'light', 
  language: 'en',
  setTheme: () => {}, 
  // ... ve diğer 20 değer
});

// MyComponent.js
// Bu bileşen yalnızca currentUser'a ihtiyaç duyar, ancak tema değiştiğinde yeniden render edilir!
const { currentUser } = useContext(AppContext);

Sonra (İyi Uygulama):**

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

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

// MyComponent.js
// Bu bileşen artık SADECE currentUser değiştiğinde yeniden render edilir.
const currentUser = useContext(UserContext);

Gelişmiş Profil Oluşturma Teknikleri ve En İyi Uygulamalar

Production Profiling için Build Alma

Varsayılan olarak, `` bileşeni bir production build'inde hiçbir şey yapmaz. Etkinleştirmek için, uygulamanızı özel `react-dom/profiling` build'ini kullanarak oluşturmanız gerekir. Bu, hala profil oluşturma enstrümantasyonunu içeren production'a hazır bir paket oluşturur.

Bunu nasıl etkinleştireceğiniz build aracınıza bağlıdır. Örneğin, Webpack ile yapılandırmanızda bir alias kullanabilirsiniz:

// webpack.config.js
module.exports = {
  // ... diğer yapılandırmalar
  resolve: {
    alias: {
      'react-dom$': 'react-dom/profiling',
    },
  },
};

Bu, canlıya alınmış, production için optimize edilmiş sitenizde gerçek dünya performans sorunlarını ayıklamak için React DevTools Profiler'ını kullanmanıza olanak tanır.

Performansa Proaktif Bir Yaklaşım

Kullanıcıların yavaşlıktan şikayet etmesini beklemeyin. Performans ölçümünü geliştirme iş akışınıza entegre edin:

  • Erken Profil Çıkarın, Sık Profil Çıkarın: Yeni özellikleri oluştururken düzenli olarak profilini çıkarın. Kod zihninizde tazeyken bir darboğazı düzeltmek çok daha kolaydır.
  • Performans Bütçeleri Oluşturun: Kritik etkileşimler için bütçeler belirlemek üzere programatik `` API'sini kullanın. Örneğin, ana kontrol panelinizin mount edilmesinin asla 200 ms'den fazla sürmemesi gerektiğini iddia edebilirsiniz.
  • Performans Testlerini Otomatikleştirin: Bir render çok uzun sürerse başarısız olan otomatik testler oluşturmak için programatik API'yi Jest veya Playwright gibi test çerçeveleriyle birlikte kullanabilir, böylece performans gerilemelerinin birleştirilmesini önleyebilirsiniz.

Sonuç

Performans optimizasyonu sonradan düşünülecek bir şey değildir; yüksek kaliteli, profesyonel web uygulamaları oluşturmanın temel bir yönüdür. React Profiler API, hem DevTools hem de programatik formlarıyla, render sürecini anlaşılır kılar ve bilinçli kararlar vermek için gereken somut verileri sağlar.

Bu araçta ustalaşarak, performans hakkında tahmin yürütmekten darboğazları sistematik olarak belirlemeye, `React.memo`, `useCallback` ve sanallaştırma gibi hedeflenmiş optimizasyonları uygulamaya ve nihayetinde uygulamanızı diğerlerinden ayıran hızlı, akıcı ve keyifli kullanıcı deneyimleri oluşturmaya geçebilirsiniz. Bugün profil oluşturmaya başlayın ve React projelerinizde bir sonraki performans seviyesinin kilidini açın.