Bir JavaScript kütüphanesi yazıp yayınlamak ile bir web uygulaması inşa etmek farklı ihtiyaçlar doğurur. Rollup ve esbuild her ikisi de "bundler" olarak tanımlanır; ancak birbirinin doğrudan alternatifi değildir. Her biri farklı bir sorunu merkeze alarak tasarlanmıştır ve hangisini seçeceğiniz büyük ölçüde ne inşa ettiğinize bağlıdır.

Rollup, ES Modules (ESM) standardının olgunlaşmasıyla birlikte şekillendi ve kütüphane üretiminde uzmanlaşmış bir yapıya kavuştu. esbuild ise Go ile yazılmış, hız ve basitlik öncelikli bir araçtır; büyük uygulama kod tabanlarını saniyeler içinde derlemek için optimize edilmiştir. İkisini "hangisi daha iyi?" sorusuyla karşılaştırmak, kaçınılmaz olarak bağlamı kaybettirir.

Yanlış seçim gizli maliyetler üretir. Uygulama build'inde Rollup'ı ham haliyle kullanmaya çalışmak, kendiniz çözmeniz gereken onlarca yapılandırma sorunu anlamına gelebilir. Kütüphane yazarken yalnızca esbuild'e güvenmek ise çıktı biçimlerini ve tree shaking hassasiyetini bizzat yönetmenizi gerektirebilir. Her aracın güçlü yanını anlamak, proje türüne göre doğru seçimi yapmayı kolaylaştırır.

Rollup Kütüphane Build'inde Neden Öne Çıkar?

Bir npm paketi yayınlıyorsanız tüketici ortamını kontrol edemezsiniz. Kütüphanenizi kullanan biri Node.js'te CommonJS (CJS) ile çalışıyor olabilir; bir diğeri modern bir bundler üzerinden ESM tüketiyor olabilir. Rollup, aynı kaynak koddan ESM, CJS ve UMD formatlarında eş zamanlı çıktı üretmeyi doğal bir iş akışı olarak sunar. package.json içindeki main, module ve exports alanlarını doğru doldurmak, Rollup ile çok daha öngörülü bir hal alır.

esbuild de birden fazla format üretebilir; ancak exports koşullarını yönetmek için gereken yapılandırma Rollup'taki kadar açık değildir. Kütüphanenizin tüketildiği ortam sayısı arttıkça bu fark hissedilir hale gelir.

Rollup'ın external seçeneği kütüphane yazarları için kritik bir araçtır. React, Vue veya lodash gibi peer dependency'leri bundle'a dahil etmek yerine dışarıda bırakmak, son paketi önemli ölçüde küçültür ve tüketici tarafında sürüm çakışmalarını önler. esbuild'de external seçeneği mevcuttur; ancak Rollup'ın bu konudaki yapılandırma dili daha zengindir ve regex desenlerinden glob ifadelerine kadar birçok biçimi destekler.

// Rollup yapılandırması örneği
export default {
  input: 'src/index.js',
  external: ['react', 'react-dom'],
  output: [
    { file: 'dist/index.cjs.js', format: 'cjs' },
    { file: 'dist/index.esm.js', format: 'esm' },
  ],
};

Tasarım sistemleri genellikle onlarca küçük paketten oluşur ve her paketin tüketici tarafında mümkün olduğunca küçük bir iz bırakması beklenir. Bu senaryoda Rollup'ın çıktı formatı kontrolü ve tree shaking hassasiyeti, esbuild'in hız avantajından çok daha kritik bir rol oynar.

esbuild'in Hız Avantajı Nereden Geliyor?

Hız farkı somuttur. Go ile yazılmış esbuild, JavaScript'in tek iş parçacıklı çalışma modelinin dışına çıkarak CPU çekirdeklerini paralel kullanır. JavaScript topluluğunun alışkın olduğu araçların büyük bölümü Node.js üzerinde çalıştığından bu fark ölçülebilir boyutlardadır: Rollup ile dakikalar süren bir build, esbuild'de çoğu zaman birkaç saniyeye iner.

Build süresi yalnızca geliştirici konforunu etkilemez. CI/CD pipeline'larında her commit sonrası tetiklenen build sürecinin uzunluğu, doğrudan maliyet ve geri bildirim hızı anlamına gelir. Paralel çalışan pipeline'larda dakikalar yerine saniyelerle ölçülen bir build, geliştirici odağını korur ve döngü hızını artırır.

TypeScript desteği de bu hızın bir parçası. esbuild TypeScript'i type stripping yöntemiyle dönüştürür: tür bilgisini siler, JavaScript üretir, tür denetimi yapmaz. Bu bilinçli bir takas. Tür güvenliği için ayrı bir tsc --noEmit adımı gereklidir; ama build pipeline'ında tip denetimini bağımsız bir aşamaya taşımak zaten iyi bir pratiktir ve esbuild'in TypeScript projelerinde de tam hızında çalışmasını sağlar.

