React SPA performans optimizasyonuyla ilgili gerçek bir örnek olay.
Web sitesi performansı yalnızca yükleme süresiyle ilgili değildir. Özellikle kullanıcıların her gün kullandığı üretkenlik masaüstü uygulamaları için kullanıcılara hızlı ve duyarlı bir deneyim sunmak çok önemlidir. Recruit Technologies'ın mühendislik ekibi, web uygulamalarından biri olan AirSHIFT'i kullanıcı girişi performansını iyileştirmek için yeniden yapılandırmaya tabi tuttu. Nasıl yaptıklarına bakalım.
Yavaş yanıt, daha düşük üretkenlik
AirSHIFT, restoran ve kafe gibi mağaza sahiplerinin personellerinin vardiyalı çalışma düzenini yönetmesine yardımcı olan bir masaüstü web uygulamasıdır. React ile oluşturulan tek sayfalık uygulama; gün, hafta, ay vb. bazı ölçütlere göre düzenlenmiş vardiya programlarının yer aldığı çeşitli ızgara tabloları da dahil olmak üzere zengin müşteri özellikleri sunar.
Recruit Technologies mühendislik ekibi, AirSHIFT uygulamasına yeni özellikler ekledikçe yavaş performansla ilgili daha fazla geri bildirim almaya başladı. AirSHIFT'in mühendislik müdürü Yosuke Furukawa şöyle diyor:
Bir kullanıcı araştırması çalışmasında, mağaza sahiplerinden biri, vardiya tablosunun yüklenmesini beklerken zaman geçirmek için düğmeyi tıkladıktan sonra koltuğundan kalkıp kahve yaptığını söyledi. Bu durum bizi şaşırttı.
Araştırmayı tamamladıktan sonra mühendislik ekibi, kullanıcıların çoğunun 10 yıl önceki 1 GHz Celeron M dizüstü bilgisayar gibi düşük özellikli bilgisayarlara devasa değiştirme tabloları yüklemeye çalıştığını fark etti.
AirSHIFT uygulaması, pahalı komut dosyaları içeren ana iş parçacığını engelliyordu ancak hızlı kablosuz bağlantıları olan zengin özellikli bilgisayarlar üzerinde geliştirme ve test yaptıkları için mühendislik ekibi komut dosyalarının ne kadar pahalı olduğunu fark edemedi.
Chrome DevTools'ta CPU ve ağ tarama özelliği etkinken performanslarının profilini oluşturduktan sonra, performans optimizasyonuna ihtiyaç duyulduğu anlaşıldı. AirSHIFT bu sorunu çözmek için bir görev gücü oluşturdu. Uygulamalarını kullanıcı girişlerine daha duyarlı hale getirmek için odaklandıkları 5 konuyu aşağıda bulabilirsiniz.
1. Büyük tabloları sanallaştırma
Kaydırma tablosunu görüntülemek birçok pahalı adım gerektiriyordu: sanal DOM'nin oluşturulması ve personel sayısının yanı sıra zaman aralıklarıyla orantılı olarak ekranda oluşturulması. Örneğin, bir restoranda 50 çalışan varsa ve aylık vardiya programlarını kontrol etmek istiyorsa 50 (çalışan) ile 30 (gün) çarpımı olan bir tablo oluşturulur. Bu tabloda oluşturulacak 1.500 hücre bileşeni olur. Bu işlem, özellikle düşük özellikli cihazlar için çok pahalıdır. Gerçekte durum daha kötüydü. Araştırma sonucunda, 200 personel yöneten mağazalar olduğunu ve tek bir aylık tabloda yaklaşık 6.000 hücre bileşeni gerektiğini öğrendiler.
AirSHIFT, bu işlemin maliyetini azaltmak için vardiya tablosunu sanallaştırdı. Uygulama artık yalnızca görüntü alanı içindeki bileşenleri ve ekran dışı bileşenlerin bağlantısını keser.
Bu durumda AirSHIFT, karmaşık iki boyutlu ızgara tablolarını etkinleştirmeyle ilgili şartlar olduğu için react-virtualized'ı kullandı. Ayrıca, uygulamayı gelecekte hafif react-window kullanmak üzere dönüştürmenin yollarını araştırıyorlar.
Sonuçlar
Tabloyu tek başına sanallaştırmak, kodlama süresini 6 saniye azalttı (4 kat CPU yavaşlatma + Hızlı 3G sınırlandırılan Macbook Pro ortamında). Bu, yeniden düzenleme projesinde en etkili performans iyileştirmesiydi.
2. User Timing API ile denetleme
Ardından AirSHIFT ekibi, kullanıcı girişinde çalışan komut dosyalarını yeniden düzenledi. Chrome Geliştirici Araçları'nın alev grafiği, ana iş parçacığında gerçekte neler olduğunu analiz etmenizi sağlar. Ancak AirSHIFT ekibi, React'in yaşam döngüsüne dayalı olarak uygulama etkinliğini analiz etmeyi daha kolay buldu.
React 16, performans izlemesini User Timing API aracılığıyla sağlar. Bu performans izlemeyi Chrome Geliştirici Araçları'nın Zamanlamalar bölümünden görselleştirebilirsiniz. AirSHIFT, React yaşam döngüsü etkinliklerinde çalışan gereksiz mantığı bulmak için Zamanlamalar bölümünü kullandı.
Sonuçlar
AirSHIFT ekibi, her rota navigasyonundan hemen önce gereksiz bir React Tree Mutabakatın gerçekleştiğini keşfetti. Bu, React'in gezinmelerden önce vardiya tablosunu gereksiz yere güncellediği anlamına geliyordu. Bu soruna, gereksiz bir Redux durum güncellemesi neden oluyordu. Bu sorunu düzeltmek yaklaşık 750 ms komut dosyası süresi tasarrufu sağladı. AirSHIFT, komut dosyası yazma süresinde toplam 1 saniyelik bir azalmaya yol açan diğer mikro optimizasyonları da yaptı.
3. Bileşenleri yavaşça yükleyin ve pahalı mantığı web işçilerine taşıyın
AirSHIFT'te yerleşik bir sohbet uygulaması vardır. Birçok mağaza sahibi, vardiya tablosuna bakarken personeliyle sohbet üzerinden iletişim kurar. Bu nedenle, tablo yüklenirken kullanıcı mesaj yazabilir. Ana iş parçacığı tabloyu oluşturan komut dosyalarıyla doluysa kullanıcı girişi kalitesiz olabilir.
AirSHIFT bu deneyimi iyileştirmek amacıyla artık gerçek bileşenleri geç yüklerken tablo içerikleri için yer tutucular göstermek üzere React.lazy ve Spause'u kullanıyor.
AirSHIFT ekibi, geç yüklenen bileşenlerdeki pahalı iş mantığının bir kısmını da web çalışanlarına taşıdı. Bu işlem, ana iş parçacığını serbest bırakarak kullanıcı girişi olumsuzluk sorununu çözdü. Böylece iş parçacığı kullanıcı girişine yanıt vermeye odaklanabildi.
Genellikle geliştiriciler, çalışanların kullanımında karmaşıklıklarla karşı karşıya kalırlar. Ancak bu kez işin zor kısmını Comlink üstlendi. Aşağıda, AirSHIFT'in en pahalı operasyonlardan birini, yani toplam işçilik maliyetlerini hesaplama işlemini nasıl yürüttüğüne ilişkin bir örnek verilmiştir.
Yükleme sırasında yedek içeriği göstermek için App.js'de React.lazy ve Suspense'i kullanın
/** App.js */
import React, { lazy, Suspense } from 'react'
// Lazily loading the Cost component with React.lazy
const Hello = lazy(() => import('./Cost'))
const Loading = () => (
<div>Some fallback content to show while loading</div>
)
// Showing the fallback content while loading the Cost component by Suspense
export default function App({ userInfo }) {
return (
<div>
<Suspense fallback={<Loading />}>
<Cost />
</Suspense>
</div>
)
}
Maliyet bileşeninde, hesaplama mantığını yürütmek için comlink işlevini kullanın.
/** Cost.js */
import React from 'react';
import { proxy } from 'comlink';
// import the workerlized calc function with comlink
const WorkerlizedCostCalc = proxy(new Worker('./WorkerlizedCostCalc.js'));
export default async function Cost({ userInfo }) {
// execute the calculation in the worker
const instance = await new WorkerlizedCostCalc();
const cost = await instance.calc(userInfo);
return <p>{cost}</p>;
}
Çalışanda çalışan hesaplama mantığını uygulayın ve comlink ile kullanıma sunun
// WorkerlizedCostCalc.js
import { expose } from 'comlink'
import { someExpensiveCalculation } from './CostCalc.js'
// Expose the new workerlized calc function with comlink
expose({
calc(userInfo) {
// run existing (expensive) function in the worker
return someExpensiveCalculation(userInfo);
}
}, self);
Sonuçlar
Deneme olarak çalıştırdığı mantık çok sınırlı olmasına rağmen AirSHIFT, JavaScript'inin yaklaşık 100 ms'lik kısmını ana iş parçacığından çalışan iş parçacığına kaydırdı (4 kat CPU kısıtlama ile simüle edildi).
AirSHIFT şu anda diğer bileşenleri gecikmeli olarak yükleyip yükleyemeyeceklerini ve gecikmeyi daha da azaltmak için web işçilerine daha fazla mantık aktarıp aktaramayacaklarını araştırıyor.
4. Performans bütçesi belirleme
Tüm bu optimizasyonları uyguladıktan sonra, uygulamanın zaman içinde yüksek performans göstermesini sağlamak çok önemliydi. AirSHIFT artık mevcut JavaScript ve CSS dosya boyutunu aşmamak için bundlesize değerini kullanıyor. Bu temel bütçeleri belirlemenin yanı sıra uygulamanın ideal olmayan koşullarda bile iyi performans gösterip göstermediğini kontrol etmek için vardiya tablosu yükleme süresinin çeşitli yüzdelik dilimlerini gösteren bir kontrol paneli oluşturdular.
- Artık her Redux etkinliğinin komut dosyası tamamlama süresi ölçülecek
- Performans verileri Elasticsearch'te toplanır.
- Her etkinliğin 10., 25., 50. ve 75. yüzdelik dilim performansı Kibana ile görselleştirilir.
AirSHIFT artık vardiya tablosu yükleme etkinliğini izleyerek 75. yüzdelik dilimdeki kullanıcılar için 3 saniyede tamamlanmasını sağlıyor. Bu, şu an için uygulanmayan bir bütçe. Ancak şirket, bütçesini aştığında Elasticsearch aracılığıyla otomatik bildirim almayı düşünüyor.
Sonuçlar
Yukarıdaki grafikte, AirSHIFT'in artık çoğunlukla 75. yüzdelik dilimdeki kullanıcılar için 3 saniyelik bütçeye ulaştığını ve ayrıca 25. yüzdelik dilimdeki kullanıcılar için vardiya tablosunu bir saniye içinde yüklediğini görebilirsiniz. AirSHIFT, çeşitli koşullardan ve cihazlardan RUM performans verilerini yakalayarak yeni bir özellik sürümünün uygulamanın performansını gerçekten etkileyip etkilemediğini kontrol edebilir.
5. Performans hackathon'ları
Tüm bu performans optimizasyonu çalışmaları önemli ve etkili olsa da mühendislik ve işletme ekiplerinin işlevsel olmayan geliştirmeye öncelik vermesini sağlamak her zaman kolay değildir. Bu performans optimizasyonlarından bazıları planlanamadığı için bu durum bir sorun teşkil ediyor. Deneme ve deneme yanılma zihniyetine ihtiyaç duyarlar.
AirSHIFT, mühendislerin yalnızca performansla ilgili çalışmalara odaklanabilmesi için artık şirket içinde 1 günlük performans hackathonları düzenliyor. Bu hackathon'larda tüm kısıtlamalar kaldırılır ve mühendislerin yaratıcılığına saygı gösterilir. Diğer bir deyişle, hıza katkıda bulunan tüm uygulamalar dikkate alınır. AirSHIFT, hackathon'u hızlandırmak için grubu küçük ekiplere ayırır ve her ekip Lighthouse performans puanında en büyük iyileşmeyi kimin elde edebileceğini görmek için yarışır. Ekipler çok rekabetçi oluyor. 🔥
Sonuçlar
Hackathon yaklaşımı onlar için iyi sonuç veriyor.
- Hackathon sırasında birden fazla yaklaşımı deneyip her birini Lighthouse ile ölçerek performans darboğazlarını kolayca tespit edebilirsiniz.
- Hackathon'dan sonra, ekibi üretim sürümüne öncelik vermeleri gereken optimizasyona ikna etmek oldukça kolaydır.
- Ayrıca hızın önemini vurgulamanın etkili bir yoludur. Her katılımcı, kodlama şekliniz ile performans arasındaki ilişkiyi anlayabilir.
Recruit bünyesindeki diğer birçok mühendislik ekibinin bu uygulamalı yaklaşımla ilgilenmesi ve AirSHIFT ekibinin şu anda şirket içinde çok sayıda hıza yönelik hackathon'ları yönetmesi de işin olumlu bir yanıydı.
Özet
AirSHIFT'in bu optimizasyonlar üzerinde çalışması kesinlikle en kolay yolculuk değildi ama kesinlikle karşılığını aldı. AirSHIFT, şimdi geçiş tablosunu ortanca değerde 1,5 saniye içinde yüklüyor.Bu da projeden önceki performansa göre 6 kat artış anlamına geliyor.
Performans optimizasyonları kullanıma sunulduktan sonra bir kullanıcı şunları söyledi:
Vardiya tablosunun hızlı yüklenmesini sağladığınız için çok teşekkür ederiz. Vardiyalı çalışmayı düzenlemek artık çok daha verimli.