---
title: 'Paketleyici Kavramı'
source: 'https://academia.sh/tr/kurslar/javascript-ekosistemi/paketleyici-kavrami'
course: 'Modüller, Araçlar ve Ekosistem'
language: tr
updated: '2026-08-17T18:09:45+00:00'
license: 'CC BY-SA 4.0'
---

# Paketleyici Kavramı

Modül çizgesinden tek çıktı üretme gerekçesi, çalışan bir paketleyicinin üç adımı, çıktının yapısı ve ağaç sarsmanın yan etkilerle sınırlanması.

Modül sistemleri ve paket yönetimi konuları, kodun kaynak dizininde nasıl düzenlendiğini
ve bağımlılıkların nasıl bulunduğunu kurdu. Kaynak düzeni, hedef ortamın istediği düzenle
aynı olmak zorunda değildir.

**Paketleyici (bundler)**, modül çizgesini girdi alıp hedef ortamda çalışan bir veya
birkaç dosya üreten araç sınıfıdır. Bu ders, aracın ne yaptığını anlatmak yerine küçük bir
gerçekleştirimini kurar; ondan sonra gerçek araçların bu iskelete eklediği şeyler
anlaşılabilir hâle gelir.

## Neden Tek Çıktı

Kaynak düzeni yüzlerce küçük dosyadan oluşur. Bu düzenin hedef ortamda doğrudan
kullanılması üç sorun çıkarır.

**Dosya başına maliyet.** Ağ üzerinden yüklenen her dosya ayrı bir istektir. İsteklerin
gecikmesi, taşınan baytların süresini aşabilir. İnternet Nasıl Çalışır kursunda tanıtılan
istek başına gecikme, çok sayıda küçük dosyada baskın maliyet hâline gelir.

**Çözümleme farkı.** Çıplak belirteçler dosya sistemindeki bir arama kuralıyla çözülür.
Bu kural her ortamda bulunmaz; tarayıcı, `bicim-yardimcisi` adını kendiliğinden bir dosyaya
çeviremez. Paketleyici bu adları çözülmüş hâlleriyle değiştirir.

**Dil ve biçim farkı.** Kaynak, hedef ortamın anlamadığı bir sözdizim veya iki farklı modül
sistemi karışımı içerebilir. Çıktı tek bir biçimde üretilir.

Bunların hiçbiri her projede geçerli değildir. Yalnızca çalışma zamanında çalışan, ağ
üzerinden dağıtılmayan bir kütüphane paketlenmeden kullanılabilir. Paketleme bir zorunluluk
değil, belirli sorunların çözümüdür.

## Üç Adım

Bir paketleyicinin çekirdeği üç adımdır: giriş noktasından başlayarak çizgeyi çıkarmak,
her modülü bir fonksiyona sarmak, ve modülleri birbirine bağlayan küçük bir çalışma
zamanıyla birlikte yazmak.

Ölçüm kütüphanesinin çağrı tabanlı modüllerle yazılmış hâli girdi olsun:

```javascript
// dosya: kaynak/bolumleme.js
const SOZCUK_AYIRACI = /[^\p{L}\p{N}]+/u;

exports.sozcuklereBol = function (metin) {
  return metin.split(SOZCUK_AYIRACI).filter((s) => s.length > 0);
};
```

```javascript
// dosya: kaynak/istatistik.js
exports.ortalamaUzunluk = function (sozcukler) {
  if (sozcukler.length === 0) return 0;
  return sozcukler.reduce((t, s) => t + s.length, 0) / sozcukler.length;
};

exports.enUzunSozcuk = function (sozcukler) {
  return sozcukler.reduce((en, s) => (s.length > en.length ? s : en), '');
};
```

```javascript
// dosya: kaynak/index.js
const { sozcuklereBol } = require('./bolumleme.js');
const { enUzunSozcuk, ortalamaUzunluk } = require('./istatistik.js');

exports.olc = function (metin) {
  const sozcukler = sozcuklereBol(metin);
  return {
    sozcukSayisi: sozcukler.length,
    ortalamaUzunluk: ortalamaUzunluk(sozcukler),
    enUzun: enUzunSozcuk(sozcukler),
  };
};
```

```javascript
// dosya: kaynak/giris.js
const { olc } = require('./index.js');

console.log(olc('Modul kendi kapsamini tasir. Betik genel kapsamda calisir.'));
```

Paketleyici, bu dört dosyayı tek bir çıktıya çevirir:

```javascript
// dosya: paketle.mjs
import { readFile, writeFile } from 'node:fs/promises';
import { dirname, join } from 'node:path';

const ISTEK = /require\(['"]([^'"]+)['"]\)/g;

async function grafCikar(giris) {
  const moduller = new Map();
  const kuyruk = [giris];
  while (kuyruk.length > 0) {
    const yol = kuyruk.shift();
    if (moduller.has(yol)) continue;
    const kaynak = await readFile(yol, 'utf8');
    const harita = {};
    for (const [, istek] of kaynak.matchAll(ISTEK)) {
      const cozulen = join(dirname(yol), istek);
      harita[istek] = cozulen;
      kuyruk.push(cozulen);
    }
    moduller.set(yol, { kaynak, harita });
  }
  return moduller;
}

function uret(moduller, giris) {
  const kayit = [...moduller]
    .map(([yol, m]) => `${JSON.stringify(yol)}: [function (require, module, exports) {\n${m.kaynak}}, ${JSON.stringify(m.harita)}]`)
    .join(',\n');
  return `(function (kayit, giris) {
  const onbellek = {};
  function calistir(yol) {
    if (onbellek[yol]) return onbellek[yol].exports;
    const [fabrika, harita] = kayit[yol];
    const modul = { exports: {} };
    onbellek[yol] = modul;
    fabrika((istek) => calistir(harita[istek]), modul, modul.exports);
    return modul.exports;
  }
  calistir(giris);
})({\n${kayit}\n}, ${JSON.stringify(giris)});
`;
}

const giris = 'kaynak/giris.js';
const moduller = await grafCikar(giris);
const cikti = uret(moduller, giris);
await writeFile('paket.js', cikti);
console.log('modül sayısı:', moduller.size);
console.log('çizge:', [...moduller.keys()].join(', '));
console.log('çıktı boyutu:', cikti.length, 'bayt');
```

```
$ node paketle.mjs
modül sayısı: 4
çizge: kaynak/giris.js, kaynak/index.js, kaynak/bolumleme.js, kaynak/istatistik.js
çıktı boyutu: 1781 bayt
```

```
$ node paket.js
{ sozcukSayisi: 8, ortalamaUzunluk: 6.125, enUzun: 'kapsamini' }
```

Dört dosya tek dosyaya indi ve çıktı, kaynağın verdiği sonucun aynısını üretti.

## Çıktının Yapısı

Üretilen dosyanın başı, çalışma zamanının tamamını gösterir:

```javascript
(function (kayit, giris) {
  const onbellek = {};
  function calistir(yol) {
    if (onbellek[yol]) return onbellek[yol].exports;
    const [fabrika, harita] = kayit[yol];
    const modul = { exports: {} };
    onbellek[yol] = modul;
    fabrika((istek) => calistir(harita[istek]), modul, modul.exports);
    return modul.exports;
  }
  calistir(giris);
})({
"kaynak/giris.js": [function (require, module, exports) {
// dosya: kaynak/giris.js
```

Yapı, modül sistemleri konusunda anlatılanların birebir karşılığıdır. Her modül bir
fonksiyona sarılmıştır — modül sarmalayıcısının çıktıya yazılmış hâli. `onbellek` nesnesi
tek değerlendirme güvencesini sağlar. `harita` nesnesi, kaynaktaki belirteçleri çıktıdaki
anahtarlara çevirir; çözümleme derleme anında yapılmış, çalışma anına bırakılmamıştır.

Örneğin sınırları da açıktır ve gerçek araçlarla arasındaki farkı verir. Belirteçleri
düzenli ifadeyle bulmak yeterli değildir: dizgi içinde geçen bir `require` yazımı da
eşleşir. Gerçek araçlar kaynağı ayrıştırıp soyut sözdizim ağacı üzerinden çalışır —
Bilgisayarlar Nasıl Çalışır kursundaki derleme aşamaları dersinde tanıtılan yapı budur.
Ayrıca burada uzantı tamamlama, dizin girişleri ve çıplak ad araması yoktur; hepsi gerçek
bir çözümleyicinin işidir.

## Kapsam Birleştirme

Her modülün ayrı bir fonksiyona sarılması bir maliyet taşır: her modül için bir fonksiyon
nesnesi, bir kapanış ve bir çağrı. Modül sayısı arttıkça bu maliyet ölçülebilir hâle gelir.

**Kapsam birleştirme (scope hoisting)**, birbirine bağlı modülleri ayrı fonksiyonlara
sarmak yerine tek bir kapsamda birleştiren dönüşümdür. Adlar çakışmaması için yeniden
adlandırılır; sonuç, ara katman olmadan çalışan tek bir gövdedir.

Dönüşüm ancak modüller arası ilişkiler derleme anında biliniyorsa uygulanabilir. Çağrı
tabanlı sistemde `require` çağrısı çalışma anında hesaplanabildiği için bu bilgi eksiktir;
standart modül sözdiziminde ise tamdır. Statik yapının ikinci somut kazancı budur.

