10 puan yazan GN⁺ 2026-03-23 | 2 yorum | WhatsApp'ta paylaş
  • npm ekosisteminde bağımlılık ağacının şişmesi önemli bir sorun olarak gösteriliyor; bunun başlıca nedenleri eski runtime desteği, atomik paket yapısı ve eski ponyfill kullanımı
  • Eski motor uyumluluğu ve cross-realm güvenliği gerekçesiyle korunan küçük yardımcı paketler, modern ortamlarda da gereksiz yere varlığını sürdürüyor
  • Atomik mimari, yeniden kullanılabilirliği artırmayı hedefledi ancak pratikte tekrar, güvenlik ve bakım maliyetlerini artıran verimsiz bir yapıya dönüştü
  • Tüm motorların zaten desteklediği özellikler için kullanılan eski ponyfill paketleri kaldırılmadığı için gereksiz indirme ve yönetim yükü oluşturuyor
  • Topluluk, e18e, knip ve module-replacements gibi araçlarla gereksiz bağımlılıkları temizleme ve yerel özelliklere geçiş sürecini ilerletiyor

JavaScript bağımlılık şişkinliğinin üç ekseni

  • e18e topluluğu büyüdükçe performans odaklı katkılar artıyor ve gereksiz ya da bakımsız paketleri ayıklamaya yönelik cleanup çalışmaları yürütülüyor
  • npm ekosisteminde bağımlılık ağacının şişmesi (dependency bloat) başlıca sorunlardan biri olarak öne çıkıyor; bunun temel nedenleri eski runtime desteği, atomik paket yapıları ve eski ponyfill kullanımı

1. Eski runtime desteği (güvenlik ve realm dahil)

  • npm ağacında is-string, hasown gibi birçok küçük yardımcı paket bulunuyor ve bunlar şu üç nedenle varlığını sürdürüyor
    • Çok eski motorları desteklemek (ES3, IE6/7, erken dönem Node.js gibi)
    • Global namespace’in değiştirilmesine karşı koruma

      • cross-realm değer işleme
  • Eski motor desteği

    • ES3 ortamlarında Array.prototype.forEach, Object.keys, Object.defineProperty gibi ES5 özellikleri yoktur
    • Bu ortamlarda özellikler doğrudan uygulanmalı ya da polyfill kullanılmalıdır
    • En iyi çözüm yükseltme yapmak olsa da bazı kullanıcılar hâlâ eski sürümlerde kalıyor
  • Global namespace’in değiştirilmesine karşı koruma

    • Node, global nesneleri ilk anda sarıp değişikliklere karşı korumak için dahili olarak primordials kavramını kullanır
    • Örneğin Map yeniden tanımlanırsa Node’un kendisi bozulabilir; bu yüzden Node özgün referansı korur
    • Bazı paket bakımcıları bu yaklaşımı genel paketlerde de uygulayarak math-intrinsics gibi güvenlik odaklı paketler kullanır
  • Cross-realm değerler

    • iframe’ler arasında nesne aktarılırken instanceof denetiminin başarısız olması sorunu ortaya çıkar
    • Örnek: window.RegExp !== iframeWindow.RegExp
    • chai gibi test framework’leri realm’ler arası tür denetimi için Object.prototype.toString.call(val) yaklaşımını kullanır
    • is-string gibi paketler bu cross-realm uyumluluğu için vardır
  • Sorunlar

    • Geliştiricilerin büyük çoğunluğu modern Node veya evergreen tarayıcılar kullanır; bu tür uyumluluklara ihtiyaç duymaz
    • Buna rağmen bu paketler genel bağımlılık ağacının “hot path” içinde yer alır ve maliyeti herkes öder