Tree Shaking: Aynı Terimin Arkasında İki Farklı Hassasiyet

İkisi de tree shaking yapar. Ama aynı düzeyde değil.

Rollup, ESM'in statik analizini temelden benimser ve modül grafiğini derleyerek hangi export'un nerede tüketildiğini izler; hiçbir yerde tüketilmeyeni atar. Bu analiz, özellikle yan etki (side effect) içermeyen modüllerde son derece etkilidir. Bir kütüphanenin yalnızca tek bir fonksiyonunu import ettiğinizde, geri kalanın bundle'a girmemesini Rollup büyük ölçüde garanti eder.

esbuild'in tree shaking'i de güçlüdür ve günlük kullanımda yeterli sonuçlar verir. Ancak bir modülün yan etki içerip içermediği belirsiz olduğunda, esbuild daha temkinli davranabilir: modülü atmak yerine dahil edebilir. Kütüphane yazarlarının package.json içinde "sideEffects": false belirtmesi bu belirsizliği giderir; ama kütüphane bunu belirtmemişse araçların davranışı ayrışabilir.

Uygulama build'inde iki araç arasındaki bu tree shaking farkı çoğu proje için pratik açıdan önemsizdir. Kütüphane yazıyorsanız ise doğrudan sizi ilgilendirir: tüketicinizin yalnızca bir bileşen import ettiğini düşünün, bütün paketin bundle'a girmemesi beklenir. Rollup bu beklentiyi karşılamada daha güvenilir bir zemin sunar.

Plugin Ekosistemi ve Yapılandırma Esnekliği

Rollup'ın plugin ekosistemi yıllar içinde olgunlaştı. @rollup/plugin-node-resolve, @rollup/plugin-commonjs, @rollup/plugin-typescript ve onlarca topluluk plugin'i, kütüphane build süreçlerinde karşılaşılan yaygın ihtiyaçları kapsar. Her plugin iyi belgelenmiştir ve kararlı bir API'ye sahiptir; yeni bir gereksinim ortaya çıktığında büyük ihtimalle mevcut bir plugin zaten çözüyordur.

esbuild'in plugin API'si kasıtlı olarak daha sade tutulmuştur. Temel işlemler için bu sadelik avantajdır: daha az yapılandırma, daha az hata yüzeyi. Ancak özel bir CSS pipeline'ı kurmak, belirli dosya uzantılarını özel dönüşümlerden geçirmek ya da build sürecine karmaşık bir adım eklemek istediğinizde esbuild'in plugin sistemi Rollup'unkinden daha sınırlı kalabilir.

Monorepo projelerinde bu fark daha belirgin hale gelebilir. Birden fazla paketin kendi build yapılandırmasına sahip olduğu bir yapıda, plugin uyumluluğu ve yeniden kullanılabilirlik önem kazanır. Rollup'ın olgun ekosistemi, bu tür yapılarda daha az sürtünmeyle ilerlemenizi sağlar.

Uygulama Build'inde Hangi Araç, Ne Zaman?

Uygulama build'inde öncelik genellikle şunlardır: hızlı geliştirme döngüsü, CSS ve statik varlık yönetimi, code splitting ve lazy loading desteği. Bu ihtiyaçların tamamını yalnızca esbuild veya yalnızca Rollup ile karşılamak teknik olarak mümkündür; ancak ikisini de doğrudan kullanmak yerine bunların üzerine inşa edilmiş bir araç kullanmak çok daha pratiktir.

Rollup'ı ham haliyle uygulama build'inde kullanmak, CSS işleme, geliştirme sunucusu ve HMR (hot module replacement) gibi konuları kendiniz çözmeniz anlamına gelir. Bu ihtiyaçlar için mevcut plugin'ler olmakla birlikte, bir araya getirmek zaman alır ve bakım yükü oluşturur.

esbuild doğrudan bir uygulama build'i için daha az yapılandırma gerektirse de CSS Modules, PostCSS zinciri ve gelişmiş code splitting stratejileri için ek çalışma gerektirir. Bu nedenle esbuild'i ham haliyle production uygulama build'inde kullanan projeler genellikle nispeten sade yapılardır.

Kod bölme stratejisi belirlerken, kullandığınız aracın chunk sınırlarını nasıl yönettiğini anlamak değer taşır. Rollup'ın manualChunks seçeneği bu konuda ince ayar yapma imkanı sunarken, esbuild'in splitting desteği belirli senaryolarda daha kısıtlı kalabilir.

İki Aracı Birlikte Kullanmak: Vite Örneği

Vite, bu iki aracın güçlü yanını bir araya getiriyor. Geliştirme modunda esbuild kullanarak milisaniyeler içinde modül sunumu sağlarken, production build için Rollup'a geçiyor. Hız, geliştirme tarafında; hassas tree shaking ve format yönetimi, production tarafında.

