JAVASCRIPT MODÜL SİSTEMİ ESM COMMONJS KARŞILAŞTIRMAK
JavaScript yıllarca modül sistemi olmayan bir dildi. Tüm kodun aynı global scope'ta çalışması büyük projelerde kabusa dönüştü. Node.js 2009'da CommonJS (require/module.exports) ile modül sistemi getirdi; 2015'te ECMAScript 6 standardı ESM (import/export) ile resmi modül syntax'ı tanımlandı. Bugün iki sistem paralel kullanılıyor; geliştiriciler hangisini ne zaman seçeceği konusunda hâlâ kafa karıştırıyor.
Modern JavaScript projeleri çoğunlukla ESM kullanır; tarayıcılar yerli olarak destekler, build tool'lar (Vite, esbuild, webpack) ESM odaklı çalışır. CommonJS Node.js ekosisteminde hâlâ baskın; özellikle eski paketler ve sunucu tarafı için. İki sistemin modül davranışını karşılaştırmak isteyenler için web teknolojileri dokümantasyonu import/export semantiğini ayrıntılı açıklar. Hangi sistemi kullanacağınızı bilmek modern JavaScript için temel.
İki modül sistemi arasındaki fark syntax'tan ibaret olsaydı mesele olmazdı: ESM statik analiz edilir, CommonJS çalışma anında çözülür — ve bu tek fark tree-shaking'den dosya uzantısına, Node.js yapılandırmasından geçiş stratejisine kadar her kararı şekillendirir.
CommonJS (CJS)
Node.js'in geleneksel modül sistemi. 2009'dan beri kullanımda. Senkron yükleme yapar.
// math.js (CommonJS)
function topla(a, b) {
return a + b;
}
module.exports = { topla };
// app.js
const { topla } = require('./math');
console.log(topla(2, 3));Karakteristikleri:
- require: Modül yükleme
- module.exports: Modülden çıkış
- Senkron: require çağrısı modül yüklenene kadar bekler
- Runtime: Modüller çalışma zamanında yüklenir
- Dinamik: require ifadesinin içine değişken yerleştirilebilir
ES Modules (ESM)
ECMAScript 2015 ile gelen resmi standart. Modern JavaScript'in tercih ettiği sistem.
// math.js (ESM)
export function topla(a, b) {
return a + b;
}
// app.js
import { topla } from './math.js';
console.log(topla(2, 3));Karakteristikleri:
- import / export: Modül yükleme ve çıkış
- Asenkron: Modüller paralel yüklenebilir
- Statik: import ifadesi build zamanında çözümlenir
- Tree shaking: Kullanılmayan kod build'den çıkarılır
- Tarayıcı desteği: Modern tarayıcılarda yerli
Syntax farkları
| İşlem | CommonJS | ESM |
|---|---|---|
| Import | const x = require('./x') | import x from './x.js' |
| Named import | const { a } = require('./x') | import { a } from './x.js' |
| Default export | module.exports = obj | export default obj |
| Named export | module.exports.a = a | export const a = ... |
Node.js'te yapılandırma
Node.js varsayılan olarak CommonJS kullanır. ESM kullanmak için iki yöntem:
1. package.json'da type: module
{
"name": "myproject",
"type": "module",
"version": "1.0.0"
}Bu ayarla tüm .js dosyaları ESM olarak yorumlanır. CommonJS dosyaları .cjs uzantısı ile kullanılır.
2. .mjs uzantısı
Karma kullanım için pratik; tek tek dosyalar ESM olur.
Tarayıcı kullanımı
Tarayıcılarda ESM yerli destekleniyor. <script type="module"> attribute'ı gerekli:
<script type="module">
import { greet } from './greet.js';
greet('World');
</script>CommonJS tarayıcıda doğrudan çalışmaz; webpack veya benzeri bundler ile derlenmesi gerekir.

Tree shaking ve performans
ESM'in en büyük avantajlarından biri tree shaking. Statik import yapısı sayesinde build tool'lar kullanılmayan kodları otomatik çıkarır.
// utils.js (ESM)
export const a = () => 'A';
export const b = () => 'B';
export const c = () => 'C';
// app.js
import { a } from './utils.js';
console.log(a());
// Build sonrası: sadece 'a' fonksiyonu bundle'a girer
// 'b' ve 'c' kullanılmadığı için çıkarılırCommonJS'te bu otomatik olmaz; require dynamic olduğu için build tool hangi fonksiyonun kullanıldığını çalışma zamanına kadar bilemez. Bundle boyutu daha büyük olur.
Dynamic import
ESM'de runtime'da modül yükleme için import() fonksiyonu var:
async function loadModule() {
const module = await import('./math.js');
return module.topla(2, 3);
}Code splitting için kritik; sayfa açıldığında değil ihtiyaç olduğunda modül yüklenir. Lazy loading'in temeli.
Ortak senaryolar
CJS modülünü ESM'de kullanma
Node.js bu interop'u otomatik yapar; çoğu durumda çalışır. Bazı paketlerde özel ayar gerekebilir.
// Modern ESM kullanım
import legacyPkg from 'legacy-pkg';
console.log(legacyPkg.utility());ESM modülünü CJS'de kullanma
CJS'te statik require ile ESM modülü yüklenmez; sadece dynamic import çalışır.
async function main() {
const { greet } = await import('modern-pkg');
console.log(greet());
}
main();Hangi sistemi kullanmalı?
Yeni projeler için: ESM
Modern bütünleşme, tree shaking, tarayıcı uyumu nedeniyle yeni projelerin tamamı ESM olmalı.
Eski projeler için: kademeli geçiş
Mevcut CommonJS projesi varsa zorlama gerekmez. Yeni eklenen kod ESM olabilir; eski kod ihtiyaç oldukça migrate edilir.
Library yazarken: dual package
NPM paketi yayınlıyorsanız hem CJS hem ESM versiyon sağlamak en kapsayıcı:
{
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
}
}
}ESM'de __dirname alternatifi
// CommonJS
const path = require('path');
const fullPath = path.join(__dirname, 'file.txt');
// ESM
import { dirname } from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);Sık Karşılaşılan Yanılgılar
- Import path'lerinde uzantı unutmak. ESM'de "./file" yerine "./file.js" yazmak gerek
- Karma kullanım. Tek dosyada hem require hem import; çalışmaz
- Tree shaking için yanlış import. "import * as" tree shaking'i devre dışı bırakır
- JSON import'u. ESM'de JSON import farklı; assert syntax gerek
- Dual package hazard. Aynı paketin CJS ve ESM versiyonları farklı state tutabilir

Disiplinin Yerleşmesi
Modül sistemleri modern JavaScript ekosisteminin temelidir. Bilgiyi sıralı yol haritasıyla edinmek için uygulamalı JavaScript eğitimi ESM, CommonJS ve modern modül yönetimi konularını birlikte aktarır.
Toparlarsak
JavaScript'te ESM ve CommonJS iki ana modül sistemi. CommonJS Node.js'in eski standartı; senkron, dinamik, runtime tabanlı. ESM modern standart; asenkron, statik, tree shaking destekli. Yeni projeler ESM tercih etmeli; mevcut projeler kademeli geçiş yapmalı. NPM paketleri yayınlanırken dual package (her ikisini destekleme) en kapsayıcı yaklaşım. Modern build tool'lar ESM odaklı çalışır; geçiş JavaScript ekosisteminin geleceği.



