Micro-frontend mimarisi, büyük mühendislik takımlarının birbirinden bağımsız çalışmasına kapı açar; her ekip kendi uygulamasını ayrı yayına alır, ayrı test eder, bağımsız sürümler çıkarır. Organizasyon açısından bu bağımsızlık güçlü bir çekimdir. Tarayıcı ise organizasyonel sınırları tanımaz; her uygulama parçasının yüklenmesi, çalıştırılması ve bellekte tutulması için kaynak harcar.

Performans bedeli, mimari seçimden doğrudan kaynaklanır. Bağımsız deploy edilen uygulamalar, ortak bir kaynak stratejisi olmadığı durumda aynı kütüphaneleri defalarca yükler. React, ReactDOM, ortak bir tasarım sistemi paketi ya da yardımcı kütüphaneler, her micro-frontend tarafından ayrı ayrı bundle'a dahil edilebilir. Sayfada üç farklı micro-frontend varsa ve her biri kendi React kopyasını getiriyorsa, tekrarlı ağ trafiği ve parse yükü birikerek ölçülebilir bir gecikmeye dönüşür.

Sorun yalnızca dosya boyutuyla sınırlı değil. Tarayıcı aynı kütüphanenin farklı örneklerini bellekte tutmak, parse etmek ve derlemek zorunda kalır. Toplam JavaScript işleme süresi artar; bu özellikle düşük kapasiteli cihazlarda sayfa etkileşimini geciktirir. Mimarinin vaat ettiği bağımsızlık, yanlış kurulduğunda kullanıcı tarafında ekstra yük olarak görünür.

Runtime'da Kaynaklar Nasıl Çakışır?

Tek bir uygulamayı monorepo içinde derleyen bir takım, Webpack veya Vite'ın ağaç sallama (tree shaking) ve chunk bölme algoritmalarından tam anlamıyla yararlanır. Ortak bağımlılıklar tek bir dosyaya çıkarılır, tarayıcı bu dosyayı bir kez indirir ve önbelleğe alır. Sonraki ziyarette dosya önbellekten gelir, ağ isteği açılmaz.

Micro-frontend senaryosunda bu hesap değişir. Her uygulama ayrı ayrı derlenir. Derleme sırasında araçlar, diğer micro-frontend'lerin neler yükleyeceğini bilmez; dolayısıyla her biri kendi bağımlılık grafiğini çizer. Sonuçta ortak kütüphaneler ayrı bundle'lara girer. Tarayıcı bu bundle'ları paralel ya da sırayla indirir; ama her birini ayrı parse ve derleme adımlarından geçirir. Parse adımı, dosya boyutundan bağımsız olarak CPU zamanı harcar.

Paylaşım mekanizması olmadığında ek maliyet üç başlıkta toplanır: artan ağ trafiği, artan JavaScript işleme süresi ve ortak kütüphanelerin birden fazla örneğinin aynı anda bellekte yaşaması. Son madde yalnızca belleği değil bileşen ağaçlarının izolasyonunu da etkiler; farklı React örneklerinden gelen bileşenler aynı context veya ref mekanizmasını paylaşamaz. Teknik olarak bu, bileşenler arası veri akışını zorlaştırır ve ayrı state yönetimi katmanları gerektirir. Uygulamanın görsel bütünlüğü korunsa bile altta yatan veri tutarsızlıkları hata ayıklaması zor sorunlara dönüşebilir.

Önbellekleme Hesabı: Deploy Döngüleri Çakıştığında

HTTP/2, çoklu dosyaları tek bağlantıda paralel taşıdığından micro-frontend mimarisinde artan dosya sayısının ağ katmanında ciddi bir sorun olmadığı savunulur. Bu kısmen doğrudur. Ama önbellekleme tarafında resim farklılaşır.

Her micro-frontend ekibi kendi deploy döngüsünde çalışır. Ekiplerden biri React'i güncelleyip yeni bir bundle yayınladığında, o bundle'ın önbellek süresi sona erer. Kullanıcı sayfayı bir sonraki ziyaretinde bu paketi yeniden indirir. Ortak bir kütüphane tek bir shared bundle içinde yaşıyor olsaydı, yalnızca o kütüphane güncellendiğinde önbellek geçersizleşirdi; artık her ekibin deploy'u kendi kütüphanelerini içeren tüm bundle'ları etkiler.

