---
title: 'Çalışma Alanları'
source: 'https://academia.sh/tr/kurslar/javascript-ekosistemi/calisma-alanlari'
course: 'Modüller, Araçlar ve Ekosistem'
language: tr
updated: '2026-08-17T18:09:46+00:00'
license: 'CC BY-SA 4.0'
---

# Çalışma Alanları

Birden çok paketin tek depoda tutulması, çalışma alanı bildirimi, yerel paketlerin bağla çözümlenmesi, topolojik derleme sırası ve sürümleme stratejileri.

Önceki derslerde tüm paketler dışarıdan geldi: bildirimde bir aralıkla istendiler, bir
dizine kuruldular, oradan çözümlendiler. Bir ekibin kendi yazdığı paketler için bu döngü
ağırdır — kütüphanede yapılan her düzeltmenin, onu kullanan uygulamada denenebilmesi için
yayımlanması gerekir.

Ölçüm kütüphanesi bu noktaya geldi. Biçimlendirme yardımcısı ayrı bir pakete çıkarıldı,
ölçüm sonucunu sunan bir rapor aracı eklendi. Üçü de aynı ekibin ürünü ve birlikte
değişiyorlar. Bu ders, üçünün tek bir depoda nasıl tutulacağını ele alır.

## Çok Paketli Depo

Birden çok paketi tek bir sürüm denetimi deposunda tutan düzene **çok paketli depo
(monorepo)** denir. Çözdüğü sorunlar somuttur:

**Bölünmüş değişiklik.** Kütüphaneye bir parametre eklemek ve onu kullanan araçları
güncellemek, ayrı depolarda birkaç adımlı bir işlemdir: yayımla, bekle, aralığı güncelle,
kur. Tek depoda bu, tek bir işlemedir (commit).

**Sürüm gecikmesi.** Ayrı depolarda kütüphanenin son hâli ile uygulamanın kullandığı hâl
arasında her zaman bir fark bulunur. Tek depoda bu fark sıfırdır.

**Yinelenen yapılandırma.** Çözümleyici kuralları, biçimlendirme ayarları ve sınama düzeni
tek yerde tutulur.

Bedeli de vardır. Depo büyür; her değişiklikte hangi paketlerin etkilendiğini hesaplamak
gerekir; sınama süresi tüm paketlerin toplamı olmaya eğilimlidir; sürüm ve yayımlama
kararları karmaşıklaşır. Bu maliyetler, paketler birlikte değişmiyorsa ödenmeye değmez.
Ölçüt basittir: paketler aynı değişiklikte birlikte güncelleniyorsa tek depo, bağımsız
gelişiyorsa ayrı depolar uygundur.

## Çalışma Alanı Bildirimi

Kök dizindeki bildirim, hangi alt dizinlerin paket olduğunu söyler ve kendisinin
yayımlanmayacağını işaretler:

```json
{
  "name": "olcum-deposu",
  "private": true,
  "workspaces": ["paketler/*"]
}
```

`private` alanı bir güvenliktir: kök dizin bir kütüphane değildir ve kazayla yayımlanması
istenmez. `workspaces` alanı ise kurulum aracına, listelenen kalıplara uyan her dizini bir
**çalışma alanı (workspace)** olarak ele almasını söyler.

Depodaki üç paket şunlardır:

```json
{ "name": "bicim-yardimcisi", "version": "1.4.0", "type": "module", "main": "index.mjs" }
```

```json
{
  "name": "metin-olcer",
  "version": "0.1.0",
  "type": "module",
  "exports": { ".": "./src/index.mjs" },
  "dependencies": { "bicim-yardimcisi": "^1.4.0" }
}
```

```json
{
  "name": "rapor-araci",
  "version": "0.2.0",
  "type": "module",
  "main": "index.mjs",
  "dependencies": { "metin-olcer": "^0.1.0" }
}
```