Vite'ın plugin sistemi Rollup'ın plugin formatını temel alır; bu nedenle mevcut Rollup plugin'lerinin büyük bölümü Vite ile de uyumlu çalışır. Vite kullanan bir projede Rollup ekosisteminin plugin zenginliğine zaten dolaylı olarak erişiyorsunuzdur.

Vite production build yapılandırmasını optimize etmek istediğinizde, aslında Rollup seçeneklerini yapılandırıyorsunuzdur: manualChunks, output.format, external ve diğer çıktı seçenekleri doğrudan Rollup API'sine aittir; Vite bunları kendi katmanı üzerinden açar.

Bu hibrit yaklaşım, hangi aracın hangi soruyu yanıtladığını netleştirir. Geliştirme hızı esbuild'in alanına girer; production çıktısının kalitesi, format çeşitliliği ve tree shaking hassasiyeti Rollup'ın alanına. İkisini ayrı tutmak mantıkla çelişmez; ikisini aynı pipeline içinde birleştirmek ise öngörülü bir tasarım kararıdır.

esbuild'i Doğrudan Kullanmak Ne Zaman Yeterlidir?

Her projenin bir framework'e ihtiyacı yoktur. Bir CLI aracı yazıyorsanız, sunucu tarafında çalışan bir Node.js servisi derliyorsanız ya da tek entry point'li ve karmaşık CSS pipeline'ı gerektirmeyen bir uygulama inşa ediyorsanız, esbuild doğrudan kullanmak için yeterli ve yeterince basittir.

Yapılandırma miktarı düşüktür. Birkaç satırla TypeScript veya JSX'i derleyebilir, birden fazla entry point tanımlayabilir ve çıktıyı sıkıştırabilirsiniz. Yüzlerce satırlık yapılandırma dosyasına gerek kalmadan işlevsel bir build pipeline'ı elde edersiniz.

// esbuild ile minimal yapılandırma
require('esbuild').build({
  entryPoints: ['src/index.ts'],
  bundle: true,
  minify: true,
  platform: 'node',
  outfile: 'dist/index.js',
}).catch(() => process.exit(1));

Kısıtlar belirli senaryolarda görünür olur. CSS Modules kullanıyorsanız, SVG'leri bileşen olarak import ediyorsanız veya gelişmiş code splitting stratejileri kuruyorsanız, esbuild'i bu işlemler için hazır hale getirmek ek çalışma gerektirir. Ham esbuild yerine üzerine inşa edilmiş bir araç kullanmak, bu senaryolarda daha az sürtünme anlamına gelir.

Seçimi Netleştiren Sorular

Ne inşa ediyorsunuz? npm'e yayınlanacak bir kütüphane veya bileşen paketi ise Rollup daha güvenli bir zemin sunar. ESM ve CJS çıktısı, external bağımlılık yönetimi ve tree shaking hassasiyeti bu senaryoda doğrudan değer üretir. Bir uygulama inşa ediyorsanız ve framework seçiminiz Vite ise zaten her iki aracın güçlü yanından yararlanıyorsunuzdur.

Build süresi darboğaz mı? Büyük bir TypeScript kod tabanında geliştirme döngüsü yavaşladıysa esbuild'in doğrudan kullanımı veya esbuild tabanlı bir araç bu sorunu çözebilir. Rollup tek başına hız sorununa yanıt vermek için tasarlanmamıştır.

Plugin ekosisteminden ne bekliyorsunuz? Olgunlaşmış ve topluluk tarafından test edilmiş plugin'lere ihtiyaç duyuyorsanız Rollup ekosistemi daha derin bir seçenek sunar. Özel dönüşümler ve karmaşık pipeline adımları söz konusu olduğunda bu fark hissedilir hale gelir.

Teknik borç perspektifinden bakıldığında, yanlış araçla kurulan bir build pipeline'ı zamanla bakım yükü biriktirir. Her iki aracın da sınırları vardır: Rollup'ın göreceli yavaşlığı büyük uygulama kod tabanlarında hissedilir; esbuild'in kütüphane build senaryolarındaki esneklik eksikliği ek yapılandırma gerektiren özel durumlar yaratabilir. Bu sınırları önceden bilmek sürprizleri azaltır.

Araç seçimi nadiren tek başına bir performans veya kalite sorunu çözer. Frontend performans sürecinde araç büyük tablonun yalnızca bir bileşenidir: hangi bağımlılıkların dahil olduğu, kod bölme stratejisi ve bundle analizinin düzenli yapılıp yapılmadığı, seçilen araçtan bağımsız olarak yanıt verilmesi gereken sorulardır.

Rollup ve esbuild çoğu zaman rekabette değil, iş birliğindedir. Biri kütüphaneyi paketler, diğeri uygulamayı derler; ikisi birden pipeline'ın farklı katmanlarında yer alabilir. Hangisini nerede kullandığınızı anlamak, araçları takip etmekten çok ihtiyaçlarınızı netleştirmekle başlar.