---
title: 'Derleme ve Yayın'
source: 'https://academia.sh/tr/kurslar/react-native/derleme-ve-yayin'
course: 'React Native'
language: tr
updated: '2026-10-21T05:02:54+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Hızlı yenilemenin düğümü güncellenen ya da korunan bıraktığını ve durumun yaşadığını ölçer'
    - 'Tam yeniden yüklemede eski kökün tamamının sökülen, yenisinin kurulan olduğunu gösterir'
    - 'Kök tipi değişince hızlı yenilemenin de durumu yitirdiğini ve derleme, imzalama, sürüm kanallarının ağaçta görünmediğini açıklar'
    - 'Yirmi dersin akıbetini kapanış tablosunda toplar ve dağılımını sayar'
---

# Derleme ve Yayın

Geliştirmede hızlı yenileme düğümü yerinde güncellerken tam yeniden yükleme kökü söker. Ders bu farkı ölçer ve yirmi dersin akıbetlerini tek tabloda toplar.

Önceki ders, yerel modülün ağaçta tek düğüm olduğunu ölçtü. Yerel kod yazılınca uygulama yalnız JavaScript olmaktan çıkar: platform tarafı derlenir, imzalanır ve mağazaya gider. Bu ders kursun kapanışıdır. Önce geliştirme sırasında bir bileşen dosyası değişince ağaçta ne olduğuna bakar, sonra yayın hattını kısaca ayırır, en sonda yirmi dersin akıbetini tek tabloda toplar.

Kursun sorusu: **bu güncelleme görünüm ağacındaki düğüme ne yapıyor?** Yanıtlar korunan, güncellenen, kurulan ve sökülen; korunan dışındakilerin toplamı komuttur. Kural çekirdek dosyadadır.

```javascript
// fate.mjs — bir guncellemenin gorunum agacindaki her dugume ne yaptigini siniflandirir
export const FATES = ["korunan", "guncellenen", "kurulan", "sokulen"];

export function el(type, props = {}, children = [], key = null) {
  return { type, props, children, key };
}

function segment(node) {
  return node.key === null ? node.type : `${node.type}[${node.key}]`;
}

function identity(node, index) {
  return node.key === null ? `#${index}` : `key:${node.key}`;
}

function sameProps(a, b) {
  const names = [...new Set([...Object.keys(a), ...Object.keys(b)])].sort();
  return names.every((n) => JSON.stringify(a[n]) === JSON.stringify(b[n]));
}

function whole(node, path, fate, ops) {
  const here = `${path}/${segment(node)}`;
  ops.push({ fate, path: here });
  node.children.forEach((child) => whole(child, here, fate, ops));
}

export function reconcile(prev, next, path = "", ops = []) {
  if (prev === null) {
    whole(next, path, "kurulan", ops);
    return ops;
  }
  if (next === null) {
    whole(prev, path, "sokulen", ops);
    return ops;
  }
  if (prev.type !== next.type || prev.key !== next.key) {
    whole(prev, path, "sokulen", ops);
    whole(next, path, "kurulan", ops);
    return ops;
  }
  const here = `${path}/${segment(next)}`;
  ops.push({ fate: sameProps(prev.props, next.props) ? "korunan" : "guncellenen", path: here });
  const before = new Map(prev.children.map((child, i) => [identity(child, i), child]));
  const matched = new Set();
  next.children.forEach((child, i) => {
    const id = identity(child, i);
    matched.add(id);
    reconcile(before.has(id) ? before.get(id) : null, child, here, ops);
  });
  prev.children.forEach((child, i) => {
    if (!matched.has(identity(child, i))) reconcile(child, null, here, ops);
  });
  return ops;
}

export function printOps(ops) {
  ops.forEach((op) => console.log(`${op.fate}: ${op.path}`));
}

