Vercel’de React uygulamanızın sayfa yenilemede 404 hatası vermesini anlamak ve hızlı bir çözüm bulmak için kapsamlı rehber. Tek sayfa uygulamaları için en iyi pratikleri keşfedin.

Modern web geliştirme dünyasında, React gibi kütüphanelerle oluşturulan Tek Sayfa Uygulamaları (SPA’lar) her geçen gün daha popüler hale geliyor. Bu uygulamalar, dinamik ve akıcı kullanıcı deneyimleri sunarak adeta bir masaüstü uygulaması hissi veriyor. Ancak bu harika deneyimlerin arkasında, bazen geliştiricileri şaşırtan küçük bir sorun yatıyor: Uygulamanız Vercel gibi statik bir hosting platformuna dağıtıldığında, herhangi bir alt sayfayı doğrudan URL’den yenilediğinizde veya o URL’yi paylaşarak açtığınızda bir “404 Not Found” hatasıyla karşılaşmak. Bu durum, özellikle yeni başlayan geliştiriciler için kafa karıştırıcı olabilir ve çoğu zaman projenin dağıtım sürecini sekteye uğratır. Peki, bu neden oluyor ve daha da önemlisi, bu sorunu nasıl 2 dakikadan kısa sürede çözebiliriz?

Bu makalede, React uygulamanızın Vercel’de neden bu şekilde davrandığını, altındaki temel teknik nedenleri ve en nihayetinde bu yaygın soruna hızlı ve etkili bir çözüm sunacağız. Temel kavramlardan başlayarak, konuya tamamen yabancı olan okuyucuların bile rahatlıkla anlayabileceği bir yol izleyeceğiz. Ardından, adım adım uygulayabileceğiniz bir düzeltme ile uygulamanızın her koşulda sorunsuz çalışmasını sağlayacağız. Hatta, daha ileri düzey optimizasyonlar ve en iyi uygulamalar hakkında da ipuçları sunarak, React deneyiminizi bir üst seviyeye taşımanıza yardımcı olacağız. Dolayısıyla, hazırsanız bu gizemi çözmek ve React uygulamanızın Vercel’de her zaman tıkır tıkır çalışmasını sağlamak için derinlemesine bir yolculuğa çıkalım.

Tek Sayfa Uygulamaları (SPA) ve Yönlendirme Nasıl Çalışır?

Sorunun kökenini anlamak için öncelikle Tek Sayfa Uygulamalarının (SPA’lar) ve geleneksel çok sayfalı uygulamaların (MPA’lar) nasıl çalıştığını kavramamız gerekiyor. Geleneksel web siteleri, sunucudan her sayfa isteği geldiğinde tam bir HTML belgesi gönderir. Yani, “Hakkımızda” sayfasına tıkladığınızda tarayıcınız sunucuya yeni bir istek gönderir ve sunucu da o sayfanın HTML’ini baştan oluşturup geri yollar. Bu, “sunucu tarafı yönlendirme” olarak bilinir. Her sayfa geçişinde tarayıcı tamamen yenilenir.

Öte yandan, React gibi modern kütüphanelerle geliştirilen SPA’lar çok farklı bir yaklaşıma sahiptir. İlk yüklemede, tarayıcı sunucudan yalnızca tek bir HTML dosyası (genellikle index.html) ve bu sayfayı çalıştıran tüm JavaScript, CSS dosyalarını indirir. Uygulamanın tüm mantığı bu JavaScript dosyalarında bulunur. Kullanıcı navigasyon düğmelerine tıkladığında (örneğin, “Ürünler” sayfasından “Hakkımızda” sayfasına geçerken), tarayıcı sunucuya yeni bir HTML isteği göndermek yerine, JavaScript kodunu kullanarak sayfanın içeriğini dinamik olarak günceller. Bu işleme “istemci tarafı yönlendirme” denir. URL çubuğundaki adres değişse bile (örneğin, /urunler‘den /hakkimizda‘ya), aslında sunucuya yeni bir istek gönderilmez ve sayfa tamamen yenilenmez.

