NX Monorepo & Micro-frontend
İlan 1 & 2 özel · İlan 1 İlan 2

NX Monorepo, Micro-frontend, Build & Performans

Turkcell.com.tr ve Superonline.net gibi birden fazla büyük ürünü aynı ekipler geliştirdiğinde ortaya çıkan "kod paylaşımı" ve "performans" problemlerine verilen cevaplar.

NX Monorepo — neden tek repo?

Çoklu ürün (turkcell.com.tr, superonline.net) aynı buton/form/API çağrısı mantığını tekrar tekrar yazmasın diye, hepsi tek bir repo altında, paylaşılan libs/ ile geliştirilir. NX bu yapıyı yönetmek için: bağımlılık grafiği çıkarır, sadece değişen projeleri build/test eder (affected), kod paylaşımını kütüphane sınırlarıyla zorunlu kılar.

nx-workspace
apps/
  web-turkcell/          ← turkcell.com.tr
  web-superonline/        ← superonline.net
libs/
  ui-components/          ← paylaşılan buton, kart, form elemanları
  data-access-billing/    ← fatura/ödeme API çağrıları
  utils-formatting/       ← para birimi, tarih formatlama vb.

# Yeni bir paylaşılan kütüphane üret
nx generate @nx/react:library ui-components

# Sadece SON COMMIT'te değişen projeleri test et (tüm repoyu değil)
nx affected:test

# Proje bağımlılık grafiğini görselleştir
nx graph

Micro-frontend — ne zaman gerekir?

Farklı ekipler aynı sayfanın farklı parçalarını (ör. header turkcell ekibinden, ödeme akışı ayrı bir ekipten) bağımsız deploy edilebilir parçalar halinde geliştirsin diye kullanılır. En yaygın teknik: Webpack Module Federation — bir app, başka bir app'in derlenmiş bir parçasını runtime'da "ödünç alır".

webpack.config.js
// webpack.config.js — superonline app, turkcell app'ten "header" alıyor
new ModuleFederationPlugin({
  name: "superonline",
  remotes: {
    turkcell: "turkcell@https://turkcell.com.tr/remoteEntry.js",
  },
  shared: ["react", "react-dom"], // aynı React kopyasını paylaş
});
⚠️
Mülakat tuzağı: her yere micro-frontend önermeMicro-frontend karmaşıklık ekler (versiyon uyumu, shared dependency yönetimi, network overhead). Doğru cevap: "birden fazla bağımsız ekip aynı ürünü paralel geliştiriyorsa ve deploy bağımsızlığı gerçek bir ihtiyaçsa tercih ederim — küçük tek ekipli bir üründe NX monorepo + paylaşılan libs yeterli, micro-frontend over-engineering olur."

Webpack vs Vite

WebpackVite
Dev sunucuTüm bundle'ı önceden derler → büyük projede yavaş başlarNative ESM kullanır, dosyayı tarayıcı ister istemez derler → anında açılır
Prod buildKendi bundler'ıRollup kullanır (dev'de esbuild)
Olgunluk / pluginÇok olgun, dev ekosistemi devasa (özellikle NX/enterprise)Daha genç ama hızla büyüyor, çoğu Webpack plugin'inin eşdeğeri var

Performans optimizasyonu: lazy loading, code splitting, memoization

Turkcell ilanında ayrı ayrı sayılan bu üç kavram aslında birbirini tamamlar: ilk ikisi "gerekmeyen kodu indirme", üçüncüsü "gerekmeyen render'ı yapma" problemini çözer.

// Lazy loading + code splitting — bu parça sadece ihtiyaç anında indirilir
import { lazy, Suspense } from "react";
const FaturaOdemeSihirbazi = lazy(() => import("./FaturaOdemeSihirbazi"));

function OdemeSayfasi() {
  return (
    <Suspense fallback={<Yukleniyor />}>
      <FaturaOdemeSihirbazi />
    </Suspense>
  );
}

// Memoization — gereksiz yeniden hesaplama/render'ı engeller
const ToplamTutar = memo(function ToplamTutar({ items }: { items: Item[] }) {
  const toplam = useMemo(() => items.reduce((s, i) => s + i.price, 0), [items]);
  return <span>{toplam} ₺</span>;
});

React Profiler / DevTools ile hangi component'in ne sıklıkla ve neden yeniden render olduğunu görürsün — "neden yavaş" sorusuna tahminle değil, ölçümle cevap verirsin.

Lighthouse ve Core Web Vitals

MetrikNe ölçerİyi eşik
LCP (Largest Contentful Paint)En büyük içerik ne zaman göründü< 2.5s
INP (Interaction to Next Paint)Tıklamadan ekranın tepki vermesine kadar geçen süre< 200ms
CLS (Cumulative Layout Shift)Sayfa yüklenirken içeriğin ne kadar "zıpladığı"< 0.1

Egzersizler

1) Bir sayfanın LCP değeri 4.2s çıkıyor. İlk 3 şüphelin ne olurdu?
1) Hero görselinin optimize edilmemiş/büyük olması (WebP değil, lazy değil) — LCP genelde en büyük görsel/başlıktır. 2) Render-blocking JS/CSS — kritik olmayan script'lerin defer/async olmaması. 3) Yavaş sunucu yanıt süresi (TTFB) — SSR/API gecikmesi. Lighthouse raporundaki "Opportunities" bölümü genelde bunu doğrudan söyler.
2) useMemo/useCallback her yere eklemek her zaman performansı artırır mı?
Hayır — her useMemo kendi başına bir bellek + karşılaştırma maliyeti taşır. Ucuz hesaplamalarda veya nadiren render olan component'lerde gereksiz karmaşıklık ekler. Doğru kullanım: React Profiler'da gerçekten pahalı olduğu ÖLÇÜLEN hesaplamalarda veya React.memo'lu bir child'a prop referansının her render'da değişmemesi gerektiği durumlarda.