Angular 21'e taşınırken defterime düştüğüm notlar
Geçen ay bir yan projeyi Angular 21'e taşımaya karar verdiğimde niyetim sadece "sürüm numarasını güncelleyeyim" gibi bir şeydi. İki hafta sonra elimde farklı bir framework vardı — aynı isim, çok farklı bir his. Bu yazı bir changelog değil. Kod yazarken tuttuğum, "vay be bu değişti" dediğim anların derlemesi.
Zone.js'i kaldırdığım gün fark ettiğim şey
provideZonelessChangeDetection()'ı ilk kez production'a aldığımda beklediğim şey performans grafiğinde küçük bir iyileşmeydi. Olan şey bambaşkaydı: hata ayıklarken artık "neden bu component tekrar render oldu" sorusuna cevap veremediğim anlar bitti. Zone.js varken bu soru bazen bir dedektiflik işine dönüşürdü — bir yerde bir setTimeout, bir yerde bir üçüncü parti kütüphanenin event listener'ı, hepsi CD tetikliyor ve sen neyin neyi tetiklediğini template'e bakarak asla anlayamıyorsun.
Zoneless'ta değişiklik artık bir mistik olay değil, bir iz sürülebilir olay. Bir signal değişti, bağımlı olan her yer güncellendi, hepsi bu. İlk başta bu netlik biraz ürkütücü geldi çünkü alışkın olmadığım bir sorumluluk getiriyor: state'ini gerçekten signal'da tutman lazım, "component property'sine atayıp CD'nin bir şekilde hallet"meyi bekleyemezsin. Ama bu sorumluluk aslında bir hediye — kodun artık kendini anlatıyor.
resource() beni RxJS'ten değil, "ne zaman loading true olsun" sorusundan kurtardı
Bir proje detay sayfasında route parametresine göre veri çekiyordum. Eskiden bu iş şuna benzerdi: bir subject, bir switchMap, takeUntilDestroyed, ayrı bir loading signal'ı, ayrı bir error signal'ı, hepsini elle senkron tutma derdi. Küçük bir state machine'i elle yazmış gibi hissederdim.
resource() ile aynı işi şöyle kurdum:
project = resource({
params: () => ({ slug: this.slug() }),
loader: ({ params }) => this.contentful.getProjectBySlug(params.slug),
});
project.value(), project.isLoading(), project.error() — üçü de zaten orada, senkron, birbirleriyle tutarlı. Route değişince params fonksiyonu yeniden çalışıyor, yeni fetch tetikleniyor, eski isteğin sonucu iptal ediliyor. Bunu daha önce elle yazdığım her seferinde bir yerinde bug bırakırdım — genelde eski isteğin geç dönüp yeni state'in üstüne yazması şeklinde bir race condition. resource() bunu default olarak doğru yapıyor ve ben artık bu bug'ı aramıyorum.
RxJS'i attığım için değil, bu — RxJS hâlâ gerçek composition gerektiren yerlerde masada. Ama "sadece bir HTTP isteğini component state'ine bağlamak" için artık ona ihtiyacım yok, ve bu fark hissettiğimden daha büyük çıktı.
Control flow'u değiştirmek "sözdizimi güzelleşti" değil, "template artık TypeScript gibi davranıyor" demek
@if / @for'a geçtiğimde beklentim kozmetikti — *ngIf yerine daha kısa bir şey yazacaktım. Asıl fark editördeydi: @if (user(); as u) yazdığımda IDE artık u'nun tipini gerçekten biliyor, *ngIf + as kombinasyonunun bazen kafa karıştırdığı belirsizlikler yok. @for içindeki track zorunluluğu ilk başta bir angarya gibi geldi, sonra fark ettim ki bu proje boyunca yanlışlıkla index'e track ettiğim, sonra liste yeniden sıralanınca DOM'un tuhaf davrandığı kaç yer olduğunu unutmuşum. Derleyicinin "track'i unutma" demesi aslında geçmişte kendime defalarca açtığım bir bug kategorisini kapatmış.
Build tarafında hissedilen şey: bekleme süresinin kaybolması
Vite/esbuild tabanlı dev server'a geçtikten sonra en çok fark ettiğim şey aslında bir "özellik" bile değildi — save tuşuna bastıktan sonraki sessizlikti. Eskiden orada küçük bir bekleme vardı, o kadar alışmıştım ki fark etmiyordum bile. Şimdi o boşluk yok, ve bunun günde onlarca kez tekrarlanan bir eylem olduğunu düşününce, biriken zamandan çok, biriken dikkat kaybının önlendiğini fark ettim. Akış kırılmıyor.
SSR/hydration: artık "umarım tutar" değil "tutuyor"
Bu projede zaten server-side render kullanıyordum ve geçmişte hydration mismatch'leri benim için hep bir şans oyunuydu — console'da sessizce bir uyarı çıkar, bazen çıkmaz, production'da bazen görürsün bazen görmezsin. Angular 21'deki hydration iyileştirmeleriyle bu belirsizlik payı küçüldü. En somut fayda: WebGL arka planımı (gl-bg component'i) server'da hiç render etmeden client'a bırakan kod artık daha az özel-durum kontrolüne ihtiyaç duyuyor çünkü framework "bu hydrate edilemez, atla" durumunu benden daha iyi anlıyor.
Genel his: framework artık arkanda duruyor, önünde durmuyor
Eski Angular'la çalışırken bazen hissettiğim şey şuydu: framework'ün varsayımlarına karşı kod yazıyordum — CD döngüsünü kandırmak, gereksiz re-render'ı önlemek, RxJS subscription'ının sızmadığından emin olmak için ekstra defans yazmak. Angular 21'de bu defans katmanının çoğu kayboldu. Signal + zoneless + resource() üçlüsü bir araya geldiğinde ortaya çıkan şey "daha az kod" değil — "daha az kod hakkında endişelenmek". Fark küçük gibi görünüyor ama bir codebase'i aylarca sürdürdüğünde asıl yorgunluğun kaynağının satır sayısı değil, bu arka plan endişesi olduğunu anlıyorsun.
Denemenizi mutlaka önereceğim üç şey varsa: resource()'ı gerçek bir route-level veri çekme senaryosunda kullanın (basit bir todo listesinde farkı göremezsiniz), zoneless'ı açık bir projede @HostListener ile güncellenen bir state'i signal'a çevirmeden bırakıp neyin kırıldığını izleyin (öğretici bir acı), ve @for + track'i yanlış kullanıp DOM'un ne zaman "hatırladığını" ne zaman unuttuğunu bizzat görün. Üçü de dokümanda okuyunca sıradan görünüyor. Elde deneyince değil.
Originally published on ysndmr.com.
Top comments (0)