Monorepo Yönetimi: Turborepo ve Nx ile Proje Organizasyonu
Monorepo Nedir ve Neden İhtiyaç Duyarız?
Yazılım projelerinin büyümesiyle birlikte, birden fazla uygulamanın ve paylaşılan kütüphanelerin yönetimi giderek karmaşık bir hale gelir. Geleneksel yaklaşımda her proje ayrı bir repository'de (polyrepo) tutulur; ancak bu durum kod paylaşımını zorlaştırır, bağımlılık yönetimini karmaşıklaştırır ve ekipler arası koordinasyonu yavaşlatır. İşte tam bu noktada monorepo yaklaşımı devreye girer.
Monorepo, birden fazla projenin, kütüphanenin ve servisin tek bir versiyon kontrol deposunda tutulması anlamına gelir. Google, Meta, Microsoft ve Uber gibi teknoloji devleri yıllardır bu yaklaşımı başarıyla uygulamaktadır. Ancak monorepo yönetimi, doğru araçlar olmadan hızla bir kabus haline gelebilir. Bu yazıda, modern JavaScript/TypeScript ekosisteminin en popüler iki monorepo aracını — Turborepo ve Nx — derinlemesine inceleyeceğiz.
Monorepo'nun Avantajları ve Zorlukları
Avantajları
- Kod paylaşımı: Ortak kütüphaneler, tipler ve yardımcı fonksiyonlar tek bir yerden yönetilir. Bir değişiklik yapıldığında tüm bağımlı projeler anında güncellenir.
- Atomik commit'ler: Birden fazla projeyi etkileyen değişiklikler tek bir commit ile yapılabilir. Bu, tutarlılığı garanti altına alır.
- Tek bir CI/CD pipeline'ı: Tüm projeler için merkezi bir build ve deployment süreci kurulabilir.
- Bağımlılık yönetimi: Paylaşılan bağımlılıkların versiyonları tek bir noktadan kontrol edilir, "dependency hell" riski azalır.
- Refactoring kolaylığı: Projeler arası refactoring işlemleri çok daha güvenli ve kolay hale gelir.
Zorlukları
- Build süreleri: Proje sayısı arttıkça build süreleri uzayabilir. Akıllı önbellekleme ve artımlı build mekanizmaları şarttır.
- Repository boyutu: Tek bir depo zamanla çok büyüyebilir ve klonlama süreleri artabilir.
- Karmaşık yapılandırma: Her projenin kendi build, test ve lint yapılandırması olabilir; bunları uyumlu tutmak gerekir.
- Erişim kontrolü: Tüm ekiplerin tüm koda erişimi olması, bazı organizasyonlar için güvenlik endişesi yaratabilir.
Turborepo: Hız Odaklı Monorepo Aracı
Turborepo, Vercel tarafından geliştirilen ve özellikle hız ile basitlik üzerine odaklanan bir monorepo build sistemidir. Mevcut package manager'ınız (npm, yarn veya pnpm) ile workspace'lerinizin üzerine oturur ve build süreçlerinizi dramatik şekilde hızlandırır.
Turborepo Kurulumu
Yeni bir Turborepo projesi oluşturmak oldukça basittir:
npx create-turbo@latest my-monorepo
cd my-monorepo
Mevcut bir projeye Turborepo eklemek için:
npm install turbo --save-dev
Proje Yapısı
Tipik bir Turborepo proje yapısı aşağıdaki gibidir:
my-monorepo/
├── apps/
│ ├── web/ # Next.js web uygulaması
│ │ └── package.json
│ ├── mobile/ # React Native uygulaması
│ │ └── package.json
│ └── api/ # Express.js API servisi
│ └── package.json
├── packages/
│ ├── ui/ # Paylaşılan UI bileşenleri
│ │ └── package.json
│ ├── config-eslint/ # Paylaşılan ESLint yapılandırması
│ │ └── package.json
│ ├── config-typescript/ # Paylaşılan TypeScript yapılandırması
│ │ └── package.json
│ └── shared-utils/ # Paylaşılan yardımcı fonksiyonlar
│ └── package.json
├── turbo.json
├── package.json
└── pnpm-workspace.yaml
turbo.json Yapılandırması
Turborepo'nun kalbi turbo.json dosyasıdır. Bu dosyada task pipeline'larınızı ve önbellekleme stratejinizi tanımlarsınız:
{
"$schema": "https://turbo.build/schema.json",
"globalDependencies": ["**/.env.*local"],
"tasks": {
"build": {
"dependsOn": ["^build"],
"inputs": ["src/**"],
"outputs": ["dist/**", ".next/**", "!.next/cache/**"]
},
"test": {
"dependsOn": ["build"],
"inputs": ["src/**", "test/**"]
},
"lint": {
"dependsOn": ["^build"]
},
"dev": {
"cache": false,
"persistent": true
},
"type-check": {
"dependsOn": ["^build"]
}
}
}
Buradaki ^build ifadesi, bir paketin build edilmeden önce bağımlılıklarının build edilmesi gerektiğini belirtir. dependsOn dizisi ile görev sıralamasını, outputs dizisi ile önbelleğe alınacak dosyaları, inputs dizisi ile hangi dosya değişikliklerinin önbelleği geçersiz kılacağını tanımlarsınız.
Turborepo'nun Temel Özellikleri
- Artımlı build'ler: Sadece değişen paketler ve onlara bağımlı olan paketler yeniden build edilir.
- İçerik tabanlı hash'leme: Dosya içerikleri hash'lenerek önbellek anahtarları oluşturulur. Gereksiz yeniden build'ler önlenir.
- Paralel yürütme: Bağımsız görevler otomatik olarak paralel çalıştırılır, CPU çekirdekleri verimli kullanılır.
- Remote caching: Build çıktıları bulutta önbelleğe alınarak ekip üyeleri arasında paylaşılabilir. CI süreleri dramatik şekilde kısalır.
Remote caching'i etkinleştirmek için:
npx turbo login
npx turbo link
Nx: Kapsamlı Monorepo Platformu
Nx, Nrwl tarafından geliştirilen ve Turborepo'ya kıyasla çok daha geniş kapsamlı bir monorepo yönetim platformudur. Sadece build optimizasyonu değil, aynı zamanda kod üretimi, bağımlılık analizi, etkilenen proje tespiti ve kapsamlı eklenti ekosistemi sunar.
Nx Kurulumu
npx create-nx-workspace@latest my-workspace
cd my-workspace
Kurulum sırasında Nx size proje tipi, framework tercihi ve yapılandırma seçenekleri hakkında sorular sorar. Mevcut bir projeye Nx eklemek de mümkündür:
npx nx@latest init
Nx Proje Yapısı
my-workspace/
├── apps/
│ ├── web/
│ │ ├── src/
│ │ └── project.json
│ └── api/
│ ├── src/
│ └── project.json
├── libs/
│ ├── shared/
│ │ ├── ui/
│ │ │ ├── src/
│ │ │ └── project.json
│ │ └── utils/
│ │ ├── src/
│ │ └── project.json
│ └── feature/
│ ├── auth/
│ │ ├── src/
│ │ └── project.json
│ └── dashboard/
│ ├── src/
│ └── project.json
├── nx.json
├── package.json
└── tsconfig.base.json
nx.json Yapılandırması
{
"$schema": "./node_modules/nx/schemas/nx-schema.json",
"namedInputs": {
"default": ["{projectRoot}/**/*", "sharedGlobals"],
"production": [
"default",
"!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)",
"!{projectRoot}/tsconfig.spec.json"
],
"sharedGlobals": []
},
"targetDefaults": {
"build": {
"dependsOn": ["^build"],
"inputs": ["production", "^production"],
"cache": true
},
"test": {
"inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"],
"cache": true
},
"lint": {
"inputs": [
"default",
"{workspaceRoot}/.eslintrc.json",
"{workspaceRoot}/.eslintignore"
],
"cache": true
}
},
"defaultBase": "main"
}
Nx'in Temel Özellikleri
- Kod üreteci (generators): Nx, yeni bileşen, servis, kütüphane veya uygulama oluşturmak için güçlü kod üreticileri sunar.
- Bağımlılık grafiği: Projeler arasındaki bağımlılıkları görselleştirir ve analiz eder.
nx graphkomutu ile tarayıcıda interaktif bir graf görüntüleyebilirsiniz. - Etkilenen proje tespiti (affected): Git diff'e dayanarak hangi projelerin değişikliklerden etkilendiğini tespit eder ve sadece o projelerde işlem yapar.
- Zengin eklenti ekosistemi: React, Angular, Node.js, Next.js, Nest.js, Storybook ve daha fazlası için resmi eklentiler mevcuttur.
- Module boundary kuralları: Hangi kütüphanenin hangi kütüphaneye bağımlı olabileceğini etiketler (tags) aracılığıyla kontrol edebilirsiniz.
Etkilenen projelerde testleri çalıştırmak için:
npx nx affected --target=test --base=main
Bağımlılık grafiğini görselleştirmek için:
npx nx graph
Yeni bir kütüphane oluşturmak için:
npx nx generate @nx/js:library shared-utils --directory=libs/shared/utils
Turborepo ve Nx Karşılaştırması
Her iki araç da monorepo yönetiminde mükemmel çözümler sunsa da, farklı ihtiyaçlara hitap ederler:
- Öğrenme eğrisi: Turborepo çok daha düşük bir öğrenme eğrisine sahiptir. Mevcut workspace yapınıza bir
turbo.jsondosyası ekleyerek başlayabilirsiniz. Nx ise daha kapsamlı bir yapı sunar ve öğrenilmesi daha fazla zaman alır. - Yapılandırma felsefesi: Turborepo minimalist ve convention-over-configuration yaklaşımını benimser. Nx ise daha açık (explicit) bir yapılandırma tercih eder ve her proje için ayrı
project.jsondosyaları kullanır. - Kod üretimi: Nx güçlü kod üreticileri sunarken, Turborepo'da böyle bir özellik yoktur. Büyük ekiplerde tutarlı kod yapısını korumak için Nx'in generator'ları büyük avantaj sağlar.
- Eklenti ekosistemi: Nx, çok daha geniş ve olgun bir eklenti ekosistemine sahiptir. Angular, React, Next.js, Nest.js gibi framework'ler için first-party destek sunar.
- Build performansı: Her iki araç da önbellekleme ve paralel yürütme konusunda oldukça etkilidir. Turborepo Go ile yazılmıştır ve ham hız açısından hafif bir avantaja sahip olabilir; ancak pratikte fark çoğu proje için ihmal edilebilir düzeydedir.
- Remote caching: Her iki araç da remote caching destekler. Turborepo, Vercel altyapısı ile entegre çalışırken Nx, Nx Cloud üzerinden remote caching sunar.
Hangi Aracı Seçmelisiniz?
Doğru aracı seçmek, projenizin büyüklüğüne, ekibinizin deneyimine ve ihtiyaçlarınıza bağlıdır:
- Turborepo'yu tercih edin eğer mevcut bir workspace yapınız varsa ve minimum yapılandırma ile hız kazanmak istiyorsanız. Küçük-orta ölçekli projeler ve hızlı başlangıç yapmak isteyen ekipler için idealdir.
- Nx'i tercih edin eğer büyük ölçekli bir monorepo yönetiyorsanız, katı mimari kurallar uygulamak istiyorsanız ve kapsamlı araç desteğine ihtiyaç duyuyorsanız. Kurumsal projelerde ve büyük ekiplerde Nx'in sunduğu yapısal özellikler büyük fark yaratır.
Monorepo'da En İyi Uygulamalar
Hangi aracı seçerseniz seçin, aşağıdaki en iyi uygulamaları takip etmeniz önerilir:
- Net bir klasör yapısı belirleyin: Uygulamalar (
apps/) ve kütüphaneler (packages/veyalibs/) arasında net bir ayrım yapın. - Paylaşılan yapılandırmaları merkezileştirin: ESLint, TypeScript, Prettier gibi yapılandırmaları paylaşılan paketler olarak yönetin.
- Bağımlılık yönünü kontrol edin: Kütüphanelerin uygulamalara bağımlı olmasını engelleyin. Bağımlılık akışı her zaman uygulamalardan kütüphanelere doğru olmalıdır.
- CI pipeline'ınızı optimize edin: Sadece etkilenen projelerde build ve test çalıştırın. Remote caching'i mutlaka etkinleştirin.
- Küçük ve odaklı kütüphaneler oluşturun: Her kütüphane tek bir sorumluluğa sahip olmalıdır. Bu, önbellekleme verimliliğini artırır ve build sürelerini kısaltır.
- Versiyon yönetimi stratejinizi belirleyin: Tüm paketlerin aynı versiyonu mu paylaşacağına yoksa bağımsız versiyonlama mı yapılacağına karar verin. Changesets veya Nx Release gibi araçlar bu süreçte yardımcı olabilir.
Sonuç
Monorepo yaklaşımı, doğru araçlarla yönetildiğinde ekip verimliliğini ve kod kalitesini önemli ölçüde artırabilir. Turborepo basitliği ve hızıyla hızlı bir başlangıç sunarken, Nx kapsamlı özellik seti ile büyük ölçekli projelerde güçlü bir temel sağlar. Her iki araç da aktif olarak geliştirilmekte ve sürekli yeni özellikler eklenmektedir. Projenizin ihtiyaçlarını değerlendirin, küçük bir deneme projesi ile her iki aracı da test edin ve ekibiniz için en uygun olanı seçin. Unutmayın: en iyi araç, ekibinizin verimli bir şekilde kullanabildiği araçtır.