Web Çerçeveleri Neleri Çözer ve Onlarsız Nasıl Yapılır (Bölüm 1)
Yayınlanan: 2022-03-10Son zamanlarda çerçeveleri vanilya JavaScript ile karşılaştırmakla çok ilgilenmeye başladım. Bazı serbest projelerimde React'i kullandığım bazı hayal kırıklıklarından sonra ve bir şartname editörü olarak web standartlarıyla yakın zamanda daha yakından tanışmamla başladı.
Çerçeveler arasındaki ortak noktaların ve farklılıkların neler olduğunu, web platformunun daha yalın bir alternatif olarak neler sunabileceğini ve bunun yeterli olup olmadığını görmek istiyordum. Amacım çerçeveleri ezmek değil, bunun yerine maliyetleri ve faydaları anlamak, bir alternatifin var olup olmadığını belirlemek ve bir çerçeve kullanmaya karar versek bile ondan öğrenip öğrenemeyeceğimizi görmek.
Bu ilk bölümde, çerçeveler arasında ortak olan birkaç teknik özelliği ve bazı farklı çerçevelerin bunları nasıl uyguladığını derinlemesine inceleyeceğim. Ayrıca bu çerçeveleri kullanmanın maliyetine de bakacağım.
Çerçeveler
Bakmak için dört çerçeve seçtim: Bugün baskın olan React ve React'ten farklı şeyler yaptığını iddia eden üç yeni yarışmacı.
- Tepki
“React, etkileşimli kullanıcı arayüzleri oluşturmayı zahmetsiz hale getiriyor. Bildirime dayalı görünümler, kodunuzu daha öngörülebilir ve hata ayıklamayı kolaylaştırır." - SolidJS
"Solid, React ile aynı felsefeyi takip ediyor... Ancak, sanal bir DOM kullanmayı bırakan tamamen farklı bir uygulaması var." - ince
“Svelte, kullanıcı arayüzleri oluşturmaya yönelik yeni ve radikal bir yaklaşım… uygulamanızı oluşturduğunuzda gerçekleşen bir derleme adımı. Svelte, sanal DOM farklılaştırma gibi teknikleri kullanmak yerine, uygulamanızın durumu değiştiğinde DOM'yi cerrahi olarak güncelleyen kod yazar." - Aydınlatılmış
"Web Bileşenleri standartlarının üzerine inşa edilen Lit, yalnızca tepkisellik, bildirime dayalı şablonlar ve bir dizi ince düşünülmüş özellik ekliyor."
Çerçevelerin farklılaştırıcıları hakkında söylediklerini özetlemek gerekirse:
- React, bildirime dayalı görünümlerle kullanıcı arabirimleri oluşturmayı kolaylaştırır.
- SolidJS, React'in felsefesini takip eder ancak farklı bir teknik kullanır.
- Svelte, kullanıcı arayüzlerine derleme zamanı yaklaşımı kullanır.
- Lit, bazı ek hafif özelliklerle birlikte mevcut standartları kullanır.
Hangi Çerçevelerin Çözdüğü
Çerçevelerin kendileri bildirimsel, tepkisellik ve sanal DOM sözcüklerinden bahseder. Bunların ne anlama geldiğine geçelim.
Bildirimsel Programlama
Bildirimsel programlama, kontrol akışını belirtmeden mantığın tanımlandığı bir paradigmadır. Hangi adımların bizi oraya götüreceğini değil, sonucun ne olması gerektiğini tanımlarız.
2010 dolaylarında, bildirim temelli çerçevelerin ilk günlerinde, DOM API'leri çok daha yalın ve ayrıntılıydı ve zorunlu JavaScript ile web uygulamaları yazmak çok fazla ortak kod gerektiriyordu. İşte o zaman, “model-view-viewmodel” (MVVM) kavramı, o zamanlar çığır açan Knockout ve AngularJS çerçeveleri ile yaygınlaştı ve kütüphane içinde bu karmaşıklığı işleyen bir JavaScript bildirim katmanı sağladı.
MVVM günümüzde yaygın olarak kullanılan bir terim değildir ve daha eski olan “veri bağlama” teriminin bir çeşit varyasyonudur.
Bağlanma verileri
Veri bağlama, verilerin bir model ile kullanıcı arabirimi arasında nasıl senkronize edildiğini ifade etmenin bildirimsel bir yoludur.
Tüm popüler UI çerçeveleri bir tür veri bağlama sağlar ve öğreticileri bir veri bağlama örneğiyle başlar.
İşte JSX'te veri bağlama (SolidJS ve React):
function HelloWorld() { const name = "Solid or React"; return ( <div>Hello {name}!</div> ) }
Lit'te veri bağlama:
class HelloWorld extends LitElement { @property() name = 'lit'; render() { return html`<p>Hello ${this.name}!</p>`; } }
Svelte'de veri bağlama:
<script> let name = 'world'; </script> <h1>Hello {name}!</h1>
reaktivite
Tepki, değişimin yayılmasını ifade etmenin bildirimsel bir yoludur.
Veri bağlamayı bildirimsel olarak ifade etmenin bir yolu olduğunda, çerçevenin değişiklikleri yayması için etkili bir yola ihtiyacımız var.
React motoru, oluşturma sonucunu önceki sonuçla karşılaştırır ve farkı DOM'nin kendisine uygular. Değişiklik yayılımının bu şekilde ele alınmasına sanal DOM adı verilir.
SolidJS'de bu, deposu ve yerleşik öğeleriyle daha açık bir şekilde yapılır. Örneğin, Show
öğesi, sanal DOM yerine dahili olarak neyin değiştiğini takip eder.
Svelte'de “reaktif” kod oluşturulur. Svelte, hangi olayların değişikliğe neden olabileceğini bilir ve olay ile DOM değişikliği arasındaki çizgiyi çizen basit kod üretir.
Lit'te tepkisellik, esasen HTML özel öğelerinin yerleşik tepkiselliğine dayanan öğe özellikleri kullanılarak gerçekleştirilir.
Mantık
Bir çerçeve, veri bağlama için bildirimsel bir arabirim sağladığında, tepkisellik uygulamasıyla birlikte, geleneksel olarak zorunlu olarak yazılan mantığın bir kısmını ifade etmenin bir yolunu da sağlaması gerekir. Mantığın temel yapı taşları “if” ve “for”dur ve tüm ana çerçeveler bu yapı taşlarının bir ifadesini sağlar.
Şartlılar
Sayılar ve dize gibi temel verileri bağlamanın yanı sıra, her çerçeve “koşullu” bir ilkel sağlar. React'te şöyle görünür:
const [hasError, setHasError] = useState(false); return hasError ? <label>Message</label> : null; … setHasError(true);
SolidJS, yerleşik bir koşullu bileşen sağlar, Show
:
<Show when={state.error}> <label>Message</label> </Show>
Svelte, #if
yönergesini sağlar:
{#if state.error} <label>Message</label> {/if}
Lit'te, render
işlevinde açık bir üçlü işlem kullanırsınız:
render() { return this.error ? html`<label>Message</label>`: null; }
Listeler
Diğer ortak çerçeve ilkel, liste işlemedir. Listeler, UI'lerin önemli bir parçasıdır - kişi listesi, bildirimler vb. - ve verimli çalışmak için, bir veri öğesi değiştiğinde tüm listeyi güncellemek yerine reaktif olmaları gerekir.
React'te liste işleme şuna benzer:
contacts.map((contact, index) => <li key={index}> {contact.name} </li>)
React, liste öğelerini ayırt etmek için özel key
niteliğini kullanır ve tüm listenin her oluşturma ile değiştirilmemesini sağlar.
SolidJS'de for
ve index
yerleşik öğeleri kullanılır:
<For each={state.contacts}> {contact => <DIV>{contact.name}</DIV> } </For>
Dahili olarak, SolidJS, öğeler değiştiğinde hangi öğelerin güncelleneceğine karar vermek for
ve index
ile birlikte kendi deposunu kullanır. Sanal DOM'nin karmaşıklığından kaçınmamızı sağlayan React'ten daha açıktır.
Svelte, güncelleyicilerine göre aktarılan each
yönergeyi kullanır:
{#each contacts as contact} <div>{contact.name}</div> {/each}
Lit, React'in key
tabanlı liste eşlemesine benzer şekilde çalışan bir repeat
işlevi sağlar:
repeat(contacts, contact => contact.id, (contact, index) => html`<div>${contact.name}</div>`
Bileşen Modeli
Bu makalenin kapsamı dışında kalan bir şey, farklı çerçevelerdeki bileşen modeli ve özel HTML öğeleri kullanılarak nasıl ele alınabileceğidir.
Not : Bu büyük bir konu ve ileride bir makalede ele almayı umuyorum çünkü bu çok uzun sürecek. :)
Ücret
Çerçeveler, bildirimsel veri bağlama, kontrol akışı ilkelleri (koşullar ve listeler) ve değişiklikleri yaymak için reaktif bir mekanizma sağlar.
Ayrıca bileşenleri yeniden kullanmanın bir yolu gibi başka önemli şeyler de sağlarlar, ancak bu ayrı bir makalenin konusu.
Çerçeveler faydalı mı? Evet. Bize bu kullanışlı özelliklerin hepsini veriyorlar. Ama sorulması gereken doğru soru bu mu? Bir çerçeve kullanmanın bir bedeli vardır. Bakalım bu maliyetler neymiş.
Paket Boyutu
Paket boyutuna bakarken, küçültülmüş Gzip'd olmayan boyuta bakmayı seviyorum. JavaScript yürütmesinin CPU maliyetiyle en alakalı olan boyut budur.
- ReactDOM yaklaşık 120 KB'dir.
- SolidJS yaklaşık 18 KB'dir.
- Yanan yaklaşık 16 KB'dir.
- Svelte yaklaşık 2 KB'dir, ancak oluşturulan kodun boyutu değişiklik gösterir.
Görünüşe göre bugünün çerçeveleri, paket boyutunu küçük tutmak için React'ten daha iyi bir iş çıkarıyor. Sanal DOM, çok fazla JavaScript gerektirir.
yapılar
Bir şekilde web uygulamalarımızı “oluşturmaya” alıştık. Node.js ve Webpack gibi bir paketleyici kurmadan, Babel-TypeScript başlangıç paketindeki bazı son yapılandırma değişiklikleriyle ve tüm bu cazla uğraşmadan bir ön uç projesi başlatmak imkansız.
Çerçevenin demet boyutu ne kadar anlamlı ve küçükse, derleme araçlarının yükü ve aktarım süresi o kadar büyük olur.
Svelte, sanal DOM'nin tamamen ek yük olduğunu iddia ediyor. Katılıyorum, ancak belki "inşa etme" (Svelte ve SolidJS'de olduğu gibi) ve özel istemci tarafı şablon motorları (Lit'te olduğu gibi) de tamamen ek yüktür, farklı türden?
hata ayıklama
İnşa etme ve aktarma ile birlikte farklı bir maliyet ortaya çıkıyor.
Web uygulamasını kullandığımızda veya hata ayıklarken gördüğümüz kod, yazdıklarımızdan tamamen farklıdır. Artık web sitesinde olanları tersine mühendislik yapmak ve kendi kodumuzdaki hatalarla ilişkilendirmek için farklı kalitedeki özel hata ayıklama araçlarına güveniyoruz.
React'te çağrı yığını asla "sizin" değildir - React, zamanlamayı sizin için yönetir. Bu, hata olmadığında harika çalışıyor. Ancak sonsuz döngü yeniden işlemelerinin nedenini belirlemeye çalışın ve bir acı dünyası içinde olacaksınız.
Svelte'de, kitaplığın paket boyutu küçüktür, ancak uygulamanızın ihtiyaçlarına göre özelleştirilmiş, Svelte'nin reaktivite uygulaması olan bir dizi şifreli oluşturulmuş kodu gönderecek ve hatalarını ayıklayacaksınız.
Lit ile, daha az inşa etmekle ilgilidir, ancak etkin bir şekilde hata ayıklamak için şablon motorunu anlamanız gerekir. Çerçevelere karşı olan duygumun şüpheci olmasının en büyük nedeni bu olabilir.
Özel bildirime dayalı çözümler aradığınızda, daha acı verici zorunlu hata ayıklama ile karşılaşırsınız. Bu belgedeki örnekler, API belirtimi için TypeScript kullanır, ancak kodun kendisi aktarım gerektirmez.
Yükseltmeler
Bu belgede dört çerçeveye baktım, ancak sayamayacağım kadar çok çerçeve var (birkaç isim vermek gerekirse AngularJS, Ember.js ve Vue.js). Çerçeveye, geliştiricilerine, zihniyet paylaşımına ve ekosistemi gelişirken sizin için çalışacağına güvenebilir misiniz?
Kendi hatalarınızı düzeltmekten daha sinir bozucu olan bir şey, çerçeve hataları için geçici çözümler bulmak zorunda olmaktır. Çerçeve hatalarından daha sinir bozucu olan bir şey, bir çerçeveyi kodunuzu değiştirmeden yeni bir sürüme yükselttiğinizde ortaya çıkan hatalardır.
Doğru, bu sorun tarayıcılarda da var, ancak ortaya çıktığında herkesin başına geliyor ve çoğu durumda bir düzeltme veya yayınlanmış bir geçici çözüm yakın. Ayrıca, bu belgedeki kalıpların çoğu, olgun web platformu API'lerine dayanmaktadır; her zaman kanayan kenarla gitmeye gerek yoktur.
Özet
Veri bağlama, tepkime, koşul ve listelere odaklanarak, çerçevelerin çözmeye çalıştığı temel sorunları ve bunları nasıl çözdüklerini anlamak için biraz daha derine daldık. Maliyetine de baktık.
Kısım 2'de, bu sorunların bir çerçeve kullanmadan nasıl ele alınabileceğini ve ondan neler öğrenebileceğimizi göreceğiz. Bizi izlemeye devam edin!
Teknik incelemeler için şu kişilere özel teşekkürler: Yehonatan Daniv, Tom Bigelajzen, Benjamin Greenbaum, Nick Ribal ve Louis Lazaris.