3 puan yazan GN⁺ 2024-08-17 | 1 yorum | WhatsApp'ta paylaş

Vanilla JSX örnekleri

JSX DOM öğeleri döndürürse?

  • ClickMe fonksiyonu bir düğme oluşturur ve tıklama sayısını gösterir
  • Düğmeye her tıklandığında metin güncellenir
export default function ClickMe() {
  let i = 0;
  const el = Click me as HTMLButtonElement;
  el.onclick = (e) => {
    el.textContent = `Clicked ${++i} times`;
  };
  return el;
}

Yeniden kullanılabilirlik

  • ClickMe bileşeni birden çok kez kullanılarak her birinin farklı durumunu koruması sağlanabilir
import ClickMe from "./sample1.js";
export default () =>

;

Etkileşimli DOM ağacı oluşturma

  • TodoInput ve TodoList sınıfları kullanılarak yapılacaklar listesi yönetilebilir
  • Öğeler eklenebilir ve tıklanarak kaldırılabilir
function TodoInput(attrs: { add: (v: string) => void }) {
  const input =  as HTMLInputElement;
  input.placeholder = 'Add todo item...';
  input.onkeydown = (e) => {
    if (e.key === 'Enter') {
      attrs.add(input.value);
      input.value = '';
    }
  };
  return input;
}

class TodoList {
  ul =  as HTMLUListElement;
  add(v: string) {
    const item =
- {v}
 as HTMLLIElement;
    item.onclick = () => item.remove();
    this.ul.append(item);
  }
}

export default () => {
  const list = new TodoList();
  list.add('foo');
  list.add('bar');
  return
     list.add(v)} />
    {list.ul}
  ;
};

Büyük veri işleme

  • FindNames fonksiyonu büyük miktarda veriyi işleyip filtreleyerek sonuçları gösterir
  • Girilen değere göre eşleşen öğeler gerçek zamanlı olarak güncellenir
import { data } from "../fetch-dataset.js";
export default function FindNames() {
  const status =  as HTMLParagraphElement;
  const results =  as HTMLUListElement;
  const input =  as HTMLInputElement;
  updateMatches();

  function updateMatches() {
    const matched = (data.entries().filter(([k]) => k.match(input.value)).toArray());
    const matches = (Iterator.from(matched).map(match => ).take(30));
    results.replaceChildren(...matches);
    status.textContent = `${matched.length} / ${data.size}`;
  }

  return
    {input}
    {status}
    {results}

;
}

function Item(attrs: { match: [string, number], regex: string }) {
  const [name, count] = attrs.match;
  const total = ({count});
  return
-
     {total}

;
}

function highlight(str: string, regex: string) {
  if (!regex) return str;
  const r = new RegExp(`(${regex})`, 'gi');
  return str.replace(r, '$1');
}

imlib'e giriş

  • imlib, immaculatalibrary.com için geliştirilen bir kütüphanedir
  • minigamemaker.com'u ve şu anda okumakta olduğunuz web sitesini oluşturmak için kullanılmıştır
  • Mevcut durum yönetimi yeterli gelmediği için geliştirildi ve uygulama oluşturmanın en çok tercih edilen yoludur

GN⁺ özeti

  • Bu yazı, JSX kullanarak DOM öğelerini doğrudan oluşturup etkileşime sokma yöntemini açıklıyor
  • Geleneksel sanal DOM kullanmadan da büyük veriyi verimli şekilde işleme yaklaşımı sunuyor
  • imlib kütüphanesi, uygulama geliştirmeyi basit ve sezgisel bir hale getiriyor
  • Benzer işlevlere sahip diğer projeler arasında React ve Vue.js bulunuyor