2. Atomik (Atomic) mimari

  • Bazı geliştiriciler, paketlerin olabildiğince küçük parçalara ayrılması ve yeniden kullanılabilir yapı taşları olarak düzenlenmesi gerektiğini savunur
  • Sonuç olarak shebang-regex, arrify, slash, path-key, onetime, is-wsl gibi aşırı derecede parçalanmış paketler ortaya çıkmıştır
  • Örnek: shebang-regex yalnızca tek satırlık bir regex içerir (/^#!(.*)/)
  • Sorunlar

    • Atomik paketlerin çoğu yeniden kullanılmaz ya da yalnızca tek bir tüketiciye sahiptir
    • Örnekler:
      • shebang-regex → yalnızca shebang-command tarafından kullanılır
      • cli-boxes → yalnızca boxen, ink tarafından kullanılır
      • onetime → yalnızca restore-cursor tarafından kullanılır
    • Bu durumda paket, satır içi kodla aynı işi yapar ama npm isteği, arşiv açma, bant genişliği gibi ek maliyetler doğurur
  • Tekrarlama sorunu

    • Örnek: nuxt@4.4.2 bağımlılık ağacında is-docker, is-stream, is-wsl, path-key gibi paketlerin ikişer sürümü bulunur
    • Satır içi kodla değiştirildiğinde sürüm çakışması ya da çözümleme maliyeti ortadan kalkar; böylece tekrar maliyeti neredeyse sıfırlanır
  • Tedarik zinciri riskinin büyümesi

    • Paket sayısı arttıkça güvenlik ve bakım riskleri de artar
    • Gerçekte bir bakımcının çok sayıda küçük paketi yönettiği ve hesabı ele geçirilince yüzlerce paketin aynı anda bozulduğu bir olay yaşanmıştır
    • Basit bir kod (Array.isArray(val) ? val : [val]) ayrı bir pakete gerek olmadan doğrudan satır içi kullanılabilir
  • Sonuç

    • Atomik mimari, niyetin aksine verimsiz ve riskli bir yapıya dönüşmüştür
    • Çoğu kullanıcı için somut fayda sağlamadan tüm ekosistem maliyeti üstlenir

3. Eski ponyfill’ler

  • Polyfill, motorun desteklemediği bir özelliği ortama ekleyen koddur; Ponyfill ise ortamı değiştirmeden doğrudan import edilerek kullanılan alternatif bir uygulamadır
  • Örnek: @fastly/performance-observer-polyfill hem polyfill hem ponyfill sağlar
  • Sorunlar

    • Ponyfill’ler geçmişte faydalıydı, ancak hedef özellik tüm motorlarda zaten desteklense bile kaldırılmıyorlar
    • Örnekler:
      • globalthis (2019’dan beri destekleniyor, haftalık 49 milyon indirme)
      • indexof (2010’dan beri destekleniyor, haftalık 2,3 milyon indirme)
      • object.entries (2017’den beri destekleniyor, haftalık 35 milyon indirme)
    • Bu paketler çoğunlukla yalnızca kaldırılmadıkları için varlığını sürdürüyor
    • Tüm LTS motorlar bir özelliği destekliyorsa ponyfill kaldırılmalıdır

Şişkinliği azaltma yolları

  • Bağımlılık ağacındaki derin iç içe geçme nedeniyle temizlik zor olsa da topluluk iş birliğiyle iyileştirme mümkündür
  • Her geliştirici “Bu paket gerçekten gerekli mi?” diye sormalı; gereksizse issue açmalı ya da alternatif paket aramalıdır
  • module-replacements projesi, yerel özelliklerle değiştirilebilen paketlerin listesini sunar
  • knip kullanımı

    • knip, kullanılmayan bağımlılıkları ve ölü kodu tespit eden bir araçtır
    • Doğrudan çözüm olmasa da temizliğe başlamak için yararlıdır
  • e18e CLI kullanımı

    • @e18e/cli analyze komutuyla değiştirilebilir bağımlılıklar tespit edilebilir
    • Örnek: chalkpicocolors için otomatik geçiş
    • İleride ortama göre Node’un styleText gibi yerel özellikleri de önerilecek
  • npmgraph kullanımı

    • npmgraph.js.org, bağımlılık ağacını görselleştiren bir araçtır
    • Örnek: eslint@10.1.0 ağacında find-up dalı izole durumdadır
    • Basit dosya arama işlevi için 6 pakete ihtiyaç olmadığından empathic gibi daha küçük alternatifler kullanılabilir
  • module replacements projesi

    • Topluluk, değiştirilebilir paketler ve yerel özellikler arasındaki eşleme veri kümesini sürdürüyor
    • codemods projesi üzerinden otomatik geçişler de destekleniyor

Sonuç

  • Mevcut şişkinlik, eski uyumluluk ya da sıra dışı yapıları korumak isteyen küçük bir kesim yüzünden maliyetin herkes tarafından ödendiği bir yapıya dönüşmüş durumda
  • Geçmişte bu kaçınılmazdı, ancak modern motorlar ve API’ler artık yeterince geliştiği için bu yük gereksiz hale geldi
  • Bundan sonra bu küçük kesimin ayrı bir yığın sürdürmesi, geri kalanların ise hafif ve modern bir kod tabanına yönelmesi gerekiyor
  • e18e ve npmx gibi projeler bunu dokümantasyon ve araçlarla destekliyor; geliştiricilerin de kendi bağımlılıklarını gözden geçirip “Neden gerekli?” sorusunu sorması gerekiyor
  • Hep birlikte temizlik yapılabilir

2 yorum

 
click 2026-03-23

Ben de kütüphane yaparken hâlâ cjs build’i sunuyorum ama
2026’da esm örneği bile olmayan ve tamamen require tabanlı kütüphanelerin biraz güncellenmesini isterdim.

 
GN⁺ 2026-03-23
Hacker News görüşleri
  • Bugünlerde bağımlılıksız JavaScript ile geliştirme yapmanın en iyi yön olduğunu düşünüyorum
    JS/CSS standart kütüphaneleri de harika, statik analiz (TypeScript'in JSDoc kontrolleri), ES modülleri, web bileşenleri gibi araçlar da fazlasıyla güçlü
    İnsanlar bu yaklaşımın ölçeklenebilirlik ya da bakım açısından dezavantajlı olduğunu söylüyor ama benim deneyimimde tam tersine daha basit ve değiştirmenin kolay olduğu bir yapı korunabildi

    • Ben de birkaç yıldır bu yaklaşımı deniyorum ve plainvanillaweb.com adında bir eğitim sitesi de yaptım
      Framework'lerin ya da build araçlarının yaptığı işlerin çoğu, tarayıcıya gömülü özellikler ve vanilla pattern'lerle değiştirilebilir
      Ancak bu yaklaşım hâlâ pek tanıdık bir alan değil; sorun da eğitim ekosisteminin büyük ölçüde büyük framework'ler etrafında dönmesi
      Nitekim React kodunu tamamen vanilla'ya taşısanız bile modülerlik korunuyor ve kod uzunluğu yalnızca yaklaşık 1.5 kat artıyor; buna karşılık bağımlılık olmadığı için performans daha iyi oluyor
      Elbette bağımlılıkların kötü olduğunu söylemiyorum. Sadece birçok geliştirici, “mutlaka kullanılmaları gerekir” gibi bir sabit fikre takılı kalmış durumda
    • Basit bir pazarlama sayfası için mümkün olabilir ama özellikleri bol bir uygulamada bağımlılıklar çoğu zaman zorunlu oluyor
      Örneğin ben yoğun harita işlevleri olan siteler yapıyorum ve mapbox/maplibre/openlayers gibi alternatifsiz kütüphaneleri kullanmak zorundayım
    • 2022'de bu yaklaşımla bir proje yürüttüm ve CVE ya da sürüm geçişleriyle ilgili hiçbir sorun yaşanmadı
      Müşteri de geçiş maliyeti için tek kuruş ödemedi
    • Bileşen render etmek kolay ama framework'lerin asıl özü, modelin reaktif güncellenmesini sağlamaları
      Şu yazıda anlatıldığı gibi model güncellemelerini nasıl ele aldığını merak ediyorum
    • Yaklaşık 20 yıldır JS ile uğraşıyorum; sonunda minimum bağımlılıkla kalıp geri kalanını kendim yapma yaklaşımında karar kıldım
      Hatta büyük kod tabanlarını az sayıda kişiyle sürdürmek daha kolay hâle geldi
      Bugünkü araçlar sayesinde pek çok şeyi elle yapmak eskisine göre çok daha kolay ve bu yaklaşım agentic engineering ile de iyi örtüşüyor
  • Yazı iyi kaleme alınmış; duygusal değil ama sorunu net biçimde anlatıyor
    JS'nin düzgün bir “standart kütüphaneye” sahip olmamasının bu durumun nedenlerinden biri olduğunu düşünüyorum

    • Günümüzde JS standart kütüphanesi epey genişledi; sence hâlâ hangi alanlarda eksik?
    • Ben ise tam tersine sert çıkışlı yazıları (rant) seviyorum. İnsanların sadece duygularını değil, nedenlerini de anlamaya yardımcı oluyorlar
  • Güzel bir yazı ama sorunun kökünde bence gereksiz eklemeler (=bloat) var
    Saint-Exupéry'nin “Mükemmellik, eklenecek bir şey kalmadığında değil, çıkarılacak bir şey kalmadığında elde edilir” sözünü alıntılamak isterim
    Yazılımların çoğu “Bunu nasıl daha zarif yaparız?” diye değil, “Buna nasıl daha kolay bir şey ekleriz?” diye sorularak yazılıyor
    Cevap da her zaman npm i more-stuff oluyor

    • Kurt Vonnegut'un yazı kurallarındaki “Her cümle ya karakteri açığa çıkarmalı ya da eylemi ilerletmeli” ilkesini hatırlatıyor
      Demosthenes ile Cicero karşıtlığındaki gibi, iyi kod çıkarılabilecek hiçbir şey kalmamış koddur
    • Her yazılımda gereksiz parçalar vardır ama özellikle npm paketlerinde ve web uygulamalarında bu çok daha belirgin
      JS hem geçmiş hem de gelecekteki tarayıcı uyumluluğunu düşünmek zorunda ve UI merkezli bir dil olduğu için erişilebilirlik, uluslararasılaştırma, mobil destek gibi nedenlerle şişiyor
  • Çoğu durumda bu bana gizli bir teknik borç sorunu gibi görünüyor
    Derleme hedefini ESx'e yükseltmemek, paketleri ya da uygulamaları güncellememek bunun nedeni
    ES5 zaten 13 yıldır tüm tarayıcılarda destekleniyor (caniuse.com/es5)

    • Pratikte hâlâ eski JS motorlarını desteklemek isteyenler ve sayısız mini paket üretenler var
      İki grup da yaptığını bir özellik olarak görüyor ve çok kullanılan paketleri sürdürüyor
      Bu yüzden değişmesi zor. Topluluk zaman zaman eleştiriyor ama onların da kendince bir mantığı var
    • ES6 altı uyumluluğu sürdürme takıntısı bana tuhaf geliyor
      Babel ile eski sürümlere transpile edince kod şişiyor ve yavaşlıyor; üstelik eski tarayıcılarda CSS ya da JS özellik sınırları yüzünden yine çalışmıyor
      Hatta polyfill'lerin sorun çıkardığı da oldu (BigInt'i işleyemeyen üs operatörü polyfill'i gibi)
    • Sadece eski tarayıcılar değil, tuhaf tarayıcılar da desteklenmek zorunda
      Konsollar, TV'ler, eski Android cihazlar, iPod touch, Facebook'un gömülü tarayıcısı gibi pek çok ortam var
      Bu yüzden tek bir dış modül kullanıp geri kalanını transpiler ayarlarıyla çözüyorum
    • Web'de “hemen dağıt, sonra düzeltiriz” kültürü güçlü olduğu için eskimiş bağımlılıklar uzun süre kalıyor
    • Angular'ın tasarım kararlarında olduğu gibi, geçmişteki yapılar bugünün verimsizliklerine yol açabiliyor
      Eskiden asenkron takibi için setTimeout gibi şeyler override ediliyordu ama artık signals ile çok daha basit şekilde çözülebiliyor
  • Bazı paket yazarlarının indirme sayılarını artırmak için bağımlılık ağacını yapay biçimde parçaladığını düşünüyorum
    7 satırlık paketlerin var olması saçma. lockfile metaverisi kodun kendisinden büyük
    Eskiden create-react-app bağımlılıklarının %5'i tek bir yazarın mini paketleriydi
    has-symbols, is-string, ljharb gibi örnekler var

    • Bunun sadece bir ego meselesi mi olduğunu, yoksa gerçekten bir getirisi olup olmadığını merak ediyorum
      Mesela Anthropic, npm indirme sayısı yüksek açık kaynak bakımcılarına ücretsiz Claude veriyor
    • immich.app/cursed-knowledge yazısındaki gibi, “geriye dönük uyumluluk” bahanesiyle 50 paket ekleyenler de var
    • Güvenlik açısından da ciddi bir mesele. Bu tür mikro paketlerin her biri bir saldırı yüzeyi oluşturuyor
      İndirme sayısı yarışı riski büyütüyor
    • Eskiden birinin bir organizasyona sızıp kendi paketini bağımlılıklara ekleterek özgeçmişine yazacağı yıldız sayılarını artırdığı bir vaka da olmuştu
    • İşin kültürel bir yönü de var. JS topluluğunda 7 satırlık kodu doğrudan kopyalayıp yapıştırmak “tekerleği yeniden icat etmek” diye eleştiriliyor
      Ama başka kültürlerde bu tam tersine iyi bir şey sayılabiliyor
  • JS ekosistemini eleştirmeden önce 30 years of br tags yazısını okumakta fayda var
    JS'nin ve araçlarının evrim sürecini anlamaya yardımcı oluyor
    Sadece “Sorun JS geliştiricileri” demek mühendislik düşüncesinin eksikliğini gösterir

    • Kötü gerçekliği anlamaya çalışmak iyi ama aşırı kabullenme yenilgiciliğe dönüşür
      Her zaman daha iyi teorileri ve pratikleri düşünmeliyiz
      Yazılım dünyası çok hızlı değiştiği için, bazen kendi “sahte cenazemizi” yapıp eski alışkanlıkları terk etmemiz gerekir
    • Bu yazı bana geliştiricileri suçlamaktan çok, mevcut durumu makul biçimde eleştiren bir metin gibi geldi
  • 9 yıllık bir Node.js kod tabanını yönetiyorum; sadece 8 bağımlılığı var ve bunların hiçbirinin alt bağımlılığı yok
    Önce Node'un yerleşik özelliklerini kullanıyor, sadece gereken parçaları kendim yazıyorum
    Eskisine göre çok daha istikrarlı ve çok daha az stresli
    Deno'nun standart kütüphanesi de harika; runtime'ın varsayılan özellikleriyle birleşince birkaç paketle rahatça uygulama yapılabiliyor
    JS, dikkatli yaklaşıldığında oldukça iyi bir dil

  • is-string gibi paketlerin cross-realm güvenliği iddiasını anlıyorum ama pratikte böyle durumlar nadir
    npm'in yayınlamayı fazla kolaylaştırmasıyla “modülü böl, ayrı paket olarak yayımla” felsefesi gereğinden fazla büyüdü
    Tüketiciler bağımlılık ağacını denetlemeden doğrudan kurulum yaptığı için, isteğe bağlı maliyet varsayılan maliyete dönüşüyor
    ponyfill sorunu otomasyonla çözülebilir
    Örneğin Node LTS sürümlerinde zaten desteklenen özellikleri otomatik tespit edip kaldıran Renovate tarzı bir bot faydalı olabilir

  • Şirket içi PWA için tek bir ilkemiz var:
    Chrome'un en güncel sürümüne yükseltin. Hâlâ sorun varsa o zaman bakarız”

    • İç kullanım için bu doğru yaklaşım. Şirket desteklenen tarayıcıyı belirlediğinde yönetim kolaylaşıyor
      Safari'nin daha az bellek kullanmasını anlıyorum ama politika olarak tekilleştirmek daha verimli
    • Her şeyi basit tutmak sonunda en büyük faydayı sağlıyor
  • “ES3'e (IE6/7 seviyesi) kadar destek vermeliyiz” sözü gerçekten anlaşılmaz geliyor
    Güvenlik açısından banka sitelerinin bile böyle antika tarayıcıları engellemesi gerekir

    • Böyle ekipler çoğunlukla 2015 civarında kurdukları build araçlarını hâlâ değiştirmemiş oluyor
      Webpack, Babel, polyfill yığınını yükseltmek büyük iş olduğu için olduğu gibi bırakıyorlar
      “Bozulmadıysa dokunma” kültürü hâkim
    • Gerçekten de böyle eski sürüm desteğini savunan belirli bir kişi var ve pek çok düşük seviye paketi o sürdürüyor
    • Bu arada Deutsche Bahn'ın hâlâ Windows 3.1 kullandığına dair bir şeyler de duymuştum