Kurumsal projelerin bir kısmında hâlâ ES5 yazımıyla, var değişkenleri ve eski sürümlü kütüphanelerle yaşayan kodlar dolaşıyor. Bu kodlar bugünün Chrome'unda, Safari'sinde ve Firefox'unda da çalışıyor; sorun çalıştırmak değil, yeni özellikleri nasıl alacağımız sorusunun yıllar içinde cevapsız kalmasıdır. Uyumluluk bir kez çözülüp kapanan bir konu değil; tarayıcılar her altı hafta değişirken kod tabanı yerinde sayıyorsa aradaki mesafe her gün biraz daha büyür.

Transpile mi, Polyfill mi?

İki araç farklı yaralara derman olur. Transpiler (Babel, TypeScript) yeni sözdizimini eski tarayıcıların anlayacağı biçime çevirir; polyfill ise yoksa var etmek için eksik API'yi ekler. Her ikisinin dozunu da iyi ayarlamak gerekir:

// Babel hedeflerine örnek: eski Android'de çalış, modern tarayıcıda şişme
module.exports = {
  presets: [
    ["@babel/preset-env", {
      targets: { "chrome": "90", "firefox": "88", "samsung": "14" },
      useBuiltIns: "usage",
      corejs: { version: 3, proposals: false },
    }],
  ],
};

useBuiltIns: "usage" sayesinde yalnızca kullandığınız API'ler için polyfill eklenir; aşırı büyüklükte bir core-js şişkinliğinden korunursunuz. Hedef listesini dar tutmak, gönderdiğiniz bayt sayısını doğrudan küçültür. Aynı mantık hata ayıklamayı da kolaylaştırır: derlenmiş çıktı hakkında kabus rüyaları görmemek için kaynak haritalarını (source map) hata izleme aracınıza bağlamayı unutmayın.

Bu noktada kurumların en sık düştüğü tuzağı da not edelim: tüm olası tarayıcıları tek bir hedef listesinde toplamak. Bir zamanın "IE11 desteği bittiğinde çıkaracağız" sözü, on yıldır birikmiş polyfill yüküyle geri döner. Hedefleri yaşlarına göre katmanlara ayırmak, borcun birikmesini önler. Geçiş dönemlerinde iki yapıyı paralel yürütmek de bir tuzaktır: modül ve klasik derleme çıktısını birlikte taşıyan ekipler, hata ayıklamada iki kat dosya, iki kat kaynak haritası ve iki kat sürüm riskiyle yaşar.

Özellik Algılama: Sormadan Kullanma

Kullanıcı agent'ına güvenmek yerine özelliğin kendisini sorabilirsiniz; if ("navigator.gpu" in window) yazmak, sürüm numarası avından çok daha sağlamdır. Modern koşullu yükleme için dinamik içe aktarma da elinizi güçlendirir:

if ("ResizeObserver" in window) {
  const { bagla } = await import("./modern-tablo.js");
  bagla(document.querySelector("#panel"));
} else {
  await import("./yedek-tablo.js");
}

Bu yaklaşımın sessiz bir maliyeti vardır: iki kod yolunu da test etmek. Özellik algılamayla bölünen her yol, bir gün gerçekten çalışmak zorundadır; aksi hâlde "eski tarayıcıda açılmıyor" şikâyeti kapınıza döner. Bu yüzden yedek yolları bile bir kez haşlamadan yayına çıkmayın.

Maratonun Ritmi

Uyumluluk bir hedef değil, sürdürülebilir bir tempo işidir: ES modüllerine geçiş, kritik polyfill'lerin denetimi ve kırılan üçüncü parti kütüphanelerin çıkarılması yıllık rutin olmalı. Kodunuzu ne kadar eski tutmak zorundaysanız, yeni özellikleri o kadar katmanlı alın; ama kod tabanını asla çağının altında dondurmayın. Test matrisinizi gerçek kullanıcı verinize göre kurun: analitiğinizde payı yüzde birin altına düşen motorları hedef listesinden çıkarın, yeni çıkan motorları ise ilk gün ekleyin. Maratonu kazanan, en hızlı koşan değil, temposunu bozmayan ekiptir.