Turborepo monorepoları için opinionated bir üretim referansı — workspace yapısı, iç paketler, görev grafiği tasarımı, önbellekleme, ortam değişkenleri, CI/CD ve deploy stratejileri. Turborepo 2.9 baz alınmıştır. Tutorial değil.
Bu referans, 2022'den bu yana her projede Turborepo çalıştırarak oluşturuldu — iki uygulamalı bir portfolyo monoreposundan 10 uygulama ve 14 paketle 600K LOC'luk bir AI platformuna kadar. Buradaki kalıplar, gerçek kod tabanlarıyla temas halinde hayatta kalanlar.
Her bölüm tek bir soruyu yanıtlar: Bunu üretim için gerçekten nasıl tasarlarım?
Turborepo 2.9 (Mart 2026) kapsar. Önemli yeni özellikler: İlk Göreve Kadar Sürede %96'ya kadar iyileştirme, turbo query kararlı, turbo.jsonc desteği, OpenTelemetry (deneysel), yapılandırılmış loglama (--json, --log-file), 3.0 geçişi için Future Flags.
Bir monorepo, karmaşıklığını yalnızca birden fazla uygulama arasında paylaşılması gereken kodun bulunduğu durumlarda karşılıyor. Uygulamalarınız minimum paylaşılan kodla bağımsız olarak gelişiyorsa, ayrı repolar daha basittir.
Monorepo ne zaman kullanılır:
✅ Birden fazla uygulama UI bileşenlerini, hook'ları, tipleri veya yardımcıları paylaşıyor
✅ Tek bir PR'ın paylaşılan bir paketi ve tüm tüketicilerini eş zamanlı güncellemesini istiyorsun
✅ Birleşik TypeScript, ESLint ve Prettier yapılandırması istiyorsun
✅ Atomik çapraz paket değişikliklerine ihtiyacın var
❌ Uygulamalar gerçekten bağımsız (farklı ekipler, farklı deploy döngüleri)
❌ Tek bir uygulaman var ve daha fazlası için planın yok
❌ Paylaşılan kod bir npm paketi olarak daha iyi olur
Monorepo vergisi: başlangıç kurulum karmaşıklığı, CI yapılandırma yükü ve zaman zaman şaşırtıcı önbellek davranışı. Bunlar gerçek maliyetler — faydaların durumun gerektirdiğinden ağır basıp basmadığı konusunda dürüst ol.
apps/ ve packages/ ayrımı bir kuraldır, zorunluluk değil. Önemli olan: uygulamalar deploy edilir ve diğer paketler tarafından import edilmez; paketler ise uygulamalar ve diğer paketler tarafından import edilen kütüphanelerdir.
packageManager alanı önemlidir — Turborepo bunu paket yöneticisini tespit etmek ve lockfile ayrıştırmayı kararlı hale getirmek için kullanır. Bu olmadan, önbellek geçersiz kılma öngörülemeyen olabilir.
Workspace içindeki iç paketler (kütüphaneler) üç şekilde yapılandırılabilir:
1. Just-in-Time (JIT) / Tüketici Tarafından Derlenen
Build adımı yok. Tüketicinin bundler'ı (Next.js, Vite vb.) TypeScript'i doğrudan derler.
// packages/ui/package.json{ "name": "@repo/ui", "exports": { ".": "./src/index.tsx" // doğrudan kaynağa işaret eder }, "devDependencies": { "typescript": "^5.0.0", "react": "^19.0.0" }}
Artıları: Sıfır build adımı, en hızlı iterasyon, dist/ konusunda endişe yok.
Eksileri: Yalnızca her tüketici TypeScript anlayan bir bundler kullandığında çalışır. Turborepo tarafından önbelleğe alınamaz (build çıktısı yok). TypeScript'te compilerOptions.paths kullanılamaz.
2. Derlenmiş Paket
Kendi build adımı var. Turborepo build çıktısını önbelleğe alabilir.
npm registry çakışmalarını önlemek için bir ad alanı öneki kullan. @repo/ kullanılmayan, talep edilemeyen bir ad alanıdır — yayınlanmayacak iç paketler için ideal.
"dependsOn": ["^build"] → tüm bağımlılık paketlerinde build'i önce çalıştır (topolojik)
"dependsOn": ["build"] → AYNI pakette build'i önce çalıştır
"dependsOn": [] → bağımlılık yok, her zaman çalıştır
"dependsOn": ["lint", "^build"] → bu paketin lint'ini VE tüm dep'lerin build'ini önce çalıştır
^ topolojik operatördür — "bağımlı olduğum tüm paketler." ^ olmadan "bu paket" anlamına gelir.
Paketteki kaynak dosyalar (varsayılan olarak gitignore edilmemiş tüm dosyalar)
Belirttiğin inputs glob kalıpları
env'de listelenen ortam değişkenleri
Global bağımlılıklar (globalDependencies)
Bağımlılık paketlerinden dependsOn çıktıları
Görev tanımının kendisi
Hash önbelleğe alınmış bir girişle eşleşirse: çıktıları geri yükle ve logları anında tekrar çal. Eşleşmezse: görevi çalıştır, ardından sonuçları önbelleğe al.
# CI ortam değişkenleri olarak ayarlaTURBO_TOKEN=vercel-token'inTURBO_TEAM=ekip-slug'in
Kendi barındırma (ducktors/turborepo-remote-cache):
# CI ortam değişkenleriTURBO_API=https://onbellek-sunucun.comTURBO_TOKEN=gizli-token'inTURBO_TEAM=ekibin
Yeni --cache flag'i (2.9'da kullanımdan kaldırılan flag'lerin yerini alır):
# Yerel okuma+yazma, uzak salt okunurturbo build --cache=local:rw,remote:r# Yalnızca uzakturbo build --cache=remote:rw# Önbelleği tamamen devre dışı bırak (--no-cache'in yerini alır)turbo build --cache=local:r,remote:r
❌ Ağ yan etkileri olan görevler (API çağrıları, DB mutasyonları)
❌ Dev sunucuları (her zaman cache: false, persistent: true kullan)
❌ Önbellek ek yükünden daha hızlı görevler (100ms altı görevler)
❌ Devasa çıktıları olan görevler (>500MB Docker imajları)
Ortam değişkenleri önbellek hash'inin bir parçasıdır. Bir env değişkeni değişirse, önbellek ıskalanır. Env değişkenlerini bildirmeyi unutursan, eski önbellekler elde edersin.
{ "tasks": { "build": { "env": [ "DATABASE_URL", // build'i etkiler → dahil et "NEXT_PUBLIC_APP_URL", // public env, bundle'ı etkiler → dahil et "NODE_ENV" // build davranışını etkiler → dahil et ], "passThroughEnv": [ "CI", // çalışma zamanında gerekli, çıktıyı etkilemez → geçir "VERCEL_URL" // deploy başına değişen URL → geçir ] } }}
env: Bu değişkenlerdeki değişiklikler önbelleği geçersiz kılar.
passThroughEnv: Göreve geçirilir ama önbellek hash'ini etkilemez.
CI sistemleri her çalıştırmada değişen CI_JOB_ID, GITHUB_SHA, BUILD_NUMBER gibi değişkenler ayarlar. Bunları hash'e dahil edersen, hiçbir zaman önbelleğe isabet edemezsin.
Otomatik çıkarımdan CI'ya özel önekleri hariç tutmak için TURBO_CI_VENDOR_ENV_KEY kullan:
# GITHUB_*'ı Turborepo'nun otomatik env çıkarımından hariç tutTURBO_CI_VENDOR_ENV_KEY=GITHUB_
# Tüm paketlerde görev çalıştırturbo buildturbo devturbo lint# Yalnızca belirli paketler için çalıştırturbo build --filter=webturbo build --filter=@repo/uiturbo build --filter=./apps/web# Bir paket ve tüm bağımlılıkları için çalıştırturbo build --filter=web...# Main'e göre değişen paketler için çalıştırturbo build --affected# Bir dizindeki paketler için çalıştırturbo build --filter="./apps/*"
turbo dev # otomatik olarak TUI kullanır# Belirli UI'yı zorlaturbo build --ui=tui # etkileşimliturbo build --ui=stream # geleneksel log akışı (CI için iyi)
TUI'de: paketler arasında gezinmek için ok tuşlarını kullan, paketin loglarına odaklanmak için Enter'a bas, odaktan çıkmak için Ctrl+Z.
GraphQL veya kısayollarla monorepo yapını sorgula:
# Etkileşimli GraphiQL playground'u açturbo query# Mevcut değişikliklerden etkilenen paketler hangileri?turbo query affected# packages/ui'yi değiştirirsem hangi paketler etkilenir?turbo query affected --packages# packages/ui'yi değiştirirsem hangi görevler çalışır?turbo query affected --tasks build# Tüm paketleri listeleturbo query ls# Belirli bir paket için detaylarturbo query ls web# Yalnızca etkilenen paketleri listeleturbo query ls --affected
Yalnızca PR'da değişen paketler için görevleri çalıştır:
- name: Etkilenen görevleri çalıştır run: pnpm turbo build test --affected # Turborepo, GitHub Actions'ta GITHUB_BASE_REF'i otomatik tespit eder # PR head'ini PR base branch'iyle karşılaştırır # Geçmiş mevcut değilse (shallow clone) her şeyi çalıştırmaya geri döner
Önemli:--affected git geçmişine ihtiyaç duyar. Tam geçmiş için fetch-depth: 0 kullan:
- name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 # doğru --affected için tam geçmiş
Not: Bu makine başına önbellek, paylaşılan bir uzak önbellekten çok daha az etkilidir. Ekip genelinde paylaşım için Vercel Uzak Önbelleği veya kendi barındırmalı sunucu kullan.
turbo prune, tek bir uygulama için yalnızca neye ihtiyacı varsa onu içeren seyrek bir workspace oluşturur:
# web uygulaması için kırpılmış workspace oluşturturbo prune web --docker
Çıktı:
out/
├── json/ # yalnızca package.json dosyaları (bağımlılık kurulum katmanı için)
│ ├── package.json
│ └── apps/web/package.json
└── full/ # tam kaynak kodu
├── package.json
├── turbo.json
└── apps/web/
FROM node:20-alpine AS base# Kırpılmış workspace'den bağımlılıkları kurFROM base AS installerWORKDIR /appCOPY out/json/ .RUN pnpm install --frozen-lockfile# Tam kaynaktan build etFROM base AS builderWORKDIR /appCOPY --from=installer /app/node_modules ./node_modulesCOPY out/full/ .# Uzak önbellek kimlik bilgileriARG TURBO_TOKENARG TURBO_TEAMENV TURBO_TOKEN=$TURBO_TOKENENV TURBO_TEAM=$TURBO_TEAMRUN pnpm turbo build --filter=web# Üretim imajıFROM base AS runnerWORKDIR /appCOPY --from=builder /app/apps/web/.next/standalone ./EXPOSE 3000CMD ["node", "server.js"]
# İsme göre--filter=web--filter=@repo/ui# Yola göre--filter=./apps/web--filter="./apps/*"# Bağımlıları dahil et (hedefe bağımlı paketler)--filter=web... # web ve bağımlıları--filter=...web # web ve bağımlılıkları# Git değişikliklerine göre--filter="[HEAD^1]" # son commit'te değişen--filter="[main...HEAD]" # main'den itibaren değişen# Etkilenen (akıllı git tespiti)--affected # base ref'i otomatik tespit eder
Yapı
☐ Deploy edilebilir uygulamalar için apps/
☐ Paylaşılan kütüphaneler ve yapılandırma için packages/
☐ Kök package.json'da packageManager alanı
☐ .gitignore'da .turbo
☐ İç paketler için ad alanı öneki (@repo/)
Görevler
☐ Kütüphaneler için build'de dependsOn: ["^build"] var
☐ build çıktıları bildiriliyor
☐ dev'de cache: false, persistent: true var
☐ Her TypeScript paketinde check-types görevi
☐ Uygulamaya özgü çıktılar için Paket Yapılandırmaları (paket başına turbo.json)
Önbellekleme
☐ Env değişkenleri tasks.env'de bildiriliyor
☐ CI env değişkenleri önbellek isabetsizliğine neden olmuyor
☐ Ekip için uzak önbellek yapılandırılmış
☐ Önbellek artifact imzalama etkin (üretim)
CI
☐ --affected'ın çalışması için fetch-depth: 0
☐ TURBO_TOKEN ve TURBO_TEAM CI secret'ları olarak ayarlanmış
☐ Seçici build'ler için --affected
☐ CI dostu çıktı için --ui=stream
1. Env değişkeni turbo.json'da bildirilmemiş → env[]'e ekle
2. CI env değişkeni hash'e dahil → passThroughEnv[]'e ekle veya TURBO_CI_VENDOR_ENV_KEY ile hariç tut
3. outputs bildirilmemiş → outputs[]'a ekle
4. globalDependencies değişti (lockfile, tsconfig) → beklenen
5. Bağımlılık paketi değişti → beklenen (topolojik yayılım)
Son güncelleme: Nisan 2026. Turborepo 2.9 (Mart 2026) kapsar. Önemli özellikler: İlk Göreve Kadar Sürede %96 iyileştirme, turbo query kararlı, turbo.jsonc, OpenTelemetry (deneysel), yapılandırılmış loglama, 3.0 geçişi için Future Flags.