export function countFates(ops) {
  for (const name of FATES) {
    console.log(`${name}: ${ops.filter((op) => op.fate === name).length}`);
  }
  console.log(`komut: ${ops.filter((op) => op.fate !== "korunan").length}`);
}
```

Geliştirme oturumunun modeli ayrı bir dosyadadır. Ekranın kaynağı `source` nesnesidir: kök düğümün tipi ve başlık metni. `buildTree` kaynaktan ağacı kurar. Sayaç oturumun durumudur ve ağaca `Counter` düğümünün özelliği olarak girer. İki yükleme yolu vardır. `fastRefresh` kaynağı değiştirir ama kök anahtarını korur. `fullReload` kök anahtarını bir artırır ve sayacı sıfırlar.

```javascript
// dev.mjs — gelistirme oturumunun modeli
import { el, reconcile } from "./fate.mjs";

export function buildTree(source, count, rootKey) {
  return el(source.root, {}, [
    el("Header", { title: source.title }),
    el("Counter", { count }),
  ], rootKey);
}

export function openSession(source) {
  return { source, count: 0, rootKey: null, tree: buildTree(source, 0, null) };
}

export function press(session) {
  const count = session.count + 1;
  return { ...session, count, tree: buildTree(session.source, count, session.rootKey) };
}

export function fastRefresh(session, source) {
  const draft = buildTree(source, session.count, session.rootKey);
  const ops = reconcile(session.tree, draft);
  const lost = ops.some((op) => op.fate === "sokulen" && op.path.endsWith("/Counter"));
  const count = lost ? 0 : session.count;
  const tree = lost ? buildTree(source, 0, session.rootKey) : draft;
  return [{ ...session, source, count, tree }, ops];
}

export function fullReload(session, source) {
  const rootKey = (session.rootKey ?? 0) + 1;
  const tree = buildTree(source, 0, rootKey);
  return [{ source, count: 0, rootKey, tree }, reconcile(session.tree, tree)];
}
```

Modelin tek kuralı durumun kimliğe bağlı olmasıdır: sayaç, ancak `Counter` düğümü güncellemeyi aşıp kimliğini koruduysa yaşar. `fastRefresh` bunu `lost` ile sınar. Durumu ayrıca saklamak ya da kopyalamak yerine ağacın karşılaştırma sonucuna bakar.

## İlk Açılış

Oturum ilk açıldığında önceki ağaç yoktur. Her düğüm kurulandır ve sayaç sıfırdır.

```javascript
// main.mjs
import { reconcile, printOps } from "./fate.mjs";
import { openSession } from "./dev.mjs";

const session = openSession({ root: "App", title: "Ana ekran" });
printOps(reconcile(null, session.tree));
console.log(`sayac: ${session.count}`);
```

```text
kurulan: /App
kurulan: /App/Header
kurulan: /App/Counter
sayac: 0
```

## Hızlı Yenileme

Kullanıcı sayaca üç kez basar, sonra geliştirici başlığı değiştirir ve dosyayı kaydeder. Hızlı yenileme yalnız değişen bileşen dosyasını yeniden yükler. Kök tipi ve anahtarı aynı kalır.

```javascript
// main.mjs
import { printOps } from "./fate.mjs";
import { openSession, press, fastRefresh } from "./dev.mjs";

let session = openSession({ root: "App", title: "Ana ekran" });
session = press(press(press(session)));
const [after, ops] = fastRefresh(session, { root: "App", title: "Baslangic" });
printOps(ops);
console.log(`sayac: ${after.count}`);
```

```text
korunan: /App
guncellenen: /App/Header
korunan: /App/Counter
sayac: 3
```

Başlık güncellenen çıktı, kök ve sayaç korunan kaldı. Tek komut gitti ve sayaç üçte durdu: yenileme düğümlerin kimliğine dokunmadı, bu yüzden durum yaşadı. Başlığı hiç değiştirmeyen bir kayıt üç düğümü de korunan bırakırdı. Hızlı yenileme, geliştirmede en sık yaşanan akıbet çiftidir: değişen düğüm güncellenen, geri kalan korunan.

## Tam Yeniden Yükleme

Her değişiklik hızlı yenilemeyle uyuşmaz. Çizim ağacının dışından içe alınan bir dosya, örneğin uygulamanın başlangıç kodu değişirse bütün paket baştan yüklenir; modelde bunun izi kök anahtarının artmasıdır. Yerel bir modül eklemek bunun da ötesine geçer: paketin yanında platform tarafının yeniden derlenmesini gerektirir.

```javascript
// main.mjs
import { countFates } from "./fate.mjs";
import { openSession, press, fullReload } from "./dev.mjs";

