3 poin oleh GN⁺ 2024-08-17 | 1 komentar | Bagikan ke WhatsApp

Contoh Vanilla JSX

Bagaimana jika JSX mengembalikan elemen DOM?

  • Fungsi ClickMe membuat tombol dan menampilkan jumlah klik
  • Teks diperbarui setiap kali tombol diklik
export default function ClickMe() {
  let i = 0;
  const el = Click me as HTMLButtonElement;
  el.onclick = (e) => {
    el.textContent = `Clicked ${++i} times`;
  };
  return el;
}

Dapat digunakan kembali

  • Komponen ClickMe dapat digunakan beberapa kali dengan masing-masing mempertahankan state yang berbeda
import ClickMe from "./sample1.js";
export default () =>

;

Membuat tree DOM interaktif

  • Dengan menggunakan kelas TodoInput dan TodoList, daftar tugas dapat dikelola
  • Item dapat ditambahkan dan dihapus dengan mengkliknya
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}
  ;
};

Pemrosesan data skala besar

  • Fungsi FindNames memproses dan memfilter data dalam jumlah besar lalu menampilkan hasilnya
  • Item yang cocok diperbarui secara real-time sesuai nilai input
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');
}

Pengenalan imlib

  • imlib adalah library yang dikembangkan untuk immaculatalibrary.com
  • Digunakan untuk membangun minigamemaker.com dan situs web yang sedang Anda baca sekarang
  • Library ini dikembangkan karena state yang ada sebelumnya tidak memadai, dan merupakan cara yang paling disukai untuk membuat aplikasi

Ringkasan GN⁺

  • Artikel ini menjelaskan cara membuat dan berinteraksi langsung dengan elemen DOM menggunakan JSX
  • Artikel ini menunjukkan cara memproses data dalam jumlah besar secara efisien tanpa menggunakan virtual DOM tradisional
  • Library imlib memungkinkan pengembangan aplikasi dengan cara yang sederhana dan intuitif
  • Proyek lain dengan fungsi serupa antara lain React dan Vue.js

1 komentar

 
GN⁺ 2024-08-17
Komentar Hacker News
  • Jika yang dikembalikan adalah node DOM sungguhan, maka keunggulan besar pustaka non-JSX seperti JSX dan Lit—yakni API bergaya immediate mode dan model UI=f(state)—hampir lumpuh
    Agar bisa mengevaluasi ulang templat dengan state baru dan memperbarui DOM hasil render templat itu secara efisien, yang perlu dikembalikan bukan DOM asli, melainkan deskripsi dari DOM tersebut
    Contohnya memperbarui dengan API DOM imperatif seperti input.onkeydown = ... atau this.ul.append(item), tetapi mungkin justru menghindari kode seperti ini dan melakukan iterasi item di dalam templat adalah keuntungan utama dari virtual DOM
    Namun, masalah virtual DOM adalah perhitungan diff yang lambat, dan ini bisa diatasi dengan templat yang memisahkan bagian statis dan dinamis seperti Lit

    • Dari pengalaman membuat UI web yang kompleks, menurut saya pada aplikasi yang cukup rumit, keuntungan performa virtual DOM hampir seperti ilusi
      Malah ini membuat orang berpikir, “UI besar bisa dirender ulang sesuka hati, nanti virtual DOM yang mengurus,” sehingga efeknya justru buruk; performa nyata jelek, tetapi struktur aplikasi sudah telanjur mengeras sehingga sulit diperbaiki tanpa penulisan ulang
      Saya melihat alur yang sama di tim saya, dan sebagai arsitek saya mendorong struktur vanilla yang sadar performa berdasarkan masalah yang akan ditemui di React, tetapi ditanggapi dengan sikap “ada banyak cara untuk menghindarinya”
      Pada akhirnya, dalam banyak kasus orang memang harus susah sendiri untuk belajar
    • Ini tergantung penggunanya. Dari sudut pandang lain, JSX hanyalah DSL lain untuk pola pemanggilan fungsi createElement, dan keuntungan yang dijelaskan tadi datang dari framework dan runtime
      Singkatnya, JSX adalah sintaks alternatif untuk pemanggilan fungsi yang punya kegunaan tertentu
      Di perusahaan lama, kami memakai JSX untuk factory data pengujian; tampilannya seperti XML, tetapi pada tahap pembuatan elemen kami bisa membuat keputusan kontekstual yang sesuai dengan data akhir lewat builder pattern
      Ini tidak ada hubungannya dengan React atau DOM, dan juga bukan berarti hal seperti itu tidak bisa diekspresikan secara deklaratif tanpa JSX
    • “Apa yang diinginkan” itu berbeda tergantung siapa yang ditanya. Secara pribadi, saya lebih suka memperbarui node DOM langsung di tempat tanpa semua mekanisme reconciliation
    • Saya paham impian “tidak perlu lagi melakukan pembaruan imperatif”. Saya sudah memakai framework seperti ini sekitar 10 tahun dan sangat terbiasa dengannya
      Secara pribadi, saya lebih suka memperbarui DOM secara imperatif. Dengan begitu saya bisa mengendalikan dengan sangat rinci apa yang terjadi, dan bisa merancang struktur yang sangat efisien
      Saya juga bisa membuat aplikasi mudah ditambah, diubah, dihapus, dan diperbaiki fiturnya tanpa harus memaksakan cara berpikir mengikuti metodologi kuat milik orang lain
    • Saya setuju bahwa jika mengembalikan node DOM sungguhan maka keunggulan pustaka non-JSX seperti JSX dan Lit—API bergaya immediate mode dan model UI=f(state)—menjadi melemah, tetapi ini terasa seperti salah satu abstraksi yang bocor paling parah di seluruh dunia komputasi
      Ada alasan kenapa di sekitar React muncul ekosistem tentang cara agar rendering tidak terjadi berkali-kali dan cara mencegah refresh yang tidak perlu
  • Saya membuat proyek ini karena merasa frustrasi dengan keadaan static site generator selama 10 tahun terakhir
    Karena saya kebanyakan membuat situs web statis, saya menginginkan alat yang sederhana dan intuitif, dan JSX tampak cocok, tetapi saya lelah dengan kompleksitas berlebihan dari framework JSX seperti React
    Karena itu saya membuat static site generator yang merender JSX menjadi string, dan memperluasnya ke sisi browser agar JSX dirender menjadi elemen DOM terasa alami
    Dalam beberapa kasus, terutama untuk layout, ini juga cocok untuk komponen bersama. Secara keseluruhan saya puas dengan hasilnya, tetapi beberapa bagian cukup hacky dan dukungan IDE juga masih bisa lebih baik
    Selain itu, pendekatan ini juga cocok untuk SEO. Ini masalah yang rasanya belum benar-benar terselesaikan dengan baik di framework JSX lain

    • Penasaran apakah Anda sudah melihat Astro. Rasanya seperti static site generator yang nyaris sempurna, walau mungkin ada kekurangan lain yang diselesaikan oleh VanillaJSX
    • Idenya bagus. Di halaman demo, aplikasi to-do menampilkan 404
      Di dokumentasi, sepertinya lebih baik menuliskan “static site generator” lengkap daripada “SSG”. Meski pernah memakai static site generator, saya tetap tidak tahu apa itu SSG sampai harus bertanya ke AI
    • Akan keren kalau ada JSX untuk sisi server Django
    • Penasaran apakah Anda sudah melihat lit-html
      Saya datang dari Vue dan cukup terkejut karena lit-html bisa melakukan banyak hal yang dilakukan templat Vue, termasuk pengaitan event, hanya dengan templat vanilla JS yang sederhana
      Jika memakai ekstensi lit di VSCode, Anda juga bisa mendapatkan syntax highlighting dan pemeriksaan tipe penuh bahkan di dalam templat
      Saya tahu soal ini setelah Marc Grabanski menulis tweet bahwa dia memakai lit-html bersama vanillajs, bukan Lit, dan setelah saya coba sendiri, hasilnya bekerja sangat baik. Ini tampak sangat mirip dengan yang sedang Anda coba selesaikan
      Dengan paket templat lit-html, Anda bisa melakukan sebagian besar hal yang dijelaskan di bagian templat: https://lit.dev/docs/templates/overview/
      Ini juga bisa dilakukan tanpa abstraksi komponen lit-element: https://lit.dev/docs/libraries/standalone-templates/#renderi...
  • Alasan “bagaimana jika” seperti ini terasa menarik adalah karena asal-usul JSX bisa ditelusuri kembali hingga XHP milik Facebook, dan XHP secara eksplisit terinspirasi oleh standar JS awal E4X, yang terlihat dan bekerja mirip dengan library yang dijelaskan di sini
    [1] https://engineering.fb.com/2010/02/09/developer-tools/xhp-a-...
    [2] https://en.m.wikipedia.org/wiki/ECMAScript_for_XML

    • E4X punya kelemahan yang sayangnya mengembalikan instance DOM nyata, jadi pembaruannya harus dilakukan secara imperatif
      Itulah juga alasan JSX bisa melampaui E4X, dan setelah itu tidak ada lagi usulan serius untuk template HTML di dalam JS
      Meski begitu, tampaknya ide umumnya masih bisa dihidupkan kembali dengan sentuhan modern: https://github.com/WICG/webcomponents/issues/1069
    • Fakta menariknya, alasan JavaScript akhirnya memakai for(of) alih-alih for each adalah karena E4X
      Alasan kita tidak mendapatkan for (:) bahkan lebih konyol, karena itu bisa berbenturan dengan anotasi :type yang diyakini beberapa anggota TC39 akan suatu hari masuk ke bahasa tersebut secara ajaib
  • Pernah ada yang membuat library UI dengan gagasan bahwa ekspresi template JSX benar-benar membuat node DOM nyata
    Dengan mengikat objek model ke properti, sebagian boilerplate event handler imperatif juga bisa dihilangkan. Seperti yang bisa diduga, menurut saya itu ide yang bagus
    https://github.com/tomtheisen/mutraction
    Kita bisa menulis kode seperti membuat model dengan track({ clicks: 0 }), lalu saat diklik menambah model.clicks dan langsung mencerminkan nilainya ke DOM

  • VanJS juga layak disebut di sini: https://vanjs.org/
    Library JSX lain seperti Solid.JS juga mengembalikan node DOM, dan bagus melihat ide seperti ini mulai mendapat dukungan
    Menurut saya, semakin dekat ke platform yang kita pakai, semakin baik. Lapisan abstraksi kadang memang berguna, tetapi sejauh ini saya belum benar-benar menemukan kebutuhan untuk menyembunyikan platformnya
    Proyek raksasa seperti milik Facebook mungkin bisa mendapat manfaat, tetapi saya belum pernah bekerja pada skala seperti itu

    • Dalam perbandingan ukuran bundle, bukankah SolidJS jadi kurang bermakna?
  • Contoh-contohnya memang keren, tetapi tampaknya penting bahwa mereka tidak menunjukkan props komponen yang bisa berubah seiring waktu
    Kemampuan seperti itu tampaknya memang tidak dimodelkan. Jika memang tidak diperlukan, ini pendekatan yang cerdas, tetapi saya kurang bisa membayangkan bagaimana ia berkembang ke aplikasi yang lebih kompleks

    • Teknik yang dipakai di sini dan di semua kode sisi browser persis sama dengan cara yang dipakai di internal VS Code, dan skalanya berjalan cukup baik
      Bedanya cuma penulisan 10 baris kode untuk membuat dan mengatur elemen DOM dengan cara biasa menjadi lebih ringkas
      Sebenarnya, bagian yang benar-benar menarik dari framework ini justru hampir semua hal selain itu. Ada JSX yang mengembalikan string di sisi static site generator, mengambil direktori sumber mentah lalu memanipulasi string|Buffer saat tahap SSG, serta sistem modul yang sangat efisien dan cepat buatan sendiri di atas chokidar dan swc
      Bagian memakai JSX sebagai DOM memang paling mencolok secara visual, tetapi sebenarnya lebih mirip trik pesta
      Sebagai contoh, source vanillajsx.com sangat ringkas, jelas, dan pendek. Semuanya ditulis hari ini tanpa dependensi selain imlib, dan demo JSX-as-DOM justru bagian yang paling tidak inovatif: https://github.com/sdegutis/vanillajsx.com/tree/main/site
    • Untuk membawa pendekatan ini ke skala nyata dan yakin semuanya bekerja bersama seperti yang diharapkan, dibutuhkan lapisan reaktivitas yang benar-benar matang
      Jika Anda menyukai pendekatan JSX yang mengembalikan elemen DOM konkret seperti ini, Solid bekerja persis seperti itu, hanya saja ditambah lapisan reaktivitas yang layak
    • Mungkin saya melewatkan sesuatu, tetapi saya tidak paham bagaimana pendekatan ini mencegah penggunaan setTimeout atau setInterval
      Meski begitu, saya setuju bahwa proyek semacam ini sering bekerja baik untuk kasus penggunaan kecil, tetapi cepat runtuh dalam skenario “dunia nyata”
    • Saya bukan membela library ini dan juga tidak berencana memakainya, tetapi kalau ingin perubahan props memicu render ulang seperti di React/Vue, tampaknya di sini bisa memakai JS Proxy
      Implementasinya sepertinya tidak terlalu sulit
  • Ini sangat mirip dengan Vanilla TSX: https://github.com/wisercoder/uibuilder
    Contoh aplikasi yang ditulis dengan Vanilla TSX ada di sini: https://github.com/wisercoder/eureka/tree/master/webapp/Clie...

  • Ini mengingatkan pada ActionScript 3, yang memiliki XML di inti bahasanya
    Itu bahasa yang menyenangkan untuk ditulis, tetapi terkenal gagal menjadi ES4. Pada akhirnya, butuh lebih dari 10 tahun untuk sampai ke titik serupa lewat TypeScript dan JSX

    • https://en.wikipedia.org/wiki/ECMAScript_for_XML — Firefox juga pernah memilikinya, tetapi publik tidak menginginkannya dan akhirnya fitur itu dihapus
      Fitur itu dinonaktifkan untuk halaman web di Firefox 17, 6 bulan sebelum rilis pertama React
    • Saya tidak ingat pernah bisa membuat XML inline seperti ini. Mungkin itu bisa dilakukan kalau merupakan fitur sisi server di Flex
  • Penasaran apakah ada orang lain yang juga mengalami contoh terakhir tidak berjalan di Firefox. Di Edge berhasil, tapi di Firefox gagal
    Uncaught (in promise) TypeError: Map.groupBy(...).entries().map is not a function

  • Saya kurang paham kenapa JSX lebih menarik dibanding dipakai seperti di bawah ini
    h("div", {}, [ h("p", {}, "this is easy"), ...list.map((l) => h("li", {}, l)) ])
    Dengan begini, kita otomatis mendapatkan loop dan interpolasi variabel tanpa perlu compiler dan tanpa membuat sintaks baru. Akan bagus kalau ada yang bisa menjelaskan

    • Banyak orang kemungkinan merasa versi JSX jauh lebih mudah dibaca dan lebih familier. Tentu ini soal selera
      Kalau mau adil, di JSX pun loop biasa dan interpolasi tetap dipakai apa adanya. {} menerima ekspresi JS biasa
      Hanya saja, dibutuhkan tahap kompilasi untuk menguraikan tag elemen menjadi pemanggilan createElement
    • Secara pribadi, saya sulit memahami orang yang melihat kode yang Anda tempel itu lalu menganggapnya sama bagusnya dengan JSX
      Cara tiap orang memproses informasi memang berbeda, tetapi contoh itu penuh tanda baca sehingga sangat sulit dipahami dengan cepat
      Tanpa mengurai sintaksnya sendiri di kepala, struktur DOM yang dihasilkan tidak terlihat, dan bisa memahami struktur DOM sepintas jauh lebih penting daripada perlu compiler atau tidak
      Sebagai catatan, saya neurodivergen, dan semoga penjelasan ini membantu
    • Kalau terus masuk ke lubang kelinci logika itu, ujung-ujungnya akan sampai ke Common Lisp
    • Saya juga pernah memikirkan hal yang sama. Salah satu kelebihannya tampaknya adalah karena bentuknya mirip HTML
      Mirip dengan yang terlihat di alat pengembang browser, jadi lebih mudah dibandingkan dan di-debug
    • Untuk satu file atau aplikasi sederhana, gaya seperti itu tidak masalah
      Tetapi di aplikasi kompleks, saat komponen menjadi ratusan dan mulai saling diimpor dan dipakai, menulis dengan tag JSX terasa seperti sintaks yang sederhana dan mudah dipahami
      Penolakan terhadap React juga pada akhirnya sering muncul karena terasa berlebihan untuk hal-hal sederhana, dan memang berlebihan
      Namun aplikasi yang dibuat tiap orang, tingkat kompleksitasnya, dan kebutuhannya berbeda-beda, jadi tidak bisa disederhanakan dengan mengatakan salah satunya lebih menarik. Ini adalah alat yang berbeda untuk masalah yang berbeda