Yazılım8 dk

Next.js, Capacitor ve Electron: Tek Kod Tabanı ile Çoklu Platform

Polimelo Stüdyo25 Mayıs 2026

Günümüzde bir dijital ürün geliştirirken sadece web tarayıcılarında var olmak yetersiz kalabiliyor. Kullanıcılar uygulamalarınıza telefonlarından (Android/iOS) erişmek, hatta masaüstünde (Windows/macOS) kesintisiz bir performansla çalıştırmak istiyorlar. Her platform için ayrı dillerde (Java/Kotlin, Swift, C#) yerel uygulamalar yazmak ise küçük stüdyolar için hem zaman hem de bütçe açısından yıkıcıdır. Polimelo stüdyosu olarak bu problemi çözmek için modern bir hibrit mimari kullanıyoruz: React/Next.js, Capacitor.js ve Electron entegrasyonu.

Teknolojik Mimari

Sistemimizin merkezinde, kullanıcı arayüzünü (UI) ve tüm iş mantığını (business logic) yöneten tek bir Next.js projesi yer alıyor. Bu projeyi üç farklı platforma şu şekilde dağıtıyoruz:

  1. Web: Next.js'in output: 'export' özelliğini kullanarak statik HTML/JS/CSS dosyaları üretiyoruz. Bu çıktıları Cloudflare Pages veya Vercel üzerinde küresel olarak çok hızlı dağıtabiliyoruz.
  2. Mobil (Android): Capacitor.js yardımıyla statik web çıktımızı alıp yerel bir Android projesinin (WebView) içerisine gömüyoruz. Capacitor, web kodumuzun telefonun yerel API'lerine (bildirimler, dosya sistemi vb.) erişmesini sağlayan köprüler kuruyor.
  3. Masaüstü (Desktop): Electron kullanarak statik çıktımızı Chromium ve Node.js tabanlı masaüstü uygulamasına dönüştürüyoruz. Bu sayede oyunumuz Syncron, Steam'de yerel bir oyun gibi çalışabiliyor.

Next.js ve Static Export Zorlukları

Next.js varsayılan olarak sunucu taraflı çalışmaya (SSR - Server Side Rendering) odaklanır. Ancak mobil ve masaüstü paketleyiciler (Capacitor/Electron) bir Node.js sunucusuna sahip olmadıkları için tamamen statik dosyalara ihtiyaç duyarlar. Bu yüzden Next.js projemizde dinamik sunucu rotalarından kaçınmamız gerekti. Dinamik sayfalarımız (örneğin bu blog yazısının detayı olan /blog/[slug]) için derleme aşamasında tüm sayfaları HTML olarak üreten generateStaticParams fonksiyonunu kullandık.

Statik export (çıktı) alırken karşılaştığımız bir diğer kritik zorluk ise Next.js'in varsayılan görsel optimizasyon (next/image) mekanizmasıydı. Bu mekanizma arka planda bir Node.js sunucusunun dinamik resim boyutlandırma yapmasını gerektirir. Çevrimdışı ve sunucusuz çalışan Capacitor/Electron WebView ortamlarında bu özellik derleme hatasına (build error) neden olur. Çözüm olarak, next.config.js dosyamıza resim optimizasyonunu devre dışı bırakan images: { unoptimized: true } kuralını ekledik. Bu sayede tüm görseller doğrudan ham halleriyle yerel WebView içerisinde yüklenerek uygulamanın kesintisiz açılmasını sağladı.

Çoklu Platformda Veri Paylaşımı ve Offline Desteği

Diğer bir büyük sorun ise yerel veritabanı yönetimiydi. Tarayıcıda verileri saklamak kolaydır, ancak uygulama kapandığında veya internet kesildiğinde mobil ve masaüstünde verilerin korunması gerekir. Bu sorunu Dexie.js (IndexedDB wrapper) kullanarak çözdük. IndexedDB, hem modern tarayıcılarda hem Capacitor WebView içinde hem de Electron ortamında standart olarak desteklendiği için tek bir kod yazarak tüm platformlarda yerel, çevrimdışı çalışan (Offline-First) bir veritabanı kurmuş olduk. Çevrimdışı öncelikli mimari, internet bağlantısı kopuk olsa dahi kullanıcının ilerlemesini yerel IndexedDB veritabanında depolar. Cihaz internete tekrar bağlandığında ise arka planda çalışan bir senkronizasyon servisi Firebase Firestore ile veri eşitlemesini güvenli ve çakışmasız (conflict-free) bir şekilde tetikler.

Platformlar Arası Köprü Kurulumu (Native Bridge API)

Platforma özel APIs (örneğin mobil cihazlarda titreşim motorunu tetiklemek veya masaüstünde yerel dosya sistemine doğrudan dosya kaydetmek) için kod tabanımızda soyut bir köprü arayüzü (bridge interface) tasarladık. Bu sayede platform bağımsız tek bir fonksiyon çağırarak yerel entegrasyonu sağlayabiliyoruz:

async function triggerHapticFeedback() {
  if (Capacitor.isNativePlatform()) {
    await Haptics.vibrate();
  } else if (process.versions && process.versions.electron) {
    // Masaüstünde titreşim yoksa log bas veya alternatif aksiyon çalıştır
    console.log("Electron: vibration not supported on PC");
  } else if (navigator.vibrate) {
    navigator.vibrate(100);
  }
}

Bu soyutlama katmanı, kodumuzun hiçbir platformda patlamamasını (runtime exception) garantiler. Next.js static HTML çıktısını ürettiğinde, bu arayüz hangi platformda çalıştığını otomatik olarak algılar ve ilgili native SDK'ları devreye sokar. Bu sayede her bir dağıtım paketi (APK, IPA, Windows EXE) sadece kendi ihtiyaç duyduğu JavaScript kodlarını yükler ve çalıştırma zamanında maksimum performansı elde etmiş olur.

Eğer siz de ürünlerinizi hızlıca tüm cihazlara ulaştırmak isteyen bağımsız bir geliştiriciyseniz; Next.js + Capacitor + Electron üçlüsü, kod tekrarını sıfırlayan ve ürün geliştirme hızınızı 3 katına çıkaran mükemmel bir tercihtir. Bu modern hibrit mimari, pazara giriş sürenizi (time-to-market) ciddi ölçüde kısaltır ve tek kişilik ekiplerin bile devasa çoklu platform projelerini tek başına yönetebilmesini sağlar.


İlginizi Çekebilecek Diğer Yazılar