let session = openSession({ root: "App", title: "Ana ekran" });
session = press(press(press(session)));
const [after, ops] = fullReload(session, { root: "App", title: "Ana ekran" });
countFates(ops);
console.log(`sayac: ${after.count}`);
```

```text
korunan: 0
guncellenen: 0
kurulan: 3
sokulen: 3
komut: 6
sayac: 0
```

Kaynak değişmediği hâlde sonuç, hızlı yenilemenin tersidir: üç düğüm sökülen, üç düğüm kurulan, korunan yok. Komut sayısı altı, sayaç sıfır. Kök anahtarı değişince karşılaştırma kökün altına inmez: kök yeni bir düğümdür, eskisi yok olur ve altındaki her düğüm onunla birlikte gider.

## Hızlı Yenileme de Kırılabilir

Hızlı yenileme bir ayrıcalık değil, bir koşuldur. Kök tipi değişirse karşılaştırma kökü eşleştiremez. Geliştirici kök bileşenin adını değiştirirse hızlı yenileme de bütün ağacı söker.

```javascript
// main.mjs
import { countFates } from "./fate.mjs";
import { openSession, press, fastRefresh } from "./dev.mjs";

let session = openSession({ root: "App", title: "Ana ekran" });
session = press(press(press(session)));
const [after, ops] = fastRefresh(session, { root: "Shell", title: "Ana ekran" });
countFates(ops);
console.log(`sayac: ${after.count}`);
```

```text
korunan: 0
guncellenen: 0
kurulan: 3
sokulen: 3
komut: 6
sayac: 0
```

Çıktı tam yeniden yüklemeyle aynı, ama yol farklı: burada kök anahtarı değil, kök tipi değişti. İki yol aynı akıbete varır. Durumun yaşayıp yaşamaması hangi komutun kullanıldığına değil, kök düğümün kimliğinin korunup korunmadığına bağlıdır.

## Yayın Hattı

Geliştirmede paket, geliştirme sunucusundan gelir. Yayında paket uygulamanın içine gömülür ve iki platformda iki ayrı yoldan geçer. Her platformda yapı üç adımdır: derleme, imzalama, dağıtım. Derleme, JavaScript paketini ve yerel kodu bir araya getirir. İmzalama, paketin kimin tarafından üretildiğini kanıtlar; iki platformda da kendi anahtar yönetimi vardır. Dağıtım, imzalı paketi bir sürüm kanalına koyar: dahili deneme, sınırlı deneme ya da herkese açık yayın.

```kotlin
// Platform kodu: yayin yapilandirmasi (Android)
buildTypes {
  release {
    isMinifyEnabled = true
    signingConfig = signingConfigs.getByName("release")
  }
}
```

Parça iki ayrımı gösterir. `release` bloğu yayın derlemesinin geliştirme derlemesinden ayrı bir yapılandırma olduğunu, `signingConfig` satırı da imzanın derleme adımının parçası olduğunu anlatır. iOS tarafında aynı iş proje ayarlarında yapılır; model bunu ayırmaz, çünkü ağaç hangi anahtarla imzalandığını görmez.

Bir kanal daha vardır: uzaktan güncelleme. JavaScript paketi mağaza sürümünden bağımsız olarak değiştirilebilir. Sınır şudur: yalnız JavaScript tarafı uzaktan değişir. Yerel modülün yeni bir sürümü, yeni bir izin ya da yeni bir yerel görünüm yeni bir mağaza sürümü ister. Bu yüzden önceki dersteki `NativeMap` düğümü uzaktan güncellemeyle yeniden yazılabilir ama haritanın yerel kodu yazılamaz.

## Yaygın Yanılgılar

İlk yanılgı, hızlı yenilemenin her zaman durumu koruduğudur. Yukarıdaki kök tipi ölçümü bunun tersini gösterdi: kök tipi değişince durum yitirildi. Hızlı yenileme bir güvence değil, ağacın karşılaştırma sonucuna bağlı bir sonuçtur.

İkinci yanılgı, tam yeniden yüklemenin uygulamayı yeniden başlatmak olduğudur. Model uygulamayı değil, kökü yeniden kurar. Telefon sürecinin ayakta kalması ya da kalmaması ağaç kuralının dışındadır; kural yalnız ağaçtaki düğümlere ne olduğunu söyler.

Üçüncü yanılgı, yayın yapılandırmasının ağaca yansıdığıdır. Derleme türü, imza ve sürüm kanalı düğümlerin tipini ya da özelliklerini değiştirmez. Aynı kaynak hem geliştirme hem yayın paketinde aynı ağacı üretir; farklı olan, ağaca ulaşan paketin nereden geldiğidir.

## Sınırlayıcı Ölçüm

Bu dersin ayrım sorusu **bu değişiklik nereye ulaşıyor (M12/K02)** sorusudur. O soru bir kod değişikliğinin yayılımını sorar: yerinde, bağlantıda, kıran ya da örtük. Bu kurs kodun değil, çalışma anındaki tek bir güncellemenin tek bir düğüme etkisini sınıflar. Hızlı yenilemede kod değişikliği yerinde yayılır; ağaçta bıraktığı iz ise başlık düğümünde güncellenen, geri kalanda korunandır. İki sorunun cevabı birbirinden bağımsızdır.

Son ölçüm eski kökü gösterir. Tam yeniden yükleme kökte yapılır; kural yalnız kök düzeyindeki kayıtlara süzülür.

```javascript
// main.mjs
import { printOps } from "./fate.mjs";
import { openSession, press, fullReload } from "./dev.mjs";

let session = openSession({ root: "App", title: "Ana ekran" });
session = press(press(press(session)));
const [after, ops] = fullReload(session, { root: "App", title: "Ana ekran" });
printOps(ops.filter((op) => op.path.split("/").length === 2));
console.log(`komut: ${ops.filter((op) => op.fate !== "korunan").length}`);
```

```text
sokulen: /App
kurulan: /App[1]
komut: 6
```

Odak düğüm eski kök `/App`. Sökülen çıktı; yenisi `/App[1]` anahtarıyla kurulan. Eski kök gidince altındaki başlık ve sayaç da sökülen kaydı aldı: komut altı. Sökülen düğüm kimliğini yitirir, yani sayaç üçten sıfıra döndü. Güncellenen bir kök kimliğini korurdu.

**BU7.** Model, bu akıbetin kuralını kurar; model çerçevenin kendisi değildir. Modelde hızlı yenileme ağacı kaynaktan baştan kurar ve karşılaştırır; gerçek bir hızlı yenileme yalnız değişen dosyayı yeniden değerlendirir ve durumu tutmak için kendi kurallarını uygular. Modelde kök anahtarı elle artırılır; gerçek bir tam yeniden yükleme paketi baştan yükler ve bunun bedeli, geliştirme sunucusunun bağlantısı model dışındadır. Yayın hattı da modelde yoktur: derleme, imzalama ve mağaza süreçleri ağaç kuralının girdisi değildir.

## Kapanış Tablosu

Kurs boyunca yirmi güncelleme ölçüldü. Her satır bir dersin akıbetini ve o dersin sınırlayıcı ölçümünde odaklanılan düğümü verir. Akıbet hücreleri kaynak dersin `Özet` bölümünden alınmıştır.

| Ders | Ölçülen güncelleme | Akıbet | Sınırlayıcı ölçüm |
|---|---|---|---|
| React Native Nedir | sayaç ağaca girmeyen değişkende artar | korunan | `/Screen/Text`, komut 0 |
| Ortam Kurulumu | kabuktan sonraki ilk güncelleme | kurulan | `/App/Home`, alt ağacıyla |
| Çekirdek Bileşenler | yer tutucu görselle değişir | sökülen | `/Card/Text` |
| Biçem Sistemi | içeriği aynı biçem nesnesi gelir | korunan | `/Row/Box`, komut 0 |
| Dokunma ve Etkileşim | basılı durum özellik olur | güncellenen | `/Screen/Button` |
| Platforma Özgü Kod | iki platformun ağacı karşılaştırılır | kurulan | `/Settings/Toggle` |
| Gezinme | yeni rota itilir | korunan | `/Stack/Screen[liste]` |
| Durum Yönetimi | sepet sayısı değişir | güncellenen | `/Screen/Header/Badge` |
| Ağ ve Veri | veri gelir | sökülen | `/Feed/Spinner` |
| Yerel Depolama | açılışta taslak okunur | kurulan | `/Editor/Draft` |
| Güvenli Depolama | oturum kapanır | sökülen | `/App/Account` |
| Bildirimler ve Derin Bağlantı | bağlantı açılır | kurulan | `/Stack/Screen[siparis-42]` |
| Hareketler ve Animasyonlar | hareket yerel tarafta sürer | korunan | `/Deck/Card`, komut 0 |
| Liste Başarımı | başa öge eklenir | güncellenen | `/Inbox/Row` |
| Kare Hızı ve Profilleme | ağaç üç kez yeniden üretilir | korunan | `/Screen/Chart` |
| Paket Boyutu ve Başlangıç | ertelenmiş ekran yüklenir | kurulan | `/App/Reports` |
| Hata Ayıklama Araçları | alt ağaç hata verir | sökülen | `/Screen/Panel` |
| Test | düğmeye basılır | güncellenen | `/Counter/Text` |
| Yerel Modül Yazımı | harita merkezi değişir | güncellenen | `/Screen/NativeMap`, komut 1 |
| Derleme ve Yayın | tam yeniden yükleme | sökülen | `/App`, komut 6 |

Derslerin dağılımı: korunan 5 (React Native Nedir, Biçem Sistemi, Gezinme, Hareketler ve Animasyonlar, Kare Hızı ve Profilleme), güncellenen 5 (Dokunma ve Etkileşim, Durum Yönetimi, Liste Başarımı, Test, Yerel Modül Yazımı), kurulan 5 (Ortam Kurulumu, Platforma Özgü Kod, Yerel Depolama, Bildirimler ve Derin Bağlantı, Paket Boyutu ve Başlangıç), sökülen 5 (Çekirdek Bileşenler, Ağ ve Veri, Güvenli Depolama, Hata Ayıklama Araçları, Derleme ve Yayın).

Bu dağılım, çekirdek dosyanın açılış sayımıyla aynı şey değildir. Çekirdeğin açılış sayımı tek bir güncellemenin sekiz düğümünü sayar: korunan 5, güncellenen 1, kurulan 1, sökülen 1 ve komut 3. Tablo ise yirmi dersin her birinin akıbetini sayar. Biri düğüm, öteki ders sayar.

## Özet

- Bu dersin akıbeti: sökülen. Tam yeniden yüklemede eski kök `/App` kök anahtarı değiştiği için sökülen çıktı; yenisi kurulan oldu, altındaki üç düğümle komut altı.
- Hızlı yenileme değişen düğümü güncellenen, geri kalanı korunan bırakır; durum yaşar. Kök tipi ya da anahtarı değişince durum yitirilir.
- Derleme, imzalama ve sürüm kanalı ağaçta görünmez; uzaktan güncelleme yalnız JavaScript tarafını değiştirir.
- Yirmi dersin akıbeti beşer beşer dağılır: korunan, güncellenen, kurulan ve sökülen beşer ders.

## Sonraki Adım

Bu kurs, ortak kodu platformun yerel görünümlerine tarif olarak ileten bir çerçeveyi ölçtü. Sıradaki kurs, ekranı platformun görünümlerine bırakmayıp kendi çizim motoruyla çizen bir çerçeveyi ele alır.