Dikkat edilecek nokta, bağımlılıkların yerel olduklarını belirten özel bir yazım
kullanmamasıdır. `metin-olcer` paketi `bicim-yardimcisi` paketini, dışarıdan gelen herhangi
bir paket gibi çıplak adıyla ve bir aralıkla ister. Yerellik, bildirimin değil kurulumun
kararıdır: kurulum aracı, istenen adın depoda bir çalışma alanı olduğunu ve sürümünün
aralığa uyduğunu görürse kayda gitmez.

## Bağların Kurulması

Yerel paket, ağaca kopyalanarak değil, sembolik bağ ile yerleştirilir:

```
$ for b in node_modules/*; do printf '%s -> %s\n' "$b" "$(readlink "$b")"; done
node_modules/bicim-yardimcisi -> ../paketler/bicim
node_modules/metin-olcer -> ../paketler/olcer
node_modules/rapor-araci -> ../paketler/rapor
```

Sembolik bağ kavramı Linux'a Giriş kursundaki bağlantılar dersinde tanımlanmıştı: hedefe
işaret eden, hedefin kendisi olmayan bir girdi. Buradaki sonucu belirleyicidir. Çözümleme
kuralı `node_modules` dizininde adı arar, bulduğu girdinin bağ olup olmadığına bakmaz;
bulunan dizin kaynak ağacın kendisidir. Kaynakta yapılan bir değişiklik, yeniden kurulum
gerektirmeden tüketiciye görünür.

```javascript
// dosya: paketler/bicim/index.mjs
export function ondalik(sayi, basamak = 2) {
  return sayi.toFixed(basamak);
}
```

```javascript
// dosya: paketler/olcer/src/index.mjs — bolumleme ve istatistik modülleri aynı dizindedir
import { ondalik } from 'bicim-yardimcisi';
import { cumlelereBol, sozcuklereBol } from './bolumleme.mjs';
import { enUzunSozcuk, ortalamaUzunluk } from './istatistik.mjs';

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

```javascript
// dosya: paketler/rapor/index.mjs
import { olc } from 'metin-olcer';

export function rapor(metin) {
  const o = olc(metin);
  return `${o.sozcukSayisi} sozcuk / ${o.cumleSayisi} cumle / ort. ${o.ortalamaUzunluk}`;
}
```

```javascript
// dosya: dene.mjs — depo kökünde
import { rapor } from 'rapor-araci';

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

```
$ node dene.mjs
8 sozcuk / 2 cumle / ort. 6.13
```

Üç paket, hiçbiri yayımlanmadan birbirini çıplak adıyla buldu. Bu düzenin sessiz bir
tuzağı vardır: yerelde çalışan içe aktarma, yayımlandıktan sonra çalışmayabilir. Bağ
üzerinden erişilen dizin kaynak ağacın tamamıdır; yayımlanan arşiv ise yalnızca bildirimde
listelenen dosyaları taşır. Dışa aktarım haritası veya dosya listesi eksikse, hata yalnızca
yayımdan sonra görünür. Bu yüzden çok paketli depolarda arşivin içeriğini yayımlamadan
önce denetlemek bir alışkanlık olmalıdır.

## Derleme Sırası

Paketler birbirine bağlı olduğuna göre, üzerlerinde yapılan toplu işlemler — derleme,
sınama, yayımlama — rastgele sırada yürütülemez. `rapor-araci` paketini sınamak,
`metin-olcer` paketinin hazır olmasını gerektirir.

Doğru sıra, bağımlılık çizgesinin topolojik sıralamasıdır. Veri Yapıları kursunda
tanıtılan bu sıralama, burada doğrudan uygulanır:

```javascript
// dosya: sira.mjs — depo kökünde, paketler/ dizinini okur
import { readdir, readFile } from 'node:fs/promises';
import { join } from 'node:path';

const kok = 'paketler';
const paketler = new Map();
for (const dizin of (await readdir(kok)).sort()) {
  const bildirim = JSON.parse(await readFile(join(kok, dizin, 'package.json'), 'utf8'));
  paketler.set(bildirim.name, Object.keys(bildirim.dependencies ?? {}));
}

// Derine arama ile topolojik sıralama: bağımlılıklar önce yayımlanır.
const sonuc = [];
const durum = new Map();
function ziyaret(ad) {
  if (durum.get(ad) === 'bitti') return;
  if (durum.get(ad) === 'sürüyor') throw new Error(`döngü: ${ad}`);
  durum.set(ad, 'sürüyor');
  for (const bagimlilik of paketler.get(ad) ?? []) {
    if (paketler.has(bagimlilik)) ziyaret(bagimlilik);
  }
  durum.set(ad, 'bitti');
  sonuc.push(ad);
}
for (const ad of paketler.keys()) ziyaret(ad);

console.log(sonuc.join(' -> '));
```