Önbelleğin etkinliği azaldıkça tekrar ziyaretlerin performansı düşer. İlk açılış kadar olmasa da tekrar yükleme süreleri artar. Uzun oturumlar boyunca farklı micro-frontend'ler yüklendikçe bu birikimli yük fark edilir hale gelir. Takım sayısı arttıkça önbellek bozulma sıklığı da artar; hangi ekibin ne zaman deploy çıkardığını kontrol etmek güçleşir. İçerik karması (content hash) tabanlı dosya adlandırması ve uzun Cache-Control süreleri bu etkiyi kısmen hafifletir; ama farklı ekiplerin deploy frekansı birbirinden bağımsız olduğu sürece önbellek bozulmasını tamamen önlemek mümkün değildir.

Module Federation ile Paylaşım Nasıl Çalışır?

Webpack 5, Module Federation özelliğiyle bu soruna doğrudan bir çözüm sunar. Her uygulama, hangi modülleri "sağlayacağını" ve hangilerini dışarıdan "tüketeceğini" yapılandırma dosyasında bildirir. Çalışma zamanında (runtime) bir uygulama, React'i kendi bundle'ından değil paylaşılan havuzdan alır.

Uygulamada bu şu anlama gelir: host uygulama React'i yükler, remote uygulama aynı sürümü görmek istediğinde tarayıcı yeni bir istek açmaz, mevcut örneği kullanır. Paylaşılan kütüphaneler için singleton: true ayarı, aynı kütüphanenin yalnızca bir örneğinin yaşamasını garanti eder. Parse ve derleme yükü de bu sayede tekrarlanmaz.

Ancak bu yapı sürüm uyumunu kritik hale getirir. Bir remote uygulama [email protected] kullanırken host [email protected] sunuyorsa, Module Federation sürüm çakışmasını nasıl çözeceğine karar vermek zorunda kalır. requiredVersion ve strictVersion ayarları bu durumu kontrol altına alır; ama dikkatli yönetilmezse çalışma zamanı hataları beklenmedik anlarda ortaya çıkar. Sürüm yönetimi, Module Federation kullanan ekiplerin sürekli güncel tutması gereken bir sorumluluğa dönüşür; ekiplerden biri geride kalırsa paylaşım mekanizması bozulur ve kütüphane yeniden ayrı ayrı yüklenir. Büyüyen ekip sayısıyla bu koordinasyon yükü de büyür. Sürüm güncelleme kararları, paylaşılan paketleri kimin ne zaman yükselteceğini belirleyen ortak protokoller ve uyumsuz sürümleri önceden yakalayan CI kontrolleri bu sürecin kaçınılmaz parçalarına dönüşür. On ekibin üzerinde çalışan yapılarda bu koordinasyon, yarı zamanlı değil tam zamanlı bir sorumluluk hâline gelir.

Import Maps: Farklı Bir Yaklaşım

Import maps, tarayıcının modül tanımlayıcılarını gerçek URL'lere çevirmesini sağlar. react adı, tek bir URL'ye bağlanır; tüm micro-frontend'ler aynı dosyayı işaret eder. Tarayıcı bu dosyayı ilk istekte önbelleğe alır, sonraki remote'lar için yeni bir istek açmaz.

Kurulum karmaşıklığı Module Federation'a göre düşüktür. Webpack veya Vite yapılandırmasına derinden girmek gerekmez; merkezi bir importmap.json dosyası tüm micro-frontend'lerin tükettiği haritayı tutar. Araç bağımlılığı azdır; tarayıcı desteğini doğrudan temel alır. Bu sadelik, farklı framework'lerin bir arada çalıştığı ortamlarda Module Federation'ın sağlayamadığı esnekliği sunar.

Kısıtlamalar da var. Eski tarayıcılar için bir polyfill kütüphanesi gerekir. Paylaşılan paket CDN üzerinde barındırılacaksa CDN kesintisi tüm uygulamaları etkiler. Ağ yavaşsa paylaşılan modül gelmeden önce micro-frontend'ler bekler. Import maps, paket sürümünü çalışma zamanında değil konfigürasyonda sabitler; bu hem avantaj hem kısıttır. CDN güvenilirliğine bağımlı kalmak istemeyenler için Module Federation daha kontrollü bir seçenektir.

İlk Yükleme: Orkestrasyon Katmanının Ağırlığı

Micro-frontend shell uygulaması, genellikle tüm remote'ların metadatasını önceden yükler: hangi uygulamanın nerede barındırıldığı, hangi route'da devreye gireceği, hangi sürümün bekleneceği. Bu orkestrasyon katmanı ek bir JavaScript dosyası demektir; sayfa açılışında önce bu dosyanın gelmesi beklenir.

