Veri Alma: FETCH API ile SWR Yaklaşımı Karşılaştırması
Bir uygulama için önemli şeylerden birisi nedir? Evet, veri. İçinde veri bulundurmayan uygulamalar birer tanıtım sayfası / uygulaması olmaktan çok da öteye ne yazık ki geçemiyor.
Yazı her ne kadar sanki arka yüz (back-end) konusuyla ilgiliymiş gibi başlasa da sizlere ön yüzde (front-end) son kullanıcıya gösterdiğimiz verilere ulaşmak için kullandığımız “JavaScript ile Data Fetching(Veri Alma)“ konusundan bahsedeceğim.
Veriye erişmek ve kullanmak için 2 farklı veri alma yöntemini değerlendiriyor olacağız. Bunlardan birincisi FETCH API , diğeri ise SWR (Stale While Revalidate) yöntemleri olacak. Ayrıca SWR yöntemiyle kullanıcı üzerinde bırakabileceğimiz pozitif etkilerden de bahsedeceğim.
Uygulamalı örneklerde bir veritabanına ihtiyacımız olacağı için kullanıcı ve siparişlerinden oluşan fake bir veritabanı oluşturdum. Örnekleri bu uygulama üzerinden açıklayacağım.( Uygulamanın kodlarına makalenin sonunda belirteceğim GitHub reposundan ulaşabilirsiniz. )
Data Fetching — Veri Alma
Data Fetching, en basit tanımıyla ön yüzde gösterilecek olan verilerin, arka yüz ile iletişim kurularak elde edilmesidir. Bu iletişimi Fetch API gibi yöntemler aracılığıyla gerçekleştirebiliriz.
FETCH API nedir?
Fetch API, bize JavaScript tarafından sunulan bir veri alma ve gönderme yöntemidir. Bu yöntemin asenkron bir yapısı vardır. Teknik anlamda Fetch API window objesi içinde bize kullanıma hazır halde sağlanan bir metottur ve bir Promise yapısı döner. Promise yapısı sayesinde resolved ya da rejected şeklinde bir response ile karşılaşırız. Promise yapısıyla ilgili daha detaylı bilgiye MDN’den ulaşabilirsiniz.
FETCH Api nasıl çalışır?
Fetch API’nin çalışma prensibini 3 aşamada ele alabiliriz. Sırasıyla bunlar;
- Kullanıcı tarafında ( tarayıcıda ) sunucuya istek gönderilir
- Sunucu isteği karşılar
- Son aşamada ise 2 ihtimal vardır. Eğer istek başarılı bir şekilde sonuçlanırsa görmeyi vadettiğimiz veri bize response olarak sunucudan dönüş yapar. Eğer istek başarısızsa bize bir HTTP hata kodu döner.
Bu adımları aşağıdaki diyagramda görsel olarak gözlemleyebiliriz.
FETCH API yönteminin maliyeti nedir ?
Bu yöntem ile yönettiğimiz isteklerde uygulamamızda veriye daha önce ulaşmış olsak dahi her seferinde UI’da tekrar ulaşılması gerekmektedir. Pure JavaScript ile yazılmış, sayfalar arası geçiş yaparken sayfa başına uygulamanın her seferinde baştan yüklendiği yöntemlerde bunu görmemiz normal sayılabilir.
Ancak günümüzde yaygın bir biçimde kullanılan Single Page Application yönteminde bir web sayfasının sıfırdan yüklenmesine çoğunlukla ihtiyaç duyulmuyor. Değişikliği içeren komponentin güncellenmesi yeterli oluyor. React gibi kütüphaneler bunu oldukça başarılı bir şekilde hallediyor. Bu sebeple tüm sayfanın yenilenmesine ihtiyaç duyulmuyor. SPA hakkında daha fazla bilgi için MDN’e göz atabilirsiniz.
FETCH API: Kod, UI ve UX açısından bir örnek
Aşağıda Fetch API ile yazılmış bir kod örneğini görebilirsiniz. ( Ne kadar uzun bir syntax’ı olduğuna da dikkatinizi çekmek isterim )
fetch('http://localhost:5001/users')
.then((response) => response.json())
.then((data) => console.log(data));
Bir veri tabanına ihtiyacımız olduğunu söylemiştim. Hazırlamış olduğum sahte veri tabanı response’una 2 saniyelik bir gecikme ekledim ve bunun UI’da nasıl göründüğüne bir bakalım.
Sol altta bulunan kayıt zamanından da anlaşılacağı üzere 13 saniye içerisinde 3 defa aynı veriye ulaşmaya çalıştım.
Gif’de de görüldüğü üzere her seferinde data sıfırlanıyor ve istek atılıyor. UI’da loading spinner’ı görüyoruz. Oysa ilk seferde attığımız istekten sonra elimizde zaten bir data bulunuyordu.
SWR (Stale While Revalidate) nedir?
İlk olarak SWR bir veri yakalama modelidir. Tek başına FETCH Api’ye muadil olarak kullanılabilecek bir yöntem değildir. Çünkü temelde SWR’ın da veriyi alabilmesi için bir fetcher’a ihtiyacı vardır ve bunun içi yine Fetch API kullanacağız.
İsminden de anlaşılacağı üzere Yeniden Doğrulama Sırasında Bayat Verinin Kullanılması şeklinde bir çalışma prensibi bulunmaktadır. Yani ilk defa bir sunucuya istek attığımızda her şey aynı FETCH API’de olduğu gibi ilerler. Sunucudan cevap dönmesini bekleriz ve bu sırada loading komponenti görünür. Ardından da veriye ya ulaşırız ya da hata alırız.
Veriye başarılı şekilde ulaştığımız senaryoda asıl büyü ve Fetch API’den farklı olan kısım burada başlar. Elimizde ilk istekten gelen yani hali hazırda var olan cachelenmiş data bulunduğu için direkt olarak bu verileri UI’da gösterebiliriz. Kullanıcı deneyimi açısından ne kadar önemli olduğunu bir düşünün,lütfen. Aynı sayfaya hiçbir gelişinizde eliniz boş gelmiyorsunuz.
Burada şu soruyu duyar gibiyim, peki data değişmişse ne olacak ? SWR size bayat (stale) veriyi gösterirken aynı zamanda sunucuya tekrar istek atar. Bu sayede değişmiş bir data varsa UI’a bu değişim de yansır.
SWR (Stale — While — Revalidate) nasıl çalışır?
SWR’ın çalışma prensibini 5 adımda ele alabiliriz. Sırasıyla bunlar;
- Sunucuya istek gönderilir ( ilk istek )
- Localde cachelenmiş data bize sunulur ( ilk istekten sonra elimizde bulunuyor )
- Ulaşmak istediğimiz veride değişiklikler olmuş olabilir. Bunu anlamak için sunucuya istek gönderilir
- Sunucu bize güncel datayı döner
- Ve kullanıcı tarafında tarayıcıda güncel veriye ulaşmış oluruz. ( Ayrıca bu bizim yeni bayat ( stale ) verimiz oluyor )
Hadi SWR’ın çalışma mantığını 2 farklı diyagramla gözlemleyelim.
SWR’ın çalışma prensibi: Diyagram 1
SWR’ın çalışma prensibi: Diyagram 2
Buraya kadar SWR’ın önbellek stratejisinden ve bu stratejinin nasıl çalıştığıyla ilgili genel bilgilerden bahsettik. Ayrıca bir diyagramla birlikte bunu görselleştirerek ilerledik. Bir sonraki adımda ise Vercel’in React için geliştirmiş olduğu SWR kütüphanesini nasıl kullanacağımızdan bahsedeceğim.
SWR ( Stale — While — Revalidate ) : Kod, UI ve UX açısından bir örnek
Aşağıda SWR ile yazılmış bir kod örneğini görebiliriz. ( Syntax’ın sadeliğine dikkatinizi çekmek isterim )
İlk olarak bir fetcher fonksiyona ihtiyacımız var ve FETCH API burada devreye giriyor.
NOT: baseUrl ve fetcher’ı SWRConfig içinde App’i sararak tanımlayabilir ve bu sayede useSWR Hookunu daha yalın bir şekilde bir şekilde kullanabiliriz. Detaylı konfigürasyon bilgilerine dokümantasyondan erişebilirsiniz.
const baseUrl = 'http://localhost:5001';
const fetcher = (baseUrl: string) => fetch(baseUrl).then((r) => r.json());
_app.tsx içinde,
import { SWRConfig } from 'swr';
import type { AppProps } from 'next/app';
import '../styles/globals.scss';
const baseUrl = 'http://localhost:5001';
export default function App({ Component, pageProps }: AppProps) {
const fetcher = (baseUrl: string) => fetch(baseUrl).then((r) => r.json());
return (
<SWRConfig
value={{
fetcher: (url: string) => fetcher(`${baseUrl}${url}`),
}}
>
<Component {...pageProps} />
</SWRConfig>
);
}
Artık ihtiyacımız olan şey tek satırlık bir istek.
const { data } = useSWR<IUser[]>(`/users`);
Hadi örneğe geçelim. Veri tabanı response’unda 2 saniyelik gecikme yine bulunuyor. Aşağıdaki gifte de görüleceği üzere yine 3 istek gönderiyorum ve 1. istekten sonrakilere dikkat etmenizi rica ediyorum. Loading spinner’ını görmeden direkt olarak veriler UI’da belirecek.
Sayfayı kaç kere ziyaret ettiğime bakın! İlk istekten sonra sanki kendi bilgisayarımda dosyalar arasında dolaşıyorum gibi. Ne kadar da muhteşem değil mi!
Bayat (stale ) verinin kullanılmasının ne gibi faydaları vardır?
Stale data sayesinde Gif’de de görüldüğü üzere UX açısından oldukça güzel sonuçlar elde edebiliyoruz. Kullanıcılar uygulamanızla çok daha fazla etkileşimde bulunabilir. Ayrıca zaten bildiğimiz bir şeyi görmeyi her seferinde beklemeyi kim ister ki ?
Bunun yanı sıra oldukça popüler bir ön yüz geliştirme yöntemi olan Optimistic UI için de önemli bir yapıdır.
FETCH API ve SWR yöntemlerinin UI bazında karşılaştırılması
Bu başlık altındaki amacım ayrı ayrı ele almış olduğum Fetch API ve SWR konularına ait karşılaştırmayı görsel olarak daha anlaşılabilir kılmak.Bu sebeple 2 isteği, tek ekranda yan yana gönderdiğimiz bir gif paylaşacağım. Eminim kafalardaki birçok soruya bu görsel net bir cevap verecektir.
Gif, bir döngü şeklinde ilerlediği için sol alttaki kayıt süresinin varlığına dikkatiniz çekmek isterim.Fark edeceğiniz üzere SWR ile veriye 1 kere ulaştıktan sonra elimizde bayat (stale) da olsa bir veri bulunduğu için kullanıcıyı bir daha loader spinner’a maruz bırakmıyoruz.
Sözü toparlamak gerekirse, karşılaştırma gifinde de görüldüğü üzere ilk istekte iki yöntem de aynı sonucu verir.Ancak ikinci ziyarette SWR bayat ( stale ) datayı bize sunduğu için herhangi bir loader ekranı görmeden veri doğrudan kullanıcı ara yüzümüzde belirir.
Çalışmamı okuyup zaman ayırdığınız için teşekkür ederim! Düşünce ve yorumlarınız çok kıymetli. Öyleyse, Arrivederci!
English: here
İlave Kısım
Gifler yeterli olmadı derseniz, ayrıca uygulama içinde daha uzun süre gezdiğim videoya buradan ulaşabilirsiniz. Youtube: https://youtu.be/MJeofIcEWLo
Kodlara erişmek için projeye ait GitHub linki: https://github.com/ooguzyuksel/data-fetching-fetch-vs-swr
Bana aşağıdaki kanallardan ulaşabilirsiniz,
LinkedIn: https://www.linkedin.com/in/developeroguzyuksel/
GitHub: https://github.com/ooguzyuksel
Oğuzhan YÜKSEL
Frontend Developer ÇSTech
Kaynakça
- https://juejin.cn/post/7005497283399647268
- https://swr.vercel.app/docs/global-configuration
- https://developer.mozilla.org/en-US/docs/Glossary/SPA
- https://www.toptal.com/react-hooks/stale-while-revalidate
- https://blog.zingsoft.com/how-to-make-a-chart-using-fetch-rest-apis/
- https://www.vuemastery.com/blog/data-fetching-and-caching-with-swr-and-vuejs/
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise