Blog'a Dön
pnpmMonoreponpmTypeScriptVersioningRe-Shell

Bir npm Org Yayınlayan Bir pnpm Monorepo Tasarlamak

Umut Korkmaz2026-04-297 min read

Hiçbir özellik listesinde görünmeyen belirli bir karmaşıklık türü vardır. Birden fazla paketi temiz bir şekilde yayınlayan bir monorepo işletmek, sürümlerini makul tutmak ve paylaştıkları tiplerin asla sessizce birbirinden ayrılmamasını sağlamak. Re-Shell bu türden bir proje. Bir npm organizasyonu yayınlayan bir pnpm monorepo'su ve orada gurur duyduğum mühendisliğin çoğu, onu kullanan herkese görünmez. Bu, o görünmez kısımla ilgili bir yazı çünkü tek başına bakım yapanların (solo maintainer) genellikle yandığı yer orası.

Neden pnpm Çalışma Alanları

Repo bir pnpm çalışma alanı ve bu seçim gelişigüzel değildi. pnpm'in içerik adresli deposu ve katı node_modules düzeni, çok paketli bir repoda insanların beklediğinden daha fazla önemlidir. Katılık asıl meseledir. Bir paketin, bağımlılık olarak bildirmediği bir şeyi import etmesine izin vermeyi reddeder; bu da bir paketin yerine hoist edilmiş bir geçişli (transitive) bağımlılığa yanlışlıkla yaslanamayacağı anlamına gelir. Üç paketin kendi başına yayınlanabilir olması gereken bir repoda, o disiplin, paketleri kurulum düzeni aracılığıyla gizlice birbirine bağlı değil, gerçekten bağımsız tutan şeydir.

Çalışma alanı ayrıca yerel geliştirmeyi dürüst kılar. CLI contracts'a bağlı olduğunda, çalışma alanı sürümüne çözülür; böylece paylaşılan tiplerdeki bir değişiklik, bir yayın adımı olmadan repo genelinde anında yansır. O sıkı iç döngü, bir monorepo'nun ek yüke değmesinin asıl nedeninin çoğudur.

Paket Düzeni

Yapı kasıtlı olarak sade. Bir packages dizini ve içinde üç paket var: cli, ui ve contracts. Tüm hikâye bu ve düzlük kasıtlı. Çoğunlukla gezinmeyi zorlaştırmaya hizmet eden ayrıntılı iç içe hiyerarşilere büyüyen monorepo'lar gördüm. Üç paket, bir seviye derinlikte, her birinin net bir işi var.

CLI insanların çalıştırdığı araç. UI, Shadcn öncelikli bileşen kütüphanesi. Contracts, paylaşılan TypeScript sınırı ve kilit taşı. Hem CLI hem UI contracts'a bağlı ve hiçbiri diğerine bağlı değil. O bağımlılık şekli bir kaza değil. İki tüketici paketin ortak tek şeyinin, üzerinde anlaşılan tipler olduğu anlamına gelir; tam da istediğim ilişki.

Birbirinden Ayrılamayacak Şey Olarak Contracts

Tek en önemli tasarım kararını adlandırmam gerekseydi, bu, contracts'ı her tüketiciye kopyalanan bir tipler klasörü yerine gerçek, ayrı sürümlenen bir paket yapmaktır. Karşı tasarladığım tüm başarısızlık modu sapmadır (drift). UI, CLI'ın ürettiğinden biraz farklı bir şekil fikri geliştirir, kimse fark etmez çünkü ikisi de izolasyonda sorunsuz derlenir ve uyuşmazlık haftalar sonra bir çalışma zamanı hatası olarak yüzeye çıkar.

Paylaşılan tipleri her iki tarafın da import ettiği tek bir pakete koyarak, sapma bir üretim olayı yerine bir derleme hatasına dönüşür. Bir sözleşmeyi değiştirirsem, henüz yetişmemiş her tüketici tip kontrolünden geçmeyi durdurur. İstediğiniz gürültülü, erken başarısızlık budur. Kırıcı (breaking) bir değişikliğin maliyetini, onu yaptığınız ana taşır; bu da onu düzeltmenin ucuz olduğu tek andır.

Sürümleme ve Yayın Disiplini

Tek bir repodan birden fazla paket yayınlamak, yarım kalmış bir yayın gönderdiğiniz ilk ana kadar basit gelir. Sahip olduğum disiplin, contracts'ın önderlik etmesidir. Bir değişiklik paylaşılan tiplere dokunuyorsa, contracts önce sürümlenir ve tüketiciler aynı yayında yeni sürüme bağlı olacak şekilde yükseltilir. CLI ve UI, henüz var olmayan bir contracts yayınına referans veren bir sürüm asla göndermez.

Sürümlemeyi konvansiyonel ve sıkıcı tutuyorum. Yayınlanmış bir tipe kırıcı bir değişiklik, contracts'ta bir major artış demektir, nokta; küçük hissettirse bile, çünkü aşağı akıştaki biri ona sabitlenmiş (pin) olabilir. Tek başına bakım yapan biri olarak cazibe, bunu görmezden gelmek çünkü repodaki tüm tüketicileri siz denetliyorsunuz. Ama npm org paketleri herkese açık yapar ve herkese açık oldukları an, kimin neye bağlı olduğunu artık tam olarak denetlemezsiniz. Yayınlanmış yüzeyi, çoğunlukla yalnızca siz olsanız bile gerçek bir sözleşme olarak ele almak, onu sonradan güvenilir tutan şeydir.

Bir Org'u Tek Başına İşletmenin Sürtünmesi

Bir npm organizasyonunu tek başına bakım yapan biri olarak işletmenin belirli bir dokusu var. Yayınlanan her paket küçük, devam eden bir yükümlülüktür. Org altındaki kapsamlı (scoped) adlandırma temizdir ve paketlerin bir arada ait olduğunu işaret eder; bunu severim ama aynı zamanda üç ayrı yayın adımı, dürüst tutulacak üç değişiklik günlüğü (changelog) ve bir hatanın sızabileceği üç yer demektir. Botched bir yayını yakalayacak ikinci bir gözden geçiren yok. CI/CD tesisatı kısmen o ikinci gözden geçiren olmak için var; herhangi bir şey çıkmadan önce kontrolleri ve derlemeyi çalıştırır.

Yapay zekâ kodlama ajanlarının yerini hak ettiği yer de burası. Yayın hijyeninin mekanik kısımları — farktan (diff) değişiklik günlükleri taslamak, sürüm artışlarının üç paket genelinde tutarlı olduğunu kontrol etmek, major artış tetiklemesi gereken sözleşme değişikliğini yakalamak — tam da uzun bir günün sonunda yapıp ince ince yanlış yapacağım şeyler. Bu tür inceleme geçişi için Claude'a yaslanıyorum. Bir yayının ne içermesi gerektiği konusundaki muhakemenin yerini almıyor ama tek başına bakım yapanların kaydığı sıkıcı kısımlarda güvenilir bir ekstra göz çifti.

Bunu Yapan Herkese Söyleyeceğim Şey

Gerçekten daha fazlasına ihtiyaç duyana kadar paket sayısını küçük tutun. Paylaşılan tiplerinizi birinci sınıf bir paket yapın ve yayınlanmış yüzeyini ilk günden bir sözleşme olarak ele alın. Yayın sıranıza karar verin ve onu asla bozmayın. Monorepo araçları kolay kısımdır. Zor kısım, üç paketi sessizce birbirinden ayrılmaktan koruyan disiplindir ve o disiplin çoğunlukla, uygun olmadan önce kendinizi adadığınız bir kurallar setidir.