Svelte 5 JavaScript değil
(hodlbod.npub.pro)- Yakın zamanda bir web uygulamasını Svelte 5 sürümüne yükselttikten sonra yaşanan sorunların özeti
- Deep reactivity özelliği ve değişen lifecycle nedeniyle beklenmedik davranışlar ortaya çıktı
- Svelte 3/4'ü uzun süre keyifle kullandım, ancak bundan sonra yeni projelerde Svelte'i seçmeyeceğimi düşünüyorum
Yüksek hız ihtiyacı
- Svelte ekibi, deep reactivity ile performans optimizasyonu denedi ve daha iyi performans elde etti
- Daha önce de derleme süreci sayesinde yüksek performans sunuyordu ve bu, onu diğer framework'lerden ayıran güçlü yönlerinden biriydi
- Bu durum framework'ü opak hale getirip debug etmeyi zorlaştırsa da, performans ve üretkenlik açısından kabul edilebilir bir trade-off gibi geliyordu
Yüksek hız ihtiyacı
- Svelte ekibinin Svelte 5'te öne çıkardığı ana değişiklik, performansı daha ince taneli tepkisellikle artırmayı amaçlayan “deep reactivity”
- Önceki Svelte sürümlerinde bu hedefe ağırlıklı olarak Svelte compiler ile ulaşılıyordu
- Geliştiricinin yeni kavramları doğrudan öğrenmesine gerek kalmadan iç mantığı yeniden düzenleyebilmesi, Svelte'in özgünlüğünü öne çıkarıyordu
- Aynı zamanda bu derleme süreci framework'ü opaklaştırarak karmaşık sorunların debug edilmesini zorlaştırıyordu
- Compiler'ın kendi hataları nedeniyle sebebi saptanması zor sorunlar çıkıyor, bazen ancak sorunlu component'i tamamen refactor ederek çözüm bulunabiliyordu
- Yine de hız ve üretkenlik açısından makul bir uzlaşma gibi geldiği için, projeyi dönemsel olarak sıfırlama zahmetine katlanıyordum
Svelte JavaScript değil
- Svelte 5 bu trade-off'u iki katına çıkarıyor
- Temel fark, soyutlama-performans uzlaşmasının derleme aşamasını aşıp runtime kısmına da sızmış olması
- Deep reactivity desteği için Proxy kullanımı
- Örtük (implicit) component lifecycle durumu
- Bu iki değişiklik performansı iyileştiriyor ve geliştirici API'sinin daha parlak (slicker) görünmesini sağlıyor
- Bundan hoşlanmamayı gerektiren ne olabilir? Ne yazık ki bu iki özellik, leaky abstraction için tipik örnekler
- Sonuçta geliştiricinin başa çıkması gereken daha karmaşık bir ortam yaratıyorlar
Proxies nesne değildir
- Proxy kullanımı sayesinde Svelte ekibi, geliştiriciden ek iş istemeden framework performansını biraz daha artırabildi
- React gibi framework'lerde durumu birçok component üzerinden aktarırken gereksiz rerender'lara yol açmak kolayken, Svelte bunu azaltmak için Proxy'yi devreye aldı
- Svelte compiler zaten sanal DOM karşılaştırmasında oluşabilecek bazı sorunları önlüyordu, ama Proxy ile performansı biraz daha artırabileceğini düşünmüş görünüyor
- Svelte ekibi, Proxy'nin geliştirici deneyimini de iyileştirdiğini ve “hem verimliliği hem kullanım kolaylığını en üst düzeye çıkarabileceğini” savundu
- Sorun şu ki Svelte 5 görünüşte daha basit dursa da gerçekte daha fazla soyutlama ekliyor
- Örneğin dizi metodu algılaması için Proxy kullanıldığında, Svelte 4'te yazmak gereken
value = valuegibi koda artık ihtiyaç kalmıyor - Svelte 4'te reactivity'yi tetiklemek için geliştiricinin compiler'ın nasıl çalıştığını belli ölçüde anlaması gerekiyordu. Svelte 5 ise “compiler'ı unutabilirsiniz” izlenimi veriyor, ama gerçekte durum böyle değil
- Yeni soyutlamalarla kazanılan kolaylık kadar, compiler'ın istediği gibi davranmasını sağlamak için geliştiricinin bilmesi gereken kurallar da arttı
- Örneğin dizi metodu algılaması için Proxy kullanıldığında, Svelte 4'te yazmak gereken
- Svelte'i uzun süre kullanırken kişisel olarak zamanla Svelte store'larını daha çok, reactive declaration'ları ise daha az kullanmaya başladım
- Svelte store'ları özünde JavaScript kavramlarına daha yakındı,
updatemetodunu çağırma biçimi basitti ve$söz dizimi daha çok ek bir fayda gibiydi - Proxy de reactive declaration'larda olduğu gibi, “tek şeymiş gibi görünse de sınır noktalarında farklı davranma” sorununa yol açıyor
- Svelte store'ları özünde JavaScript kavramlarına daha yakındı,
- Svelte 5'i ilk kullandığımda her şey iyi çalışıyordu, ancak Proxy durumunu IndexedDB'ye kaydetmeye çalışınca
DataCloneErroroluştu- Üstelik hangi değerin Proxy olduğunu kesin biçimde anlamak için structured clone'u
try/catchile denemek gerekiyor; bu da performans maliyeti yaratıyor - Sonuç olarak neyin Proxy olduğunu akılda tutmak ve dış dünyanın Proxy'yi tanımadığı bağlamlarda her seferinde
$state.snapshotkullanmak gerekiyor - Bu da, “soyutlama geliştirici kolaylığı sağlar” şeklindeki ilk niyetin tersine, geliştiriciye daha karmaşık kurallar ve prosedürler dayatıyor
- Üstelik hangi değerin Proxy olduğunu kesin biçimde anlamak için structured clone'u
Component'ler fonksiyon değildir
- Sanal DOM'un 2013 civarında popüler olmasının nedeni, uygulamaları fonksiyon bileşimleri şeklinde modellemeyi mümkün kılmasıydı
- Svelte, sanal DOM yerine compiler kullanarak lifecycle fonksiyonlarını sadeleştirme ve performansı artırma yaklaşımını sürdürüyordu
- Ancak Svelte 5 ile lifecycle kavramı, React Hooks'a benzer şekilde yeniden eklenmiş oldu
- React'te Hooks, lifecycle metodlarındaki state ile ilgili kodu azaltan bir soyutlamadır
- Kod daha temiz görünür, ancak
setTimeoutiçinde state'e erişmek gibi durumlarda geliştiricinin dikkat etmesi gereken çok nokta vardır - Svelte 4'te de component unmount olduğunda asenkron kodun DOM öğelerine erişmesi sorun yaratabiliyordu
- Şimdi Svelte 5'te state değişiklikleriyle effect'leri koordine etmek için component lifecycle'a örtük state eklenmiş görünüyor
- Kod daha temiz görünür, ancak
- $effect için resmi belgelerde şöyle deniyor:
“$effect herhangi bir yere yerleştirilebilir, ancak component başlatılırken (veya bir parent effect aktifken) çağrılmalıdır ve component (ya da parent effect) unmount edildiğinde ortadan kalkar”
- Bu, lifecycle'ın yalnızca mount/unmount olmak üzere iki aşamadan ibaret olduğu anlatısına rağmen, state değişimlerini izlemeyi gerektiren karmaşık bir effect yapısı bulunduğunu düşündürüyor
- Resmi lifecycle belgeleri “before update/after update yok” dese de,
$effect.prevetickgibi yeni kavramlar ortaya çıkıyor - Bu da fiilen mount/unmount dışında state değişim anlarının da anlaşılmasını gerektiriyor
- Gerçek kullanımda sorun çıkaran nokta, Svelte ile ilgisiz bir fonksiyona geçirilen state'in bile component lifecycle'ına bağlı kalmasıydı
- Örneğin modal pencereleri bir store ile yönetirken callback'i child component'e aktaran bir desen kullandım
const { value } = $props() const callback = () => console.log(value) const openModal = () => pushModal(MyModal, { callback }) - Eğer bu kod modal component'in içindeyse, modalı çağıran component önce unmount olur ve o anda
valueundefinedolarak değişir - Bu repoda minimal bir yeniden üretim örneği paylaşılmış
- Yani component yaşam döngüsü bittikten sonra bile yaşamaya devam eden callback'in referans verdiği props bir anda
undefinedoluyor - Bu, temel JavaScript'ten farklı bir davranış ve Svelte sanki kendi başına garbage collection benzeri işler yapıyormuş gibi görünüyor
- Bunun için mühendislik açısından gerekçeler olabilir, ancak beklenmedik bir davranış olduğu için şaşırtıcı
Sonuç
- Kolay olanın çekici olduğu açık, ancak Rich Hickey'nin dediği gibi kolay olmak basit olmak anlamına gelmez
- Joel Spolsky'nin de dediği gibi, beklenmedik davranışların ortaya çıkmasından hoşlanmıyorum
- Svelte şimdiye kadar çok fazla ‘sihir’ gösterdi, ancak bu sürümde o sihri kullanabilmek için ezberlenmesi gereken şeyler arttığından getirisi yükünden az kalıyor
- Bu yazının amacı Svelte ekibini suçlamak değil; aksine Svelte 5'i (ve React Hooks'u) tercih eden birçok kişi olduğunun farkındayım
- Önemli olan, kullanıcıya kolaylık sağlamak ile kullanıcının kontrolü elinde tutabilmesi arasındaki denge
- Gerçekten iyi yazılım, ‘zekice’ olmaya değil ‘anlaşılabilir’ olmaya dayanır
- Yapay zeka araçları geliştikçe, insana ne yaptığını unutturan araçlar yerine mevcut birikimini kullandıran ve derin anlayışı destekleyen araçları seçmek daha önemli hale geliyor
- Rich Harris'e ve ekibine bugüne kadarki keyifli geliştirme deneyimi için teşekkürler. Umarım bu yazı çok da temelsiz olmayan bir geri bildirim olur
7 yorum
Proxy onu yapan kişi için rahat ama debug eden kişiyi sinirlendiriyor tabii lol
Yan projelerde DX açısından solidjs bir numara >m< / çok mutluyum
Svelte gibi alternatifler olduğu için React/nextjs’in de büyük bir ivme kazanabildiğini düşünüyorum.
Temelde svelte bir language olduğu için, umarım UI’ı tanımlayan bir dilin ilerlemesi gereken yönü de iyi gösterir.
Ben React kullanacağım
Aşırının fazlası zarardır
Takıntılı saplantı
Üstüne bir kat daha
React ve özellikle Next'in etkisini epey alırken garip bir şekilde değiştiğini düşünüyorum.
+page, Svelte'i bilmeden bakınca anlaması zor ve$state,$derivedgibi rune'lar da sanki React'i takip ediyormuş gibi; açıkçası değişkenlerin başına$:koyulan dönem bana daha iyi geliyor.{#each a in array} {/each}gibi eski usul sözdizimine de katlanılır ama hâlâ zahmetli. Eğer amaç seçmeli reactivity sayesinde performans iyileştirmesiyse, bence SolidJS çok daha iyi bir yönde. JSX'i olduğu gibi kullandığı için React'ten geçmek de görece daha kolay. SolidJS'in nispeten ilgi görmemesi gerçekten şaşırtıcı.Signals'ın Gartner hype cycle içindeki
Trough of disillusionmentaşamasına doğru gittiğini düşünmeden edemiyorum 🤔 Kullanım senaryoları zamanla daha netleştikçe değerlendirmelerin de iyileşebileceğini düşünüyorumHacker News görüşü
Başta runes hakkında pek heyecanlı değildim. Ancak
.svelteşablonlarına reaktif harici bileşenler aktarabildiğinizde ve reaktiviteyi dahili olarak kapsülleyebildiğinizde fikrim değişti. Bu, vitest testleri yazabilip yine de reaktivitenin avantajlarından yararlanabileceğiniz anlamına geliyor. Bu gerçekten çok güçlü ve AFAIK, frontend dünyasında benzersizTicari olarak dağıtılmış bir SvelteKit uygulamasını aktif olarak geliştiriyorum ve deneyimim hakkında birkaç düşünce paylaşmak istiyorum
+pagegibi routing yapılarıyla uğraşmak gerekmiyordu. Svelte dosyalarını istediğiniz yere koyabiliyor ve modern bir framework'ün avantajlarını alırken sorunsuz biçimde render edebiliyordunuzEmberJS'in ortadan kaybolması üzücü. API'si son 10 yılda oldukça istikrarlıydı. İronik biçimde, son 10 yılda EmberJS uygulaması yazan biri; React, Svelte, Vue vb. ile aynı işi yapan birine göre migration konusunda daha az zorlanmış olacaktır
Yazarın gönderinin üst kısmında listelediği iki Github bağlantısı da aynı soruna işaret ediyor ve bu sorunun bir çözümü var (
use $state.raw)Svelte 5, JavaScript olmamanın <i>en kötü</i> hâli. js'in sorunlarını çözmüyor, sadece bazı frontend problemleri için sızdıran bir soyutlama sunuyor. Bence Solid, Svelte'den daha iyi bir yön. Çünkü yeni bir dile dayanmıyor. Ama js ideal olmadığı için js olmayan bir şey üretme içgüdüsü var. Elm, svelte'in öncülü. Ama daha iyisini yapabileceğimizi düşünüyorum...[0]
Svelte 4'te store'lardan gerçekten nefret ettiğim için Svelte 5 kullanmaya başladım. Yeni bir projede Sveltekit ve Svelte 5 kullanıyorum ve şunu söylemeliyim... React'in üretkenliği, Sveltekit ve Svelte teknolojisi teknik olarak daha iyi olsa bile hâlâ rakipsiz
+page.server.tsveya+page.svelteya da bunların türevleri şeklinde adlandırılması, kod içinde kolay arama yapmayı zorlaştırıyor. Svelte'in araçlarıtscve ESLint'ten ayrı duruyor; bu da bunları CI'a entegre etmeyi ve geliştirme sırasında kullanmayı zorlaştırıyorCallback olarak closure geçirirken beklenmedik davranışlar olduğu için Svelte'in JavaScript olmadığını söylemek garip geliyor. Daha iyi başlık bence "Svelte 5 beni şaşırttığı için hoşuma gitmiyor" olurdu
Saf JavaScript kullanarak bileşenler ve uygulamalar inşa etmenizi sağlayan bir kütüphane arıyorsanız Lit'e bakın: Lit
Makul bir frontend deneyimi mi istiyorsunuz? Düz JavaScript, web component'leri, htmx, Blazor kullanın