esbuild'i Bağımsız Araç Olarak Kullanmak Ne Zaman Mantıklı?
esbuild'i Vite veya Rollup plugin'i olarak değil, doğrudan CLI veya JavaScript API'siyle çalıştırmak ne zaman mantıklı? Kütüphane build script'leri, özel pipeline aşamaları ve yan derleme görevleri için senaryo bazlı karar rehberi.
esbuild, JavaScript ve TypeScript dosyalarını olağandışı hızda derleyen bir bundler ve transpiler. Çoğu geliştirici bunu Vite'ın içinde fark etmeden kullanır; Vite geliştirme modunda esbuild'i transpiler olarak çalıştırır, ancak tüm plugin sistemi ve yapılandırma Vite üzerinden yürür. esbuild'i bu sarmalayıcı katmanlar olmadan, doğrudan CLI'dan ya da Node.js API'sinden çağırmak farklı bir kullanım biçimidir. Buna bağımsız kullanım (standalone use) demek yerinde olur.
Her proje Vite veya Rollup'ın tam yapılandırma ağırlığını taşıyamaz ya da taşıması gerekmez. Bir araç paketi, bir CLI uygulaması, bir Node.js kütüphanesi veya özel bir derleme pipeline'ı kuruyorsanız, bir framework'ün üstüne başka bir framework bindirmek yerine doğrudan esbuild'i çağırmak hem daha hafif hem daha öngörülebilir sonuçlar üretir. Bu kullanım biçimi nişel görünse de Node.js ekosistemindeki pek çok popüler araç esbuild'i tam da bu şekilde, bir build aracının içi değil, temel derleme motoru olarak kullanır.
Ne zaman bağımsız gitmek kazandırır, ne zaman geri teper? Karar sezgisel görünür, ama pratikte küçük detaylar birikir. Senaryo bazında bakmak en güvenilir yöntemdir.
esbuild'in Bağımsız Çalışma Biçimi
esbuild iki ana giriş noktası sunar: komut satırı arayüzü (CLI) ve JavaScript API'si. CLI tek bir komutla çalışır; esbuild src/index.ts --bundle --outfile=dist/index.js gibi bir ifade dosyayı alır, bağımlılıklarını çeker, çıktıyı üretir. Go ile yazılmış olduğu için başlatma süresi son derece kısadır; soğuk başlatma dahil tipik bir build birkaç yüz milisaniyeyi geçmez.
JavaScript API ise Node.js'ten çağrılır. esbuild.build() fonksiyonu yapılandırma nesnesini alır ve promise döner. Bu API ile build adımlarını programatik olarak yönetebilir, çıktı dosyalarını bellekte tutabilir, birden fazla entry point'i paralel işleyebilirsiniz. Vite veya Rollup'u ayağa kaldırmadan, yalnızca esbuild bağımlılığıyla çıktı üretmek mümkün olur.
İkisi arasındaki sınır şu noktada netleşir: koşullu mantık veya programatik adım yönetimi gerektiğinde CLI yetersiz kalır, API devreye girer.
Node.js Kütüphaneleri için Build Script
Kütüphane veya araç paketi geliştirirken yaygın bir gereksinim: CJS ve ESM formatlarında ayrı çıktı üretmek, TypeScript kaynaklardan başlamak, ama geliştirme sunucusu veya HMR gibi şeylere hiç ihtiyaç duymamak. Vite bu iş için fazla büyüktür; Rollup güçlü ama yapılandırma yükü küçük projeler için ağır gelebilir.
Birkaç satırlık bir build.js dosyası çoğu zaman yeterlidir:
import * as esbuild from 'esbuild';
await esbuild.build({
entryPoints: ['src/index.ts'],
bundle: true,
format: 'esm',
outfile: 'dist/index.esm.js',
platform: 'node',
external: ['fs', 'path'],
});
await esbuild.build({
entryPoints: ['src/index.ts'],
bundle: true,
format: 'cjs',
outfile: 'dist/index.cjs.js',
platform: 'node',
external: ['fs', 'path'],
});
Script okunabilirdir ve bağımlılık sayısı birdir. Projenin package.json dosyasındaki build komutu bu dosyayı çalıştırır; CI pipeline'ında da aynı komut işe yarar. Karmaşıklık yalnızca gerçek ihtiyaçla büyür; her yeni özellik için yapılandırmayı şişirmek zorunda kalmazsınız.
CLI Yeterli mi, JavaScript API mi?
CLI tek adımlı veya az adımlı iş için uygundur. Bir TypeScript dosyasını tarayıcı için derlemek, bir CSS dosyasını küçültmek ya da bir şeyi hızlıca denemek gibi durumlarda birkaç parametre yeterlidir.
Koşullu mantık gerektiğinde tablo değişir. "Production build'inde kaynak haritaları dahil et, test build'inde çıkar" veya "her entry point için ayrı dışa aktarım listesi uygula" gibi kurallar parametre sıralamasıyla ifade edilemez. Bu mantığı shell script'e yazmak hem kırılgan hem okunaksız hale getirir. JavaScript API'sine geçmek bu eşiği aşmanın doğal yoludur.
Bir kural konabilir. Build adımı tek bir esbuild komutuyla tam olarak ifade ediliyorsa CLI kullanın. İki veya daha fazla adım, koşul ya da format varsa JavaScript API'si yazın. Ortada kalan durumlar genellikle API tarafına düşer; çünkü "şimdilik basit" senaryolar hızla büyür.
Ön İşleme ve Özel Pipeline Aşamaları
esbuild'in en az konuşulan kullanım biçimlerinden biri: daha büyük bir pipeline içinde ön işleyici (preprocessor) olarak konumlanmaktır. Tüm build sürecini esbuild'e vermek yerine belirli bir dönüşüm adımını ona yaptırmak, sonra başka bir aracın devralmasını sağlamak demektir.
TypeScript'i JavaScript'e indirgemek, ardından başka bir araçla işlemek bu kategoriye girer. esbuild --bundle seçeneği olmadan da çalışır; tip ek açıklamalarını (type annotation) kaldırmak için kullanılabilir. Gerçek anlamda tip denetimi yapmaz, sadece sözdizimsel olarak kaldırır. Bu işlemi Babel'e kıyasla belirgin biçimde daha hızlı tamamlar.
Worker dosyalarını veya service worker'ları ayrı bundle'lar olarak üretmek başka bir örnek. Ana Vite yapılandırmasına dahil etmek yerine bu dosyaları ayrı bir esbuild çağrısıyla derlemek ve çıktıyı belirli bir dizine yazmak, sorumlulukları net çizgilerle ayırır. Ana pipeline etkilenmez; worker bundle'ları bağımsız sürüm döngüsüne girer.
Monorepo yapılarında da bu kullanım yaygınlaşır. Paylaşılan bir util paketi, her downstream tüketici tarafından ayrıca derlenmek yerine bir kez esbuild ile derlenir ve çıktı çalışma alanına yazılır. Downstream paketler saf JavaScript tüketir; esbuild kurulumuna veya TypeScript yapılandırmasına ihtiyaç duymaz.
Mevcut Framework'ün Yanında Çalışmak
Bağımsız kullanım Vite veya Rollup'un tamamen yerine geçmek anlamına gelmez. Çoğu zaman ikisi birlikte var olur; Vite ana uygulamayı yönetirken esbuild farklı bir sorumluluk üstlenir.
Somut bir senaryo: bir web uygulamasında hem ana uygulama hem bir tarayıcı uzantısı üretmek gerekiyor. Uzantının içeriği farklı entry point'ler, farklı hedefler, farklı output biçimleri istiyor. Vite'ı bu karmaşıklığı kapsayacak biçimde bükmek hem zaman alır hem bakımı zorlaştırır. Uzantı bundle'ları için ayrı bir esbuild script'i yazmak daha az sürtüşme üretir ve iki bağımsız endişeyi birbirinden ayırır.
Benzer mantık bazı varlık işleme görevleri için de geçerlidir. Belirli dosya türlerini dönüştüren küçük bir esbuild script'i, özel bir Vite plugin yazmaktan daha az yapılandırma gerektirebilir. Özellikle bu dönüşüm tekrar tekrar aynı biçimde çalışıyorsa ve herhangi bir plugin hook'una ihtiyaç duymuyorsa bağımsız bir script daha sade kalır.
Bağımsız Kullanımın Getirmediği Şeyler
Hız gerçektir. Ama bazı özellikler esbuild'de yoktur ya da kısıtlıdır; bu yüzden her senaryo için uygun değildir.
TypeScript tür denetimi eksiktir. esbuild type annotation'ları kaldırır, ama tsc --noEmit gibi gerçek bir tip kontrolü yapmaz. Tip hatalarını CI pipeline'ına ayrıca tsc adımı ekleyerek yakalamak gerekir. Bu kısıtlama bağımsız kullanıma özgü değildir; esbuild'i Vite içinde kullananlar için de aynı şekilde geçerlidir.
CSS Modules için yerleşik destek yoktur. Vanilla CSS veya basit CSS dosyalarını işleyebilir, ama .module.css sözdizimini Vite'ın yönettiği biçimde ele almaz. CSS Modules gerektiren projelerde esbuild'i tek başına kullanmak bu altyapıyı çözümsüz bırakır.
Plugin ekosistemi Rollup'a kıyasla dardır. esbuild plugin API'si çalışır ve belgelenmiştir, ama Rollup ekosisteminin uzun yıllık birikimi kadar zengin değildir. Özelleşmiş dönüşümler gerektiren durumlarda bu fark hissedilir.
Kod bölme (code splitting) ESM çıktısı için desteklenir, ama dinamik import() ile tam entegrasyon bazı kenar durumlarda beklenmedik davranışlar üretebilir. Büyük tarayıcı uygulamalarında bu alan dikkat gerektirir ve çıktıyı test etmeden production'a geçmek risklidir.
Senaryo Bazlı Karar
Birkaç soru kararı netleştirir.
Proje bir tarayıcı uygulaması mı, yoksa Node.js kütüphanesi veya araç mı? Kütüphane ve araçlar için bağımsız kullanım çok daha sık uygun düşer. Geliştirme sunucusu, HMR, asset pipeline gibi ihtiyaçlar bu tür projelerde zaten yoktur; esbuild'in sağladıkları tam ihtiyaç listesiyle örtüşür.
Build pipeline'ında koşullu mantık, çoklu format çıktısı veya programatik adım sıralaması var mı? Varsa JavaScript API en doğal seçenektir; CLI bu mantığı taşıyamaz.
Projede CSS Modules veya framework'e özgü dosya türleri (Vue SFC, Svelte bileşenleri, vb.) var mı? Varsa Vite veya Rollup'tan uzaklaşmak net bir kazanım getirmez; aksine bu özellikleri kendiniz eklemeniz gerekir ve sonuç daha karmaşık olur.
Mevcut bir Vite veya Rollup projesinde yalnızca belirli bir dosya grubu için ayrı derleme mi gerekiyor? Bağımsız esbuild çağrısı en az sürtüşmeli çözümdür. Ana yapılandırmayı karmaşıklaştırmadan yan bir görevi kapatır.
Bağımsız esbuild, doğru senaryo için oldukça temiz bir araçtır. Build hızı somuttur; birkaç yüz milisaniye içinde biten derlemeler, büyük giriş noktası koleksiyonlarında bile saniyeler içinde sonuçlanır. Ama bu hız, Vite veya Rollup'un sunduğu olgunlaşmış plugin ekosisteminin, CSS Modules desteğinin veya geliştirme sunucusunun yerini almaz.
Karar asıl olarak projenin ihtiyaç listesine bakar. Kütüphane, araç veya özel pipeline için liste kısa olduğunda esbuild mükemmel uyum sağlar. Liste uzadığında, özellikle tarayıcı uygulamalarında, esbuild'i daha eksiksiz bir araçla birleştirmek ya da entegre biçimde kullanmak daha az manuel çalışma gerektirir.
Karar eşiği düşüktür: tek bir bağımlılık, tek bir dosya, birkaç satır yapılandırma. Çıktı boyutu ve derleme süresi, tartışmadan önce görünür hale gelir.