Bu istemci tarafı yönlendirme, kullanıcılara son derece hızlı ve akıcı bir deneyim sunar. Sayfa geçişleri anında gerçekleşir, çünkü tarayıcının tüm sayfayı yeniden yüklemesi gerekmez; sadece DOM’u (Belge Nesne Modeli) günceller. Bu sihir, tarayıcının HTML5 History API‘si sayesinde mümkün olur. React Router gibi popüler kütüphaneler, bu API’yi kullanarak URL’yi değiştirir ve uygulamanın hangi bileşenleri render etmesi gerektiğini belirler. Örneğin, bir React uygulaması içerisinde genellikle şöyle bir yapı görürsünüz:


import React from 'react';
import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';
import Home from './Home';
import About from './About';
import Products from './Products';

function App() {
  return (
    
      
      
        } />
        } />
        } />
        } />
      
    
  );
}

function ProductDetail() {
  const { id } = useParams();
  return 

Ürün Detayı: {id}

; } export default App;

Bu kodda, BrowserRouter HTML5 History API'sini kullanarak URL değişikliklerini yönetir. Link bileşenleri tıklanıldığında sayfa yenilenmeden rotalar arasında geçiş yapar. Ancak, işte tam da burada sorun başlıyor. Eğer tarayıcının adres çubuğuna doğrudan /urunler/123 yazıp Enter tuşuna basarsanız veya bu URL'yi yenilerseniz, tarayıcı sunucuya "/urunler/123" adında bir dosya veya dizin olup olmadığını soracaktır. Vercel gibi statik hosting platformları, bu tür durumlarda sunucu tarafında fiziksel olarak o URL'ye karşılık gelen bir dosya bulamadıkları için varsayılan olarak bir 404 hatası döndürür. Bu, SPA'ların istemci tarafı yönlendirme mantığı ile sunucunun statik dosya sunma mantığı arasındaki temel bir çatışmadır. Bu nedenle, çözüme odaklanmadan önce bu çatışmanın neden kaynaklandığını daha derinlemesine incelememiz gerekiyor.

Tarayıcı Yenilemesinde Neden 404 Hatası Alırız?

Yukarıda bahsettiğimiz gibi, sorun aslında istemci tarafı yönlendirme ile sunucu tarafı dosya sunumu arasındaki uyumsuzluktan kaynaklanıyor. React uygulamanızı npm run build komutuyla derlediğinizde, ortaya çıkan üretim dosyaları (genellikle bir build veya dist klasöründe), optimize edilmiş bir index.html dosyası, bu dosyayı besleyen JavaScript ve CSS paketleri ile statik varlıklardan (resimler, fontlar vb.) oluşur. Vercel gibi bir statik site hosting sağlayıcısına bu klasörü dağıttığınızda, Vercel aslında bu dosyaları bir CDN (İçerik Dağıtım Ağı) üzerine koyar ve HTTP isteklerini doğrudan bu statik dosyalara yönlendirir.

Şimdi bir senaryo düşünelim: React uygulamanızı Vercel'e dağıttınız. Uygulamanızın ana URL'si https://benim-uygulamam.vercel.app/ olsun. Bu adrese gittiğinizde Vercel, index.html dosyasını sorunsuz bir şekilde bulur ve tarayıcınıza gönderir. index.html yüklendikten sonra, uygulamanızın JavaScript'i çalışmaya başlar ve React Router devreye girer. Uygulama içinde "Ayarlar" sayfasına (https://benim-uygulamam.vercel.app/ayarlar) bir Link aracılığıyla gittiğinizde, React Router URL'yi günceller ve ilgili "Ayarlar" bileşenini render eder, ancak tarayıcı sunucuya yeni bir istek göndermez.

Ancak, bu "Ayarlar" sayfasında iken tarayıcınızı yenilediğinizde veya bu URL'yi doğrudan başka bir sekmede açtığınızda ne olur? Tarayıcı yeni bir HTTP isteği ile https://benim-uygulamam.vercel.app/ayarlar adresine gider. Vercel sunucuları bu isteği alır ve /ayarlar adında bir fiziksel dizin veya ayarlar.html gibi bir dosya arar. Ancak React uygulamanızda ayarlar.html diye bir dosya yoktur; tüm yönlendirme JavaScript tarafından yönetilmektedir. Bu durumda Vercel, istenen URL'ye karşılık gelen bir kaynak bulamadığı için standart 404 "Not Found" HTTP durum kodu ile yanıt verir. Sonuç olarak, ekranınızda hoş olmayan bir hata sayfası belirir.

Vaka Analizi: E-ticaret Uygulamasında Ürün Detay Sayfası Refresh Sorunu

Bu durumu daha iyi somutlaştırmak için bir e-ticaret uygulamasını ele alalım. Diyelim ki bir kullanıcı React ile geliştirilmiş bir alışveriş sitesinde gezinirken ana sayfadan belirli bir ürünün detay sayfasına tıklıyor. URL, https://benim-dukkanim.vercel.app/urun/elbise-kirmizi-123 gibi bir şeye dönüşüyor. Bu URL, React Router tarafından yönetiliyor ve kullanıcıya o ürünün bilgilerini gösteriyor. Her şey yolunda.

Şimdi kullanıcı, bu ürünü arkadaşına göndermek için URL'yi kopyalıyor veya yanlışlıkla o sayfadayken tarayıcısını yeniliyor. İşte bu noktada Vercel sunucuları devreye giriyor. Sunucu, /urun/elbise-kirmizi-123 yolunu statik dosyaları arasında aramaya başlıyor. Ancak bu yol, sunucuda fiziksel olarak var olan bir klasöre veya HTML dosyasına karşılık gelmiyor. Bu, React uygulamasının JavaScript'i tarafından dinamik olarak oluşturulan bir "sanal" yol. Dolayısıyla, sunucu beklediği dosyayı bulamayınca kullanıcıya kibarca bir 404 hatası döndürüyor. Kullanıcı, uygulamanın çalışmadığını düşünüyor veya hayal kırıklığına uğruyor. Bu durum, özellikle SEO (Arama Motoru Optimizasyonu) açısından da ciddi problemlere yol açabilir, çünkü arama motoru botları da bu sayfaları indekslemekte zorlanabilir. Bu nedenle, bu sorunu çözmek, sadece kullanıcı deneyimi için değil, aynı zamanda uygulamanızın genel sağlığı ve keşfedilebilirliği için de kritik öneme sahiptir.

2 Dakikalık Çözüm: Vercel Rewrites ile Sorunu Kalıcı Olarak Giderin

Neyse ki, bu sorun Vercel üzerinde oldukça basit ve hızlı bir şekilde çözülebilir. Çözüm, Vercel'in "Rewrites" (Yeniden Yazma) özelliğini kullanmaktan geçiyor. Rewrites, gelen bir HTTP isteğinin URL'sini değiştirmek veya başka bir hedefe yönlendirmek için kullanılan güçlü bir mekanizmadır. Amacımız, sunucunun herhangi bir yola gelen isteği, bizim tek ve ana HTML dosyamıza (index.html) yönlendirmesini sağlamaktır, böylece React Router kontrolü ele alabilir.

Vercel'de bu yapılandırmayı gerçekleştirmek için projenizin kök dizininde (package.json dosyanızla aynı yerde) vercel.json adında bir dosya oluşturmanız veya mevcutsa düzenlemeniz gerekir. Bu dosya, Vercel dağıtımınız için çeşitli yapılandırma ayarlarını içerir ve rewrites de bunlardan biridir.

Adım Adım Yapılandırma: vercel.json Oluşturma

  1. Projenizin Kök Dizinine Gidin: Terminalinizde veya dosya yöneticinizde React projenizin ana klasörüne gidin. Bu genellikle src, public ve package.json gibi dosyaların bulunduğu yerdir.
  2. vercel.json Dosyasını Oluşturun: Eğer yoksa, bu klasörde vercel.json adında yeni bir dosya oluşturun.
  3. Aşağıdaki Yapılandırmayı Ekleyin: vercel.json dosyasının içine aşağıdaki JSON kodunu yapıştırın:

{
  "rewrites": [
    {
      "source": "/(.*)",
      "destination": "/index.html"
    }
  ]
}
        

Bu JSON kodundaki "rewrites" dizisi, Vercel'in gelen istekleri nasıl yeniden yazacağını tanımlar. İçindeki nesne ise şu anlama gelir:

  • "source": "/(.*)": Bu, bir "regex" (düzenli ifade) kalıbıdır ve sunucuya gelen herhangi bir yolu eşleştirir. Parantez içindeki . herhangi bir karakteri, * ise o karakterin sıfır veya daha fazla kez tekrarını ifade eder. Kısacası, bu kalıp /'dan sonra gelen her şeyi yakalar, örneğin /urunler/123, /hakkimizda veya /herhangi-bir-sey.
  • "destination": "/index.html": Bu, eşleşen herhangi bir isteğin hedefinin index.html dosyası olacağını belirtir. Yani, sunucu /urunler/123 isteğini aldığında, aslında arka planda index.html dosyasını sunar.

Bu yapılandırma sayesinde, Vercel sunucusu artık fiziksel bir dosya aramaya çalışmak yerine, gelen tüm istekleri uygulamanızın ana giriş noktası olan index.html'e yönlendirecektir. index.html yüklendiğinde, React uygulamanızın JavaScript'i çalışacak ve React Router, tarayıcının adres çubuğundaki gerçek URL'ye göre ilgili bileşeni render ederek doğru sayfayı gösterecektir. Problem çözüldü!

Vercel CLI ile Dağıtım ve Doğrulama

Bu değişikliği yaptıktan sonra, projenizi Vercel'e yeniden dağıtmanız yeterlidir. Eğer Vercel CLI kullanıyorsanız, proje dizininizde vercel komutunu çalıştırmanız yeterlidir. Eğer GitHub/GitLab entegrasyonu kullanıyorsanız, sadece bu değişikliği içeren bir commit yapıp push etmeniz, Vercel'in otomatik olarak yeni bir dağıtım yapmasını sağlayacaktır. Dağıtım tamamlandıktan sonra, uygulamanızın herhangi bir alt URL'sini doğrudan adres çubuğuna yazıp yenilediğinizde veya o URL'yi paylaşarak açtığınızda artık 404 hatası almayacaksınız.

Uzman İpucu: Bu vercel.json dosyasının yalnızca Vercel'e özgü olmadığını unutmayın. Netlify gibi diğer hosting sağlayıcıları da benzer yapılandırmalar sunar. Netlify için, projenizin kök dizinine _redirects adında bir dosya oluşturup içine /* /index.html 200 satırını eklemeniz yeterlidir. Bu sayede uygulamanız farklı platformlarda da aynı şekilde çalışacaktır. Bu teknikle, uygulamanızın URL yönetimi %100 sorunsuz hale gelir ve kullanıcı deneyimi kesintisiz devam eder.

Bu basit ama etkili yapılandırma, React uygulamanızın Vercel'de karşılaştığı sayfa yenileme sorununu kökten çözer. Artık kullanıcılarınız herhangi bir URL'yi güvenle paylaşabilir ve tarayıcılarını yenileyebilirler. Bu, uygulamanızın profesyonelliğini ve kullanılabilirliğini önemli ölçüde artırır. Gördüğünüz gibi, çözüm gerçekten de sadece birkaç satır kod ve birkaç dakikalık bir işlemdi.

İleri Düzey Optimizasyonlar ve En İyi Uygulamalar: Performans ve Kullanıcı Deneyimi İçin Ek İpuçları

Yukarıdaki vercel.json çözümü, React uygulamanızın Vercel'de yenileme sorununu kalıcı olarak giderir. Ancak, modern bir web uygulaması geliştirirken sadece bu sorunu çözmekle kalmamalı, aynı zamanda performansı ve kullanıcı deneyimini en üst düzeye çıkarmak için ek optimizasyonlara da odaklanmalıyız. İşte bu bağlamda dikkate almanız gereken bazı ileri düzey ipuçları ve en iyi uygulamalar:

1. Kod Bölme (Code Splitting) ve Tembel Yükleme (Lazy Loading)

React uygulamaları büyüdükçe JavaScript paketleri de büyür. Bu, uygulamanın ilk yükleme süresini artırarak kullanıcı deneyimini olumsuz etkileyebilir. Kod bölme ve tembel yükleme, uygulamanızın tüm kodunu tek bir büyük dosya yerine daha küçük, ayrı parçalara bölerek sadece ihtiyaç duyulduğunda yüklenmesini sağlar. Bu, özellikle farklı rotalar veya bileşenler için farklı kod parçalarının yüklenmesi anlamına gelir. React'in React.lazy() ve Suspense özellikleri, bu işlemi oldukça kolaylaştırır. Örneğin:


import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';

const Home = lazy(() => import('./Home'));
const About = lazy(() => import('./About'));
const Products = lazy(() => import('./Products'));

function App() {
  return (
    
      
      Yükleniyor...