```
$ node sira.mjs
bicim-yardimcisi -> metin-olcer -> rapor-araci
```

Betiğin iki ayrıntısı önemlidir. Depoda bulunmayan bağımlılıklar atlanır: dış paketlerin
sırası bizi ilgilendirmez, onlar zaten kuruludur. İkincisi, ziyaret durumu üç değerlidir;
"sürüyor" durumundaki bir düğüme yeniden gelinmesi döngü demektir ve hata verilir. Paketler
arası dairesel bağımlılık, modüller arasındakinin aksine hiçbir biçimde çözülemez.

Aynı çizge ikinci bir soruya da yanıt verir: bir pakette yapılan değişiklikten hangi
paketler etkilenir? Yanıt, çizgenin ters yönde dolaşılmasıyla bulunur ve yalnızca etkilenen
paketlerin sınanmasını sağlar. Büyük depolarda sınama süresini yönetilebilir tutan yöntem
budur.

## Sürümleme Stratejisi

Depodaki paketlerin sürümleri iki biçimde yönetilir.

**Ortak sürüm.** Tüm paketler aynı numarayı taşır ve birlikte yayımlanır. Yayımlama kararı
tektir, izlenmesi kolaydır; karşılığında hiç değişmemiş bir paket de yeni sürüm alır ve
tüketicileri gereksiz yükseltmeye zorlanır.

**Bağımsız sürüm.** Her paket kendi numarasını taşır ve yalnızca değiştiğinde yayımlanır.
Tüketici açısından dürüst olan yaklaşımdır; karşılığında hangi paketin hangi sürümde
olduğunun izlenmesi ve depo içi aralıkların güncel tutulması gerekir.

Seçim, tüketicinin kim olduğuna bağlıdır. Paketler yalnızca depo içinde kullanılıyorsa
ortak sürüm işi kolaylaştırır. Dışarıya yayımlanıyorsa bağımsız sürüm, önceki derste
kurulan sözleşmeye sadık kalan tek seçenektir: sürüm numarası ancak gerçek bir değişikliği
bildirdiğinde anlam taşır.

## Özet

- Çok paketli depo, birlikte değişen paketleri tek işlemede güncellemeyi ve tek
  yapılandırmayı paylaşmayı sağlar; paketler bağımsız gelişiyorsa maliyeti karşılıksız kalır.
- Kök bildirimindeki çalışma alanı listesi hangi dizinlerin paket olduğunu belirtir;
  bağımlılıklar yerel olduklarını belirten özel bir yazım kullanmaz.
- Yerel paketler ağaca sembolik bağla yerleştirilir; kaynakta yapılan değişiklik yeniden
  kurulum gerektirmeden görünür.
- Bağ üzerinden tüm kaynak ağacı erişilebilir olduğu için, yayımlanan arşivde eksik kalan
  dosyalar yalnızca yayımdan sonra fark edilir.
- Paketler üzerindeki toplu işlemler bağımlılık çizgesinin topolojik sırasına göre yürütülür;
  ters yönde dolaşma, bir değişiklikten etkilenen paketleri verir.

## Sonraki Adım

Ağaçtaki paketlerin çoğu doğrudan seçilmedi; başka paketlerin bağımlılığı oldukları için
oradalar. Bu paketler de kod çalıştırır ve kurulum sırasında betik işletebilirler. Sonraki
ders, bu geçişli kütlenin büyüklüğünü ölçer ve bağımlılık seçiminin, kilitlemenin ve
doğrulamanın savunma değeri olan yanlarını ele alır.