Kötü tasarlanmış bir orkestrasyon şelale (waterfall) etkisi yaratır. Shell indirilir, çalıştırılır; ardından remote manifest'leri istenir; ardından gerçek uygulama kodu gelir. Üç adım art arda sıralandığında, düz bir uygulama mimarisine kıyasla First Contentful Paint uzar. Üç adım değil, sekiz adımın sıralandığı kurulumlar da var; bu durumda gecikme daha belirgin olur ve ölçüm olmadan fark edilmesi güçleşir.

Bu şelaleyi kırmak için <link rel="preload"> etiketleriyle kritik remote'ların bundle'ları önceden talep edilebilir. Ya da critical path'e giren micro-frontend server-side render edilerek tarayıcı JavaScript bundle'ını beklemeden içeriği görür. Her iki yol da ek yapılandırma ister. Bunlar micro-frontend mimarisinin getirdiği ek seçimlerdir, düz bir uygulamada doğmayan maliyetlerdir.

Micro-Frontend Ne Zaman Doğru Seçimdir, Ne Zaman Gereksizdir?

Bağımsız deployment avantajı, yüksek çıktılı ve büyük mühendislik takımlarında gerçek bir organizasyonel kazanç sağlar. On farklı ekip, tek bir repository'de birbirine bağımlı dallar açmak yerine kendi pipeline'larını çalıştırır; bir ekibin deploy'u diğerini beklemez. Ölçek büyüdüğünde bu bağımsızlık, teslim süresini doğrudan kısaltır.

Küçük ya da orta ölçekli takımlarda bu hesap tersine döner. Organizasyon karmaşıklığı küçükse, micro-frontend mimarisinin getirdiği teknik yük kazandırdığından fazladır. Module Federation veya import maps'i kurmanın, sürümleri senkron tutmanın, orkestrasyon katmanını yönetmenin maliyeti tek bir build pipeline'ından çok daha yüksektir. Üstelik her uygulama ayrı derleneceğinden tüm micro-frontend'ler için tutarlı bir code splitting stratejisi uygulamak güçleşir; her ekip kendi chunk kurallarını yazdığında bütünlük kaybolur ve boyut regresyonları dikkatlerden kaçar.

Hangi kütüphanelerin paylaşılacağı, hangi sürümlerin kabul edileceği ve hangi micro-frontend'in ilk yüklenmede öncelikli olacağı, baştan netleştirilmesi gereken tasarım kararlarıdır. Bu kararlar sonradan eklenmek istendiğinde performans bedeli katlanarak büyür; zira her ekibin kendi bundle stratejisi artık yerleşmiştir ve değiştirmek koordinasyon gerektirir. Paylaşım stratejisi olmadan büyüyen bir micro-frontend sistemi, zamanla hem deploy bağımsızlığını hem de performans hedeflerini tehlikeye atar.

Teknoloji yığını homojenliğinin olmadığı geçiş projeleri ayrı bir kategori oluşturur. Farklı framework'lerin aynı çatı altında yaşadığı senaryolarda micro-frontend mimarisi bir tercih değil yapısal bir zorunluluk olarak belirir; paylaşım kısıtlıdır ama her parçanın izole derlenmesi geçişi yönetilebilir kılar. Paylaşımın sınırlı kalacağı biliniyorsa performans bedeli en baştan hesaba katılır ve buna göre önbellekleme ile orkestrasyon stratejisi kurulur.

Sayfaya micro-frontend taşımanın temel çekimi ekip özerkliğidir; bu özerkliğin tarayıcıya yansıyan faturası ise paylaşım stratejisi yoksa ağır kütüphane tekrarıdır. Module Federation doğru kurulduğunda bu tekrarı ortadan kaldırır, ama sürüm yönetimini beraberinde getirir. Import maps daha basit bir kurulum sunar, ama kontrol katmanını azaltır.

Mimari kararı seyrek değiştirilen bir seçimdir. Performans ve organizasyon boyutlarını baştan tartmadan alınan micro-frontend kararı zamanla her iki tarafta sorun üretir; ekipler koordinasyon yüküyle boğuşurken kullanıcılar gereksiz kütüphane kopyalarını indirmeye devam eder.

Paylaşım mekanizmasını erkenden kurmak, sürüm koordinasyonunu ekip sözleşmesine dönüştürmek ve orkestrasyon katmanını ölçülebilir tutmak; bunlar micro-frontend mimarisini hem organizasyonel hem de performans açısından işler kılan temel disiplinlerdir. Hangisi göz ardı edilirse mimari, vaat ettiği kazanımı tam olarak karşılayamaz.