1 yorum

 
GN⁺ 2024-08-17
Hacker News yorumları
  • Gerçek DOM düğümleri döndürmek, JSX’in ve Lit gibi JSX olmayan kütüphanelerin büyük avantajı olan immediate mode tarzı API’yi ve UI=f(state) modelini neredeyse etkisiz bırakır
    Gerçek DOM değil, DOM’un bir tanımını döndürmek gerekir ki şablon yeni durumla tekrar tekrar değerlendirilebilsin ve bu şablonun render edildiği DOM verimli biçimde güncellenebilsin
    Örnekler input.onkeydown = ... veya this.ul.append(item) gibi imperatif DOM API’leriyle güncelleme yapıyor; oysa bu tür kodlardan kaçınmak ve öğeler üzerinde şablon içinde dönmek, sanal DOMun başlıca faydası olabilir
    Ancak sanal DOM’un sorunu diff hesaplamasının yavaş olması; bu da Lit’te olduğu gibi statik ve dinamik kısımları ayıran şablonlarla çözülebilir

    • Karmaşık web UI’leri geliştirmiş biri olarak, yeterince karmaşık uygulamalarda sanal DOM performans avantajının neredeyse bir yanılsama olduğunu düşünüyorum
      Aksine, “büyük bir UI’yi istediğim gibi yeniden render etsem de sanal DOM halleder” diye düşündürerek ters etki yaratıyor; gerçek performans kötüleşirken uygulama yapısı da yeniden yazmadan düzeltilmesi zor olacak şekilde katılaşıyor
      Dört ekipte aynı gidişatı gördüm; mimar olarak React’te yaşanacak sorunları gerekçe gösterip performansı gözeten vanilla bir yapı önermiştim, ama “kaçınmanın birçok yolu var” denerek kabul görmedi
      Sonunda çoğu durumda insanların bunu bizzat zorlanarak öğrenmesi gerekiyor gibi
    • Bu kullanıcıya göre değişir. Başka bir açıdan bakınca JSX, createElement fonksiyon çağrısı kalıbı için başka bir DSL’den ibarettir; anlattığınız faydalar framework ve runtime’dan gelir
      Daha kısa söylersek JSX, faydalı kullanım alanları olan alternatif bir fonksiyon çağrısı söz dizimidir
      Eski şirketimde JSX’i test verisi factory’lerinde kullanıyorduk; XML gibi görünse de öğe oluşturma aşamasında builder pattern ile nihai veriye uygun bağlamsal kararlar alabiliyorduk
      React ya da DOM ile ilgisi yoktu; bu, JSX olmadan deklaratif ifade edilemeyeceği anlamına da gelmiyordu
    • “İstenen şey” kime sorduğunuza bağlı. Şahsen, tüm reconciliation mekanizmaları olmadan DOM düğümlerini yerinde güncellemeyi tercih ederim
    • “Artık imperatif güncellemeler yapmak zorunda kalmama” hayalini anlıyorum. Bu tür framework’leri yaklaşık 10 yıldır kullanıyorum ve gayet alışığım
      Şahsen DOM’u imperatif olarak güncellemeyi daha çok seviyorum. Ne olduğunu çok ince ayrıntısına kadar kontrol edebiliyor ve çok verimli yapılar tasarlayabiliyorum
      Birinin katı metodolojisine göre düşünmek zorunda kalmadan uygulamaya özellik eklemeyi, değiştirmeyi, kaldırmayı ve düzeltmeyi kolaylaştırabiliyorum
    • Gerçek DOM düğümleri döndürmenin, JSX’in ve Lit gibi JSX olmayan kütüphanelerin avantajı olan immediate mode tarzı API’yi ve UI=f(state) modelini zayıflattığına katılıyorum; ama bu, tüm bilişim alanındaki en sızdıran soyutlamalardan biri gibi hissettiriyor
      React etrafında render’ı birden çok kez yapmamanın, gereksiz yenilemeleri engellemenin yollarına dair bir ekosistem oluşmasının bir nedeni var
  • Son 10 yılda statik site oluşturucularının durumundan bunaldığım için bu projeyi yaptım
    Çoğunlukla statik web siteleri yaptığım için basit ve sezgisel araçlar istiyordum; JSX uygun görünüyordu, ama React gibi JSX framework’lerinin aşırı karmaşıklığından yorulmuştum
    Bu yüzden JSX’i string’e render eden bir statik site oluşturucu yaptım; bunu tarayıcı tarafına genişletip JSX’i DOM öğelerine render ettirmek de doğal bir adımdı
    Bazı durumlarda, özellikle layout’larda, paylaşılan component’ler için de iyi uyuyor. Genel olarak ortaya çıkan sonuçtan memnunum, ama bazı kısımlar epey hacky ve IDE desteği de daha iyi olabilir
    Ayrıca bu yöntem SEO için de iyi uyuyor. Diğer JSX framework’lerinde düzgün çözüldüğünü hissetmediğim bir konuydu

    • Astro’ya baktınız mı merak ediyorum. Bana kusursuz bir statik site oluşturucu gibi geliyor; yine de VanillaJSX’in çözdüğü başka eksiklikler olmuş olabilir
    • Fikir güzel. Demo sayfasındaki yapılacaklar uygulaması 404 veriyor
      Dokümantasyonda “SSG” yerine “static site generator” diye açık yazmak daha iyi olabilir. Statik site oluşturucu kullanmış olmama rağmen SSG’nin ne olduğunu bilmiyordum ve yapay zekaya sormak zorunda kaldım
    • Django server-side için JSX olsa harika olurdu
    • lit-html’e baktınız mı merak ediyorum
      Vue’dan gelmiş biri olarak şaşırdım; lit-html, yalnızca basit vanilla JS şablonlarıyla, event bağlama dahil Vue şablonlarının yaptığı birçok şeyi yapıyor
      VSCode lit eklentisini kullanınca şablon içinde de syntax highlighting ve tam type checking alabiliyorsunuz
      Marc Grabanski’nin Lit değil, vanillajs ile birlikte lit-html kullandığını tweet’lemesinden sonra öğrendim; kendim deneyince de çok iyi çalıştığını gördüm. Şu anda çözmeye çalıştığınız şeye oldukça benziyor
      lit-html şablon paketini kullanırsanız şablon bölümünde anlatılanların çoğunu yapabilirsiniz: https://lit.dev/docs/templates/overview/
      lit-element’in component soyutlaması olmadan da mümkün: https://lit.dev/docs/libraries/standalone-templates/#renderi...
  • Bu tür “ya öyle olsaydı”ların eğlenceli olmasının nedeni, JSX’in kökeninin Facebook’un XHP’sine kadar izlenebilmesi; XHP’nin de burada anlatılan kütüphaneye benzer görünüp davranan erken dönem JS standardı E4X’ten açıkça esinlenmiş olması
    [1] https://engineering.fb.com/2010/02/09/developer-tools/xhp-a-...
    [2] https://en.m.wikipedia.org/wiki/ECMAScript_for_XML

    • E4X’in talihsiz dezavantajı gerçek DOM örnekleri döndürmesiydi; bu yüzden emirsel olarak güncellenmeleri gerekiyordu
      JSX’in E4X’in ötesine geçmesinin nedeni de buydu ve sonrasında JS içinde HTML şablonları için ciddi bir öneri çıkmadı
      Yine de genel fikri modernleştirip yeniden canlandırmak mümkün gibi görünüyor: https://github.com/WICG/webcomponents/issues/1069
    • İlginç bir bilgi: JavaScript’e for each yerine for(of) girmesinin nedeni E4X’tir
      for (:) elde edemememizin nedeni daha da saçma: Bazı TC39 üyeleri, bir gün dile sihirli biçimde geleceğine inandıkları :type açıklamalarıyla çakışabileceğini düşünüyordu
  • JSX şablon ifadelerinin gerçek DOM düğümleri oluşturması fikriyle bir UI kütüphanesi yapmıştım
    Model nesnelerini özelliklere bağlayarak emirsel event handler kalıp kodunun bir kısmını da ortadan kaldırıyor. Tahmin edileceği gibi, bunun iyi bir fikir olduğunu düşünüyorum
    https://github.com/tomtheisen/mutraction
    track({ clicks: 0 }) ile bir model oluşturup tıklamada model.clicks değerini artıran ve bu değeri doğrudan DOM’a yansıtan kodlar yazılabiliyor

  • Burada VanJS’den de bahsetmeye değer: https://vanjs.org/
    Solid.JS gibi başka JSX kütüphaneleri de DOM düğümleri döndürüyor; bu fikrin ivme kazanması hoşuma gidiyor
    Kullandığımız platforma ne kadar yakın olursak o kadar iyi olduğunu düşünüyorum. Soyutlama katmanları kimi zaman yararlı olabilir ama pratikte platformu gizlememiz gereken bir durumu hâlâ bulamadım
    Facebook gibi devasa projeler bundan fayda görebilir, ama ben o ölçekte çalışmadım

    • Bundle boyutu karşılaştırmasında SolidJS pek anlamlı değil gibi değil mi?
  • Örnekler harika, ancak zamanla değişebilecek bileşen props’larını göstermemeleri önemli görünüyor
    Böyle bir yetenek sanki hiç modellenmemiş. Buna ihtiyaç yoksa zekice bir yaklaşım, ama daha karmaşık uygulamalara nasıl ölçekleneceğini pek göremiyorum

    • Burada ve tüm tarayıcı tarafı kodunda kullanılan teknik, VS Code içinde kullanılan yöntemle birebir aynı ve gayet iyi ölçekleniyor
      Fark yalnızca, DOM öğelerini alışılagelmiş şekilde oluşturup ayarlayan 10 satırlık kodun daha özlü yazılması
      Aslında bu framework’te gerçekten ilginç olan kısım bunun dışındaki neredeyse her şey. Statik site üreticisi tarafında JSX’in string döndürmesi, ham kaynak dizinini alıp SSG sırasında string|Buffer üzerinde işlem yapılması, chokidar ve swc üzerinde kurulmuş, kendi yazdığım son derece verimli ve hızlı modül sistemi gibi şeyler var
      JSX’i DOM olarak kullanma kısmı görsel olarak en dikkat çekeni, ama gerçekte daha çok bir gösteri numarası
      Örneğin vanillajsx.com’un kaynak kodu çok özlü, açık ve kısa. imlib dışında bağımlılığı olmadan bugün tek günde tamamını yazdım; JSX-as-DOM demosu en az yenilikçi bölüm: https://github.com/sdegutis/vanillajsx.com/tree/main/site
    • Bu yaklaşımı gerçek ölçekte büyütmek ve her şeyin beklendiği gibi birlikte çalıştığından emin olmak için düzgün bir reaktivite katmanı gerekiyor
      JSX’in somut DOM öğeleri döndürdüğü bu yaklaşımı seviyorsanız Solid tam olarak böyle çalışıyor ve buna düzgün bir reaktivite katmanı ekliyor
    • Bir şeyi kaçırıyor olabilirim ama bu yaklaşımın setTimeout veya setInterval kullanımını nasıl engellediğini anlamıyorum
      Yine de bu tür projelerin küçük kullanım senaryolarında iyi çalıştığı, fakat “gerçek dünya” senaryolarında çoğu zaman hızla dağıldığı konusunda hemfikirim
    • Bu kütüphaneyi savunuyor da değilim, kullanmayı da planlamıyorum; ancak props değişikliklerinin React/Vue’daki gibi yeniden render tetiklemesini istiyorsanız burada JS Proxy kullanılabilir gibi görünüyor
      Uygulaması o kadar zor olmayabilir
  • Bu, Vanilla TSX’e çok benziyor: https://github.com/wisercoder/uibuilder
    Vanilla TSX ile yazılmış bir uygulama örneği burada: https://github.com/wisercoder/eureka/tree/master/webapp/Clie...

  • Dilin çekirdeğinde XML bulunan ActionScript 3’ü hatırlatıyor
    Yazması eğlenceli bir dildi ama ES4 olma konusunda malum şekilde başarısız oldu. Sonunda TypeScript ve JSX ile benzer bir noktaya varmamız 10 yıldan fazla sürmüş oldu

    • https://en.wikipedia.org/wiki/ECMAScript_for_XML — Firefox’ta da vardı, ama kitleler bunu istemedi ve sonunda kaldırıldı
      React’in ilk sürümünden 6 ay önce, Firefox 17’de web sayfaları için devre dışı bırakılmıştı
    • XML’i bu şekilde inline oluşturabildiğimizi hatırlamıyorum. Belki Flex’in sunucu tarafı özelliğiyse mümkün olmuş olabilir
  • Son örneğin Firefox’ta çalışmadığı başka biri var mı merak ediyorum. Edge’de çalıştı ama Firefox’ta başarısız oldu
    Uncaught (in promise) TypeError: Map.groupBy(...).entries().map is not a function

  • JSX’in aşağıdaki gibi yazmaktan neden daha çekici olduğunu pek anlayamıyorum
    h("div", {}, [ h("p", {}, "this is easy"), ...list.map((l) => h("li", {}, l)) ])
    Böyle yapınca derleyici ve yeni söz dizimi oluşturmaya gerek kalmadan döngüleri ve değişken yerleştirmeyi vb. otomatik olarak elde ediyorsunuz. Biri açıklarsa sevinirim

    • Birçok kişinin JSX sürümünü çok daha okunabilir ve alışıldık bulacağını düşünüyorum. Tabii bu bir zevk meselesi
      Adil olmak gerekirse JSX’te de normal döngüler ve yerleştirme aynen kullanılıyor. {} vanilla JS ifadeleri alıyor
      Sadece öğe etiketlerini createElement çağrılarına açan bir derleme adımı gerekiyor
    • Kişisel olarak, eklediğin koda bakıp bunun JSX kadar iyi olduğunu düşünen insanları pek anlayamıyorum
      Herkes bilgiyi farklı işliyor olabilir ama o örnekte noktalama işaretleri çok fazla olduğu için hızlıca kavramak çok zor
      Söz dizimini zihninde bizzat ayrıştırmadan oluşacak DOM yapısı görünmüyor; derleyici gerekip gerekmediğinden çok DOM yapısını bir bakışta anlamak çok daha önemli
      Not olarak, nöroçeşitlilik sahibi biriyim ve umarım bu açıklama yardımcı olur
    • Bu mantığın tavşan deliğinden inmeye devam edersen sonunda Common Lisp’e varırsın
    • Ben de aynı şeyi düşünmüştüm. Bir avantajı HTML’e benzemesi gibi geliyor
      Tarayıcı geliştirici araçlarında gördüğüne benzediği için karşılaştırması ve hata ayıklaması kolay
    • Tek dosyalık ya da basit bir uygulama için o tarz da gayet iyi
      Ama karmaşık bir uygulamada bileşen sayısı yüzlere çıkıp birbirlerini içe aktarıp kullanmaya başladığında, JSX etiketleriyle yazma biçimi sade ve anlaşılır bir söz dizimi gibi geliyor
      React’e yönelik tepkinin önemli bir kısmı da sonuçta basit işler için aşırı kaçmasından kaynaklanıyor; gerçekten de aşırı
      Ama herkesin yaptığı uygulama, karmaşıklık ve ihtiyaçlar farklı olduğundan, bir tarafın daha çekici olduğunu basitleştirerek söyleyemeyiz. Farklı problemler için farklı araçlar bunlar