Web Hosting & cPanel

    Next.js Sitesi Paylaşımlı Hostingde Çalışır mı? Statik Export Rehberi

    SSR ve API route kullanan Next.js projeleri paylaşımlı hostingde çalışmaz. Export edilebilirlik kontrol listesi ve cPanel'e yükleme adımları.

    13 dk okuma Güncellendi: 18 Ağustos 2026

    npm run build yerelde sorunsuz tamamlandı, .next klasörü oluştu. FTP ile bunu public_html içine attınız, alan adını açtınız ve karşınıza ya "Index of /" dizin listesi ya da bembeyaz bir sayfa çıktı. Bir arama sonrası "cPanel'de Setup Node.js App var" bilgisine ulaşıp uygulamayı oradan tanımladınız; bu kez de 503 Service Unavailable ya da sonsuza kadar dönen bir yükleme ikonu.

    Bu noktada aranan cevap genelde "hangi ayarı kaçırdım" oluyor. Oysa sorun çoğu zaman bir ayar değil, mimari bir uyumsuzluk: paylaşımlı hosting hesapları HTML, CSS, JavaScript ve PHP servis etmek üzere kurgulanmıştır. Next.js'in sunucu tarafı ise sürekli ayakta duran bir Node.js süreci ister — kalıcı bellek, bir port ve süreç yöneticisi. Ekonomik paylaşımlı paketlerin çoğunda bunların hiçbiri yoktur.

    Bu rehber önce dürüst cevabı verir: hangi Next.js projesi paylaşımlı hostingde çalışır, hangisi hiçbir ayarla çalışmaz. Ardından iki yol ayrımını anlatır — projeyi statik export edilebilir hale getirip cPanel'e yüklemek, ya da Node destekli bir pakete veya sanal sunucuya geçmek. Aradaki kararı verebilmeniz için hangi Next.js özelliğinin export'u imkânsız kıldığını madde madde çıkarıyoruz.

    Kısa Cevap: Hangi Next.js Projesi Paylaşımlı Hostingde Çalışır?#

    Karar tek bir soruya iner: projeniz derleme anında (build time) tamamen HTML dosyalarına dönüştürülebiliyor mu?

    Proje tipiPaylaşımlı hostingNode destekli paketVDS / sunucu
    Tamamen statik sayfalar (blog, kurumsal site, dokümantasyon)ÇalışırÇalışırÇalışır
    Statik sayfa + istemci tarafı veri çekme (harici API'ye fetch)ÇalışırÇalışırÇalışır
    generateStaticParams ile üretilmiş dinamik rotalarÇalışırÇalışırÇalışır
    API route / Route Handler (kendi backend'i)ÇalışmazÇalışırÇalışır
    Server Actions (form gönderimi sunucuda)ÇalışmazÇalışırÇalışır
    SSR — her istekte sunucuda renderÇalışmazÇalışırÇalışır
    ISR / revalidate ile arka planda yenilemeÇalışmazÇalışırÇalışır
    middleware.tsÇalışmazÇalışırÇalışır
    next/image varsayılan optimizasyonÇalışmazÇalışırÇalışır

    Tablonun özeti şu: statik içerik üreten bir Next.js sitesi paylaşımlı hostingde mükemmel çalışır; kendi sunucu tarafını kullanan bir Next.js uygulaması ise çalışmaz. İkinci grup için ayar aramak zaman kaybıdır.

    Neden SSR ve API Route'ları Paylaşımlı Hostingde Çalışmaz?#

    Paylaşımlı hosting hesabınızda istek şu yolu izler: Apache ya da LiteSpeed gelen HTTP isteğini alır, adres bir dosyaya karşılık geliyorsa onu gönderir, .php ise PHP yorumlayıcısını çağırıp çıktısını döndürür. Süreç isteğin sonunda biter, bellekte hiçbir şey kalmaz.

    Next.js'in sunucu tarafı bunun tersini ister:

    • Kalıcı süreç. next start bir Node.js sürecidir ve site ayakta olduğu sürece çalışır. Paylaşımlı hesaplarda uzun ömürlü süreçler genellikle birkaç dakika içinde sonlandırılır.
    • Port dinleme. Node uygulaması bir portu dinler (varsayılan 3000). Paylaşımlı hesaplarda rastgele port açma yetkiniz yoktur.
    • Reverse proxy. Dinlenen portu 443'e bağlayacak bir ters vekil katmanı gerekir; bu yapılandırma sunucu yöneticisine aittir.
    • Bellek payı. Node süreci boşta bile 80-150 MB tutar. PHP tabanlı paketlerin süreç ve bellek limitleri bu senaryoya göre boyutlandırılmamıştır.

    Bu maddelerin hiçbiri "kötü hosting" göstergesi değil; sadece farklı bir çalışma modeli. .next klasörünü public_html içine kopyalamak da bu yüzden hiçbir zaman işe yaramaz: o klasör tarayıcıya sunulacak bir site değil, Node sürecinin okuyacağı bir derleme çıktısıdır.

    Tek istisna, cPanel'in Setup Node.js App aracıdır. Passenger üzerinden Node uygulaması ayağa kaldırır ve gerçekten çalışır — ama her pakette bulunmaz, bellek limitleri düşüktür ve sharp gibi native modüllerde sorun çıkarabilir. Bu yolu değerlendiriyorsanız cPanel'de Node.js uygulaması yayınlama yazısı kurulumun tamamını anlatıyor.

    Projeniz Statik Export Edilebilir mi? Kontrol Listesi#

    Karar vermeden önce projeyi tarayın. Aşağıdaki tablo, output: 'export' ile uyumsuz olan özellikleri ve pratik alternatiflerini listeliyor:

    ÖzellikExport ile uyumlu muAlternatif
    middleware.tsHayırYönlendirmeleri .htaccess'e taşıyın
    Server Actions ("use server")HayırFormu harici bir API'ye veya form servisine gönderin
    Route Handler / API route (dinamik)HayırAyrı bir backend, serverless fonksiyon veya harici servis
    cookies(), headers() (sunucu tarafında)Hayırİstemci tarafında document.cookie ile okuyun
    revalidate / ISRHayırHer içerik değişiminde yeniden build alın
    export const dynamic = 'force-dynamic'HayırVeriyi istemcide çekin
    generateStaticParams olmayan dinamik rotaHayırParametreleri build anında üretin
    Draft / Preview ModeHayırCMS önizlemesini ayrı ortamda çalıştırın
    next/image varsayılan loaderHayırimages.unoptimized: true veya harici loader
    next.config içindeki rewrites, redirects, headersHayır.htaccess kuralları
    generateStaticParams ile dinamik rotaEvet
    İstemci bileşenleri, useEffect ile veri çekmeEvet
    generateMetadata (statik veriyle)Evet
    CSS Modules, Tailwind, sassEvet

    Taramayı elle yapmayın; birkaç komut yeterli:

    # Middleware var mı?
    ls middleware.ts middleware.js 2>/dev/null
    
    # Server Actions kullanılıyor mu?
    grep -rn '"use server"' app/ src/ 2>/dev/null
    
    # Sunucu tarafı istek başlıkları okunuyor mu?
    grep -rn "next/headers" app/ src/ 2>/dev/null
    
    # Dinamik render zorlanıyor mu?
    grep -rn "force-dynamic\|revalidate" app/ src/ 2>/dev/null
    
    # API route klasörleri
    find app -type d -name api 2>/dev/null
    

    Çıktıların hepsi boşsa proje büyük olasılıkla export edilebilir. Değilse, iki seçenek var: ilgili özellikleri istemci tarafına taşıyıp export'a uygun hale getirmek, ya da Node çalıştıran bir ortama geçmek. Kararı verirken paylaşımlı hosting ile VPS farkı karşılaştırması maliyet tarafını netleştirir.

    Statik Export Yapılandırması: next.config Ayarları#

    Next.js 13.3'te next export komutu yumuşak biçimde kullanımdan kaldırıldı, Next.js 14'te ise tamamen silindi. Artık export bir komut değil, bir yapılandırma seçeneğidir. Hâlâ next export yazan rehberler görürseniz o içerik eskimiştir.

    // next.config.mjs
    const nextConfig = {
      output: 'export',
      images: {
        unoptimized: true,
      },
      trailingSlash: true,
    };
    
    export default nextConfig;
    

    Üç ayarın da bir gerekçesi var:

    • output: 'export'next build komutunun sonunda out/ klasörünü üretir. Bu klasör doğrudan yüklenebilir statik siteyi içerir.
    • images.unoptimized: true — Varsayılan görsel optimizasyonu çalışma anında bir sunucu ister. Bu ayar olmadan build, "default loader export ile uyumlu değil" benzeri bir hatayla durur.
    • trailingSlash: true — Bu ayarla /hakkimizda rotası out/hakkimizda/index.html olarak yazılır. Apache dizin isteklerinde index.html dosyasını otomatik sunduğu için ekstra kural gerekmeden çalışır. Kapalıyken çıktı out/hakkimizda.html olur ve uzantısız adres için .htaccess tarafında MultiViews ya da açık yeniden yazma kuralı gerekir.

    Ardından derleyin:

    npm ci
    npm run build
    ls out
    

    out klasörü oluşmadıysa build çıktısındaki uyarıları okuyun; Next.js hangi sayfanın export'u engellediğini genellikle dosya yoluyla birlikte söyler.

    out Klasörünü cPanel'e Yükleme#

    Buradan sonrası, herhangi bir statik siteyi yayınlamaktan farksızdır — süreç HTML sitesini hostinge yükleme yazısındakiyle aynıdır.

    1. out klasörünün içeriğini zip'leyin. Klasörün kendisini değil; aksi halde site siteniz.com/out/ altında kalır.
    2. cPanel → File Manager → public_html içine girin, varsa eski dosyaları temizleyin.
    3. Zip'i yükleyin ve Extract ile açın.
    4. index.html, _next/ klasörü ve 404.html dosyasının public_html içinde, kök seviyede durduğunu doğrulayın.
    5. Alan adını açın ve tarayıcı konsolunu kontrol edin.

    Yüklemeyi terminalden yapıyorsanız rsync hem daha hızlı hem de silinenleri temizler:

    rsync -avz --delete out/ kullanici@sunucu:/home/kullanici/public_html/
    

    --delete bayrağı hedefte olup kaynakta olmayan dosyaları siler. Eski build'in artık kullanılmayan _next/static dosyalarının birikip inode kotanızı doldurmasını bu bayrak engeller.

    Alt Dizin veya Ek Alan Adına Kurulum#

    Siteyi siteniz.com/uygulama gibi bir alt yolda yayınlayacaksanız basePath ayarı zorunludur; yoksa tüm CSS ve JS dosyaları kökten aranır ve 404 döner.

    const nextConfig = {
      output: 'export',
      basePath: '/uygulama',
      assetPrefix: '/uygulama',
      images: { unoptimized: true },
      trailingSlash: true,
    };
    

    404 Sayfası ve Önbellek Kuralları#

    Next.js export'u 404.html üretir ama Apache'nin bunu kullanacağını bilmesi gerekir. public_html/.htaccess dosyasına şunu ekleyin:

    ErrorDocument 404 /404.html
    
    # Hash'li varlıklar uzun süre önbelleklenebilir
    <IfModule mod_expires.c>
        ExpiresActive On
        ExpiresByType text/css "access plus 1 year"
        ExpiresByType application/javascript "access plus 1 year"
        ExpiresByType image/svg+xml "access plus 1 month"
    </IfModule>
    
    # HTML dosyaları önbelleklenmemeli, yoksa deploy görünmez
    <FilesMatch "\.html$">
        Header set Cache-Control "no-cache, must-revalidate"
    </FilesMatch>
    

    _next/static altındaki dosya adları içerik özetini taşır; her build'de değişirler, bu yüzden bir yıl önbelleklenmeleri güvenlidir. HTML dosyaları ise aynı adı koruduğu için önbelleklenirse yeni sürüm ziyaretçiye günlerce ulaşmaz. Kural yazımının ayrıntıları için .htaccess yönlendirme ve kural yazımı yazısına bakabilirsiniz.

    Dinamik Rotalar: generateStaticParams Olmadan Export Çalışmaz#

    app/blog/[slug]/page.tsx gibi bir rotanız varsa, Next.js hangi slug değerleri için HTML üreteceğini bilemez ve build şu türde bir hatayla durur: "Page /blog/[slug] is missing generateStaticParams() so it cannot be used with output: export."

    Çözüm, olası değerleri build anında listelemektir:

    // app/blog/[slug]/page.tsx
    export const dynamicParams = false;
    
    export async function generateStaticParams() {
      const yazilar = await fetch('https://cms.siteniz.com/api/yazilar')
        .then((r) => r.json());
    
      return yazilar.map((yazi: { slug: string }) => ({ slug: yazi.slug }));
    }
    
    export default async function Page({
      params,
    }: {
      params: Promise<{ slug: string }>;
    }) {
      const { slug } = await params;
      return <article>{slug}</article>;
    }
    

    dynamicParams = false ayarı, listede olmayan bir slug istendiğinde 404 döndürülmesini sağlar. Export modunda listede olmayan bir sayfa zaten üretilmez; bu satır davranışı açık hale getirir.

    Bu yaklaşımın doğal sonucu şudur: her yeni içerik için yeniden build almanız gerekir. Günde birkaç yazı yayınlanan bir blogda bu kabul edilebilir, ama kullanıcıların anlık içerik ürettiği bir platformda değildir. İkinci durumda export doğru araç değildir.

    Görseller: next/image Neden Sorun Çıkarıyor?#

    next/image bileşeni normalde çalışma anında görselleri yeniden boyutlandırır ve WebP/AVIF'e çevirir. Bu işi yapan bir sunucu olmadığı için export modunda kapatılması gerekir. unoptimized: true ayarı bileşeni çalışır durumda tutar, ama görselleri olduğu gibi servis eder — yani boyutlandırmayı derleme öncesinde siz halletmelisiniz.

    Pratikte üç seçenek var:

    YöntemNasıl çalışırNe zaman tercih edilir
    unoptimized: trueGörseller olduğu gibi servis edilirGörsel sayısı az, boyutlar zaten optimize
    Harici loader (Cloudinary, imgix vb.)URL üzerinden boyutlandırmaGörsel yoğun siteler
    Build öncesi optimizasyon (sharp betiği)WebP çıktıları repoya girerTam kontrol istendiğinde

    Görselleri bir CDN üzerinden servis etme fikrini değerlendiriyorsanız CDN mi daha iyi yoksa hosting mi yazısı ne zaman gerçekten fark yarattığını anlatıyor.

    Nuxt, Vite ve Create React App İçin Karşılığı#

    Aynı mantık diğer framework'lerde de geçerlidir: derleme çıktısı statik dosyalarsa paylaşımlı hosting yeter.

    FrameworkKomutÇıktı klasörüNot
    Next.jsnext build (output: 'export')out/SSR/API varsa export edilemez
    Nuxtnuxt generate.output/public/nuxt build çıktısı Node ister
    Vite (React/Vue)vite builddist/Varsayılan olarak tamamen statik
    Create React Appreact-scripts buildbuild/Varsayılan olarak tamamen statik
    Astroastro builddist/Adaptör eklenmediyse statik

    Vite ve CRA gibi tek sayfa uygulamalarında ek bir adım vardır: yönlendirme tarayıcı tarafında yapıldığı için /hakkimizda adresine doğrudan girildiğinde sunucu böyle bir dosya bulamaz ve 404 verir. Çözüm, var olmayan yolları index.htmle yönlendirmektir:

    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.html [L]
    

    Next.js statik export'unda bu kural gerekmez, çünkü her rota için gerçek bir HTML dosyası üretilir. Bu, export'un tek sayfa uygulamasına göre SEO avantajıdır.

    Export Yetmiyorsa: Node Destekli Hosting mi, VDS mi?#

    Projeniz sunucu tarafına gerçekten ihtiyaç duyuyorsa iki seçenek kalır.

    KritercPanel Node.js App (Passenger)VDS / sanal sunucu
    Kurulum zorluğuDüşük, arayüzdenOrta, komut satırı bilgisi ister
    BellekPaket limitiyle sınırlıAyrılan RAM kadar
    Node sürümü seçimiPanelin sunduğu sürümlerİstediğiniz sürüm
    Native modüller (sharp vb.)Sorun çıkarabilirSorunsuz
    Süreç yönetimiPassenger yönetirpm2 veya systemd
    SSLAutoSSL ile otomatikLet's Encrypt kurulumu
    Root erişimiYokVar

    Sanal sunucu tarafında tipik kurulum şöyle işler: uygulama pm2 ile arka planda ayağa kaldırılır, Nginx da 443 portundan gelen istekleri uygulamanın portuna aktarır.

    npm ci --omit=dev
    npm run build
    pm2 start npm --name "site" -- start
    pm2 save
    pm2 startup
    

    Süreç yönetiminin ayrıntıları için pm2 ile Node.js süreç yönetimi, önündeki vekil katmanı için Nginx reverse proxy yapılandırması yazıları doğrudan bu adımları anlatıyor.

    Sık Karşılaşılan Hatalar ve Çözümleri#

    BelirtiSebepÇözüm
    Build "missing generateStaticParams" diyorDinamik rota, parametre listesi yokgenerateStaticParams ekleyin
    "Image Optimization ... not compatible with export"Varsayılan görsel loaderimages.unoptimized: true
    "Middleware cannot be used with output: export"middleware.ts varDosyayı kaldırın, kuralları .htaccess'e taşıyın
    Ana sayfa açılıyor, alt sayfalar 404trailingSlash kapalıtrailingSlash: true + yeniden build
    Sayfa geliyor, CSS/JS 404Alt dizine kurulum, basePath yokbasePath ve assetPrefix tanımlayın
    Site eski hâlinde kalıyorHTML önbelleklenmişHTML için no-cache başlığı ekleyin
    Form gönderilince hiçbir şey olmuyorServer Action export'ta çalışmazHarici API veya form servisi kullanın
    out klasörü hiç oluşmuyoroutput: 'export' yok / build hata verdiKonfigürasyonu ve build çıktısını kontrol edin

    Karar sürecini tek cümleye indirgemek gerekirse: projenizde bir tane bile sunucu tarafı özellik varsa ve bunu kaldıramıyorsanız, paylaşımlı hostingte harcadığınız her dakika kayıptır. Buna karşılık tamamen statik bir Next.js sitesi, paylaşımlı bir pakette hem hızlı hem de son derece ucuza çalışır; çünkü sunulan şey düz HTML dosyalarından ibarettir.

    Sıkça Sorulan Sorular#

    .next klasörünü doğrudan public_html içine yükleyebilir miyim?#

    Hayır. .next klasörü tarayıcıya sunulacak bir site değil, Node.js sürecinin okuyacağı derleme çıktısıdır; içinde sunucu tarafı paketler ve manifest dosyaları bulunur. Paylaşımlı hostingte bu klasörü yüklemek dizin listesi ya da boş sayfa dışında bir sonuç vermez. Yüklenmesi gereken klasör, output: 'export' ayarıyla üretilen out klasörüdür.

    Statik export ile SEO performansım düşer mi?#

    Aksine, genellikle iyileşir. Statik export her rota için gerçek bir HTML dosyası üretir; arama motoru sayfayı JavaScript çalıştırmadan okur ve sunucu tarafı gecikmesi olmadığı için yanıt süresi çok düşer. Meta etiketleri generateMetadata ile derleme anında yazıldığı için sayfa başına özel başlık ve açıklama da korunur.

    Statik export edilen siteye iletişim formu nasıl eklerim?#

    Sunucu tarafı olmadığı için formu harici bir uç noktaya göndermeniz gerekir. En yaygın üç yol: form gönderim servisleri, sitenizle aynı alan adında çalışan küçük bir PHP betiği, ya da ayrı bir alan adında barındırılan bir API. PHP betiği yöntemi paylaşımlı hostingte tamamen ücretsiz çalışır; yalnızca CSRF ve spam koruması eklemeyi unutmayın.

    İçeriğim değiştiğinde her seferinde yeniden build almak zorunda mıyım?#

    Evet, içerik derleme anında HTML'e gömüldüğü için yeni içeriğin yayına girmesi yeni bir build gerektirir. Bu yükü otomatikleştirebilirsiniz: CMS'iniz bir webhook tetikler, sürekli entegrasyon aracı npm run build çalıştırır ve out klasörünü sunucuya rsync ile gönderir. İçerik günde birkaç kez değişiyorsa bu akış rahatlıkla yeter.

    cPanel'in Setup Node.js App aracıyla tam Next.js çalıştırabilir miyim?#

    Bazı durumlarda evet. Passenger, uygulamayı ayağa kaldırır ve SSR ile API route'ları çalışabilir. Ancak bellek limitleri düşüktür, Node sürüm seçimi panelin sunduklarıyla sınırlıdır ve sharp gibi derlenmiş modüller sorun çıkarabilir. Küçük projeler için makul, trafik alan bir uygulama için sanal sunucu daha öngörülebilir bir tercihtir.

    Nuxt veya Vite projem için de aynı kurallar geçerli mi?#

    Büyük ölçüde evet. Belirleyici olan, derleme çıktısının statik dosyalar olup olmadığıdır. Nuxt'ta nuxt generate komutu .output/public klasörünü üretir ve bu klasör paylaşımlı hostingte çalışır; nuxt build çıktısı ise Node süreci ister. Vite ve Create React App projeleri varsayılan olarak statiktir, yalnızca yönlendirme için .htaccess kuralı eklemeniz gerekir.

    Next.jscPanelNode.js

    Uygulamaya geçmeye hazır mısınız?

    NVMe SSD, ücretsiz SSL ve %99.9 uptime garantisiyle Clou.TR hosting ve sunucu çözümleriyle projenizi hayata geçirin.