## Ağaç Sarsmanın Sınırı

Kullanılmayan kodun çıktıdan düşürülmesi, örnek paketleyicide hiç yapılmıyor. Etkisi
ölçülebilir: istatistik modülüne, hiçbir yerden çağrılmayan bir işlev eklendiğinde

```javascript
// kaynak/istatistik.js dosyasının sonuna eklenir
// Hiçbir yerden çağrılmayan, ama modülde duran bir dışa aktarım.
exports.harfDagilimi = function (sozcukler) {
  const sayac = new Map();
  for (const sozcuk of sozcukler) {
    for (const harf of sozcuk.toLowerCase()) {
      sayac.set(harf, (sayac.get(harf) ?? 0) + 1);
    }
  }
  return [...sayac.entries()].sort((a, b) => b[1] - a[1]);
};
```

çıktı büyür, davranış değişmez:

```
$ node paketle.mjs
modül sayısı: 4
çizge: kaynak/giris.js, kaynak/index.js, kaynak/bolumleme.js, kaynak/istatistik.js
çıktı boyutu: 2127 bayt
```

```
$ node paket.js
{ sozcukSayisi: 8, ortalamaUzunluk: 6.125, enUzun: 'kapsamini' }
```

Üç yüz kırk altı bayt, hiç çalışmayan kod için ödendi. Gerçek araçlar bu işlevi düşürebilir
— ama yalnızca üç koşul sağlandığında:

**Kullanım görülebilmeli.** Dışa aktarımın hangi adla ve nereden kullanıldığı statik olarak
izlenebilmelidir. Ad hesaplanarak erişiliyorsa izlenemez.

**Yan etki olmamalı.** Modülün en üst düzeyinde, dışa aktarımlardan bağımsız bir iş
yapılıyorsa — bir kayda yazma, bir yerleşik nesneyi değiştirme — modülün tümü düşürülemez.
Araç, yan etkisi olmadığı bildirilmemiş modüllerde temkinli davranır; bu yüzden paketler
bildiriminde yan etki bilgisini işaretler.

**Erişim doğrudan olmalı.** Ad alanı nesnesinin tamamı bir değere bağlanıp dolaştırılıyorsa
hangi adların kullanıldığı bilinemez.

Bu koşullar, kütüphane yazarına somut bir sorumluluk yükler: en üst düzeyde iş yapmamak,
adları doğrudan dışa aktarmak ve yan etki durumunu bildirimde doğru işaretlemek.

## Dış Bırakılan Bağımlılıklar

Her bağımlılığın çıktıya katılması gerekmez. Çalışma zamanının kendi sağladığı modüller ya
da hedef ortamda zaten bulunan kütüphaneler **dış bağımlılık (external)** olarak
işaretlenir: paketleyici onları çizgeye almaz, çağrıyı olduğu gibi bırakır.

Ayrım kütüphane ve uygulama arasında da geçerlidir. Bir uygulamanın çıktısı, çalışması için
gereken her şeyi taşımalıdır. Bir kütüphanenin çıktısı ise bağımlılıklarını içine
gömmemelidir; gömerse tüketici aynı paketin iki kopyasını taşır ve bağımlılık ağacı
dersinde anlatılan yinelenen sürüm sorunları ortaya çıkar.

## Özet

- Paketleyici, modül çizgesini girdi alıp hedef ortamda çalışan çıktı üretir; gerekçesi
  dosya başına ağ maliyeti, çözümleme farkı ve biçim farkıdır.
- Çekirdek üç adımdır: çizgeyi çıkarmak, her modülü bir fonksiyona sarmak, modülleri
  bağlayan küçük bir çalışma zamanı yazmak.
- Çıktıdaki önbellek tek değerlendirme güvencesini, belirteç haritası ise derleme anında
  yapılmış çözümlemeyi taşır.
- Kapsam birleştirme, modül başına düşen sarmalayıcı maliyetini kaldırır ve yalnızca
  ilişkiler derleme anında bilindiğinde uygulanabilir.
- Ağaç sarsma üç koşula bağlıdır: kullanımın izlenebilmesi, yan etkisizlik ve doğrudan
  erişim. Yan etki bilgisi bildirimde işaretlenir.

## Sonraki Adım

Paketleyici modülleri birleştirdi, ama kaynağın yazıldığı sözdizimin hedef ortamda
tanınacağını varsaydı. Bu varsayım her zaman doğru değildir: hedef, kaynağın kullandığı
yazımı ayrıştıramayabilir veya çağırdığı yeteneği sağlamıyor olabilir. Sonraki ders,
kaynağın hedefe uyarlanmasını ve bu uyarlamanın nerede durduğunu ele alır.
