2 poin oleh GN⁺ 2024-04-05 | 1 komentar | Bagikan ke WhatsApp
  • Tim Sequin mencoba baik React SPA maupun Phoenix LiveView murni, lalu menyimpulkan bahwa pendekatan paling produktif adalah menggabungkan LiveView dan Svelte dengan LiveSvelte
  • LiveView dapat membuat UI kaya tanpa SPA melalui status server dan pembaruan DOM inkremental, tetapi saat status klien dibutuhkan, modul JS, hook, dan status LiveView mulai bercampur sehingga batasnya menjadi kabur
  • Dalam LiveView murni, LiveView, LiveComponent, dan Component memiliki siklus hidup, cara meneruskan props, dan metode komunikasi yang berbeda, sehingga refactoring dan penempatan status lebih merepotkan dibanding React
  • LiveSvelte menyediakan batas dua arah yang jelas: Elixir menurunkan props dan Svelte mengirim event ke atas melalui live.pushEvent
  • Dalam kombinasi ini, routing, logika bisnis, dan persiapan data tetap di server, sementara status UI, animasi, dan conditional rendering ditangani oleh Svelte sehingga kompleksitas SPA bisa dikurangi

Model pengembangan yang disediakan LiveView

  • Aplikasi server-rendering tradisional membuat server tidak menyimpan status, dan merender halaman untuk setiap permintaan klien
  • SPA menyerahkan penyusunan halaman ke klien, membaca dan menulis data melalui API backend, serta mengelola status klien dengan pendekatan seperti useState di React
  • LiveView tetap membuat server menangani rendering halaman sambil mempertahankan status, lalu memproses aksi frontend dan memperbarui DOM secara inkremental seperti SPA
  • Kompleksitas SPA membesar karena aplikasi JS di klien pada praktiknya bertindak seperti sebuah microservice frontend
    • Route dan controller backend bertambah karena kebutuhan khusus frontend
    • Satu permintaan bisa melewati onMount, pemanggilan API, parsing respons, router, auth plug, controller, fungsi domain, dan lapisan persiapan respons
  • Keunggulan LiveView adalah dapat menghadirkan pengalaman klien yang kaya tanpa microservice frontend
    • Query database bisa dilakukan dekat dengan fungsi rendering tabel
    • Saat baris baru masuk, baris itu bisa di-push ke tabel dan LiveView akan memperbarui klien
    • Ini memungkinkan interaksi yang lebih dekat ke framework frontend stateful dibanding pendekatan server-rendering lama yang membangun ulang seluruh status pada tiap request

Gesekan yang ditemui di LiveView murni

  • Status sisi klien tidak bisa benar-benar dihindari

    • LiveView tidak bisa menghindari latensi bolak-balik antara server dan pengguna
    • Animasi, tooltip, tampil/sembunyi DOM, atau menonaktifkan field formulir kadang harus ditangani di klien
    • Pada formulir dengan dua dropdown yang saling bergantung, UX yang baik mengharuskan dropdown kedua langsung dinonaktifkan setelah pilihan di dropdown pertama berubah, lalu diaktifkan kembali setelah server mengisi daftar baru
    • Untuk menerapkan perilaku ini hanya dengan LiveView, beberapa konsep perlu dipakai bersama
      • JS module milik LiveView dipakai untuk menonaktifkan dropdown kedua saat dropdown pertama berubah
      • hook dipakai untuk mendaftarkan event listener pada dropdown kedua dan menerima aksi pengaktifan kembali dari backend
      • Jika pengaktifan kembali bersifat kondisional, status LiveView juga bisa ikut terlibat
    • Saat JS, hook, dan status LiveView dipakai bersama, sebagian status DOM berada di luar LiveView sehingga sulit menemukan pola yang konsisten
  • Batas status yang berbeda dari React

    • React menangani sebagian besar transisi dengan konsep inti status dan aksi, sehingga batas antara status DOM dan status komponen relatif jelas
    • Karena tidak ada latensi antara aksi klien dan status klien, React bisa memperlakukan aksi dan transisi dengan paradigma status
    • Status LiveView berada di sisi server, jadi latensi antara aksi klien dan status server harus diperhitungkan
    • Pada contoh field input, React melewati jalur status sebelum karakter diketik, dan komponen dirender ulang pada setiap penekanan tombol
    • LiveView lebih dekat ke model di mana pengguna lebih dulu mengubah field input, lalu beberapa saat kemudian status server mengetahuinya dan bereaksi
    • Jika latensi nyaris nol, perilakunya terlihat seperti React, tetapi makin besar latensinya makin jelas perbedaan kedua model tersebut

Kompleksitas yang diciptakan oleh tiga jenis komponen

  • LiveView memiliki tiga jenis komponen: LiveViews, LiveComponents, dan Components
  • LiveViews dan LiveComponents lebih mirip komponen stateful di React, sedangkan Components lebih mirip komponen fungsional
  • LiveView selalu menjadi komponen induk tingkat atas, dan di bawahnya dirender LiveComponents serta Components
  • Di React, cukup menambah atau menghapus hook useState untuk berpindah dengan mudah antara komponen stateful dan komponen fungsional
    • Keduanya menerima props dengan cara yang sama
    • Selain status, set fitur keduanya sama
    • Pendaftaran event DOM dan cara meresponsnya juga sama
  • Di LiveView, perbedaan antar tiga jenis komponen ini cukup besar sehingga merefaktor LiveView menjadi LiveComponent terasa merepotkan
    • LiveViews dan LiveComponents memakai sintaks rendering dan penerusan props yang berbeda
    • Siklus hidupnya berbeda
    • Opsi komunikasinya berbeda: LiveViews memakai send, sedangkan LiveComponents memakai send_update
    • LiveComponents bukan proses, jadi tidak bisa berinteraksi dengan bagian lain sistem seperti LiveViews

Batasan LiveComponent

  • LiveView adalah sebuah proses Elixir, sehingga memiliki pid, status, inbox, dan bisa bertindak seperti proses lain dalam sistem Elixir/OTP
  • Di LiveView, pub/sub bisa dipakai untuk berlangganan perubahan di seluruh sistem
  • LiveComponent bukan proses tersendiri, melainkan modul yang dipanggil oleh LiveView
  • Karena proses LiveView induk memegang status komponen turunannya, LiveView juga harus menangani routing pesan untuk child LiveComponents
  • Agar LiveComponents memiliki kemampuan mandiri untuk mengelola status dan menangani aksi, masing-masing harus berupa proses, tetapi model saat ini bukan seperti itu
  • Dalam pengembangan nyata, sering kali tidak ada cara yang baik untuk mengirim event atau aksi ke LiveComponent, dan menjadi tidak jelas apakah send_update seharusnya dipakai untuk mengirim aksi atau menambal status
    • Jika dipakai untuk menambal status, maka perlu dipikirkan juga bagaimana membedakan mount dan update di dalam klausa update

Batas yang dibentuk LiveSvelte

  • LiveSvelte memungkinkan komponen Svelte dirender di dalam LiveView
  • Di dalam render LiveView, struktur data Elixir bisa di-encode menjadi plain map untuk frontend lalu diteruskan sebagai props ke komponen Svelte
  • Komponen Svelte menerima props dengan export let, dan berkomunikasi dengan LiveView melalui prop live yang disediakan LiveSvelte
  • Di sisi Svelte, event bisa dikirim ke server melalui live.pushEvent
    • Dalam contoh, reactive block Svelte mengirim event "form_updated" ke server saat form berubah
    • LiveView mendekode parameter frontend di handle_event("form_updated", ...) lalu memperbarui changeset
    • Error validasi changeset lalu dikirim kembali ke frontend melalui prop errors
  • Data diturunkan dari Elixir ke Svelte sebagai props, dan dari Svelte dinaikkan ke LiveView sebagai event websocket
  • Proses LiveView dapat memperbarui props kapan saja untuk memicu render ulang komponen Svelte

Sifat inti kombinasi LiveView dan Svelte

  • Inti dari kombinasi ini adalah proses backend stateful dan komponen frontend stateful bekerja bersama
  • Ada tiga sifat yang menopang kombinasi ini
    • Backend mengendalikan props komponen frontend
    • Frontend dan backend sama-sama memiliki status
    • Keduanya memiliki saluran komunikasi dua arah privat yang memungkinkan masing-masing pihak memulai pesan
  • Sifat pertama dimungkinkan oleh cara rendering LiveView
    • Hasil render ulang server otomatis di-push ke klien dan diterapkan
    • Server dapat memperbarui props komponen seperti komponen induk JS
  • Sifat kedua berasal dari fakta bahwa LiveView adalah proses Elixir
    • Proses Elixir adalah cara untuk mengenkapsulasi status
  • Sifat ketiga dimungkinkan oleh koneksi websocket berkelanjutan yang disediakan LiveView

Perbedaannya dengan SPA

  • Routing di browser seluruhnya dilakukan di backend sehingga strukturnya lebih sederhana
    • Pada SPA biasa, perlu memelihara dua jenis route: route browser dan route API
  • Backend memiliki status dan mengetahui route saat ini serta resource yang sedang dikerjakan
    • Setiap aksi bisa diproses sebagai perubahan status backend sendiri, alih-alih membangun ulang seluruh status dari awal
  • Komunikasi frontend dan backend bersifat privat dan saling terikat
    • Tidak perlu menambah route publik server untuk pemanggilan RPC yang hanya mendukung satu komponen
    • Saat melihat pushEvent di klien, kita tahu handler terkait berada di modul Elixir yang berkolaborasi dengannya
  • Fitur biasanya terbagi terutama ke dalam dua file
    • Modul backend memanggil fungsi backend seperti query database
    • Frontend mengimpor komponen dan style
    • Alur bolak-balik frontend/backend tidak melewati modul API, router, atau stack controller
  • Prosedur komunikasinya juga berkurang
    • Backend cukup memberi tahu perubahan frontend melalui pembaruan props
    • Frontend bisa mengirim pushEvent tanpa token kedaluwarsa, timeout, atau handler penanganan gangguan
    • Jika websocket terbuka, berarti server berjalan; jika tertutup, LiveView menampilkan banner global “disconnected”

Pemisahan tanggung jawab dan struktur kode

  • Dalam struktur ini, efeknya seperti microservice frontend dihilangkan
  • Logika bisnis ditempatkan di backend
    • Cara memuat data
    • Data apa yang harus dimuat
    • Cara pengurutan dan pemfilteran
    • Validator
  • Kode frontend Svelte menjadi lebih sederhana
    • Blok if/end untuk conditional rendering
    • Animasi
    • Fungsi pushEvent sederhana untuk mengirim ke server
  • Pada frontend SPA biasa, sering muncul banyak logika map, reduce, dan filter untuk memproses data server, menyiapkan data untuk ditampilkan, dan menyiapkan data untuk dikirim kembali ke server
  • Di aplikasi LiveSvelte, pemrosesan seperti ini bisa dilakukan di sisi server
    • LiveView menyiapkan data dalam bentuk yang dibutuhkan komponen Svelte
    • Kompleksitas tetap berada di bahasa server, struktur data server, dan suite pengujian server
  • LiveView dan komponen Svelte bukan dua elemen yang hanya terhubung longgar, melainkan lebih seperti dua bagian dari satu fitur
    • LiveView hanya merender komponen Svelte tersebut
    • Komponen Svelte itu juga hanya dirender oleh LiveView tersebut

Yang berubah dibanding LiveView murni

  • Pendekatan LiveSvelte menerima keberadaan status frontend dan transisi status
  • Lapisan batas antara frontend dan backend menjadi lebih jelas
  • Paradigma komponen matang milik Svelte bisa dimanfaatkan
  • Ekosistem framework JavaScript yang sulit dijangkau dengan LiveView murni juga bisa digunakan
    • Svelte menyediakan primitive animasi
  • Dengan memindahkan lebih banyak tanggung jawab ke frontend, rasa serba tanggung di area tengah yang canggung berkurang

Alasan memilih Svelte dan posisi LiveView

  • Alasan memilih LiveSvelte adalah karena belum ada library LiveView untuk React yang punya tingkat kematangan serupa
  • Svelte dinilai sebagai framework frontend yang ringan dan cepat dalam hal status dasar dan reaktivitas
  • Karena LiveView menangani porsi besar manajemen status, pengelolaan status di sisi Svelte tetap sederhana
  • Fitur template Svelte juga lebih disukai daripada React
    • Bisa memakai if/else alih-alih operator ternary
    • Bisa memakai pengaturan atribut kondisional
  • runes di Svelte 5 diharapkan membuat Svelte lebih mudah dipelajari dan lebih mudah dipahami
  • LiveView paling bersinar sebagai backend-for-frontend yang merender komponen frontend, melakukan pembaruan inkremental, mempertahankan proses backend stateful, dan menyediakan API websocket

1 komentar

 
GN⁺ 2024-04-05
Komentar Hacker News
  • Pola yang sering dipakai di game multipemain pada dasarnya adalah menjalankan kode yang sama di sisi klien dan server
    Kode klien berjalan lebih dulu dengan memprediksi state server, lalu ketika state server tiba, state klien ditimpa
    Dalam game, klien bisa menebak hasil inputnya sendiri dengan cukup baik tetapi tidak tahu input pemain lain, jadi istilah “prediksi” memang cocok
    Namun cara ini juga bisa dipakai untuk memberi respons langsung sambil menunggu state server resmi, seperti mengaktifkan/menonaktifkan dropdown atau menampilkan loading spinner
    Ada juga banyak state klien yang tidak perlu dijalankan di server sama sekali, seperti sistem partikel atau ragdoll, dan jika ada koneksi server yang terus-menerus, tampaknya tidak ada alasan ini tidak bisa dilakukan dalam paradigma reaktif

    • Di https://territoriez.io/ saya memakai cara ini persis
      Itu adalah klon dari https://generals.io/ dan dibuat dengan LiveSvelte
      Pada dasarnya ini board game dan hanya 2 tick per detik, jadi fitur prediksi tidak diperlukan, tetapi saya memakai optimistic update yang menampilkan state game terlebih dahulu sebelum update dari server
      Jika tidak sinkron dengan server, server akan menimpa state game
      Semua logika game ada di Elixir, dan untuk melakukan prediksi dengan benar, server dan klien harus berbagi logika
      Kalau tidak, logikanya harus ditulis dua kali, dan itu jalan menuju bencana
      Saya belum menyelidikinya, tetapi solusi yang mungkin adalah menulis semua logika game dengan gleam(https://gleam.run/)
      Gleam kompatibel dengan Elixir dan juga bisa dikompilasi ke JavaScript, jadi secara teori kode yang sama bisa dijalankan di server dan klien
      Namun jika ada yang berkata “ya tulis saja semuanya dengan js”, itu juga cukup benar, dan saya mungkin akan setuju
      Meski begitu, keuntungan yang didapat adalah bisa memakai BEAM dan fitur-fitur yang bagus untuk sistem terdistribusi real-time, yang sangat cocok untuk game multipemain kecuali bagian frontend-nya
    • Saat memainkan game seperti Overwatch yang mensimulasikan fisika ragdoll secara lokal dan nondeterministik, saya berharap hal itu dilakukan dengan benar
      Ketika seseorang mati lalu mayatnya terpental atau tersangkut dalam pose lucu, tidak ada orang lain yang bisa melihatnya, dan di replay pun tiap klien merendernya berbeda sehingga tidak bisa ditonton ulang
      Jika tidak tertangkap lewat rekaman real-time, momen itu hilang selamanya
      Untuk game yang kadang konyol seperti Overwatch, sayang sekali tidak ada yang bisa melihatnya bersama
    • Game fighting mendorong masalah resolusi konflik latensi rendah seperti ini sampai ekstrem, dan ada subbidang tersendiri untuk teknik “netcode” yang menyesuaikan stream event real-time
      https://arstechnica.com/gaming/2019/10/explaining-how-fighti... adalah penjelasan yang bagus, dan diskusi terkait ada di https://news.ycombinator.com/item?id=34399790 serta https://news.ycombinator.com/item?id=26289933
      Jika ada persistensi server seperti MMO, bottleneck I/O juga harus ikut dipertimbangkan
      https://prdeving.wordpress.com/2023/09/29/mmo-architecture-s... adalah tulisan yang menarik dari sudut pandang itu, dan diskusinya ada di https://news.ycombinator.com/item?id=37702632
    • Bukankah itu hanya optimistic update? Sepertinya itu sudah lama umum di logika sisi klien
    • Ini harus dipakai dengan hati-hati
      Misalnya, sebuah form live/interaktif mungkin tampak berjalan baik sambil memperbarui data turunan di halaman, tetapi akan merepotkan jika nanti semuanya dikembalikan karena error server atau masalah jaringan
      Lebih buruk lagi, pengguna bisa saja menutup halaman atau berpindah tanpa mengetahui hal itu
  • Saya suka kombinasi LiveView + Svelte
    Saya mempresentasikan cara menggabungkan keduanya di ElixirConf 2022, tetapi para kontributor live_svelte-lah yang membuatnya benar-benar bisa dipakai
    Menurut saya, aplikasi dengan pengalaman pengguna yang kaya selalu membutuhkan state di sisi klien
    Terutama jika tinggal di New York, koneksi jaringan saat bepergian bukan sesuatu yang bisa dianggap pasti
    Salah satu fitur kuat yang tidak dibahas dalam tulisan ini adalah bahwa dengan pubsub Phoenix, perubahan state sisi server yang terjadi di server lain juga bisa didorong secara reaktif ke semua klien
    Untuk menangani trafik menengah ke atas, cukup umum menjalankan beberapa web server

    • Jaringan seluler secara umum juga memiliki latensi tinggi, dan sering kali diperlukan sistem caching local-first di klien
      Jika ingin pengalaman pengguna seperti LiveView tetapi tetap tahan terhadap jaringan yang tidak stabil, saya menambahkan binding Svelte 5 ke Triplit[1]
      Anda bisa menulis query di sisi klien dan menyinkronkannya dengan server melalui websocket
      Bagi developer Elixir mungkin tidak terlalu menarik, tetapi jika Svelte menjadi pusatnya, Triplit adalah pilihan yang bagus
      [1] https://www.triplit.dev/docs/frameworks/svelte
    • Dalam kondisi jaringan terputus-putus, seberapa bergunakah halaman LiveView saat offline?
  • Saat baris baru masuk, pendekatan yang sekadar mendorongnya ke tabel dan membiarkan LiveView memperbarui klien sebaiknya dihindari pada aplikasi bisnis yang baris-barisnya bisa diinteraksikan
    Karena latensi kognitif, pengguna mudah mengklik item yang salah, mengirim email ke pelanggan yang salah, atau mengembalikan dana untuk transaksi yang salah
    Pengalaman pengguna yang lebih disukai adalah banner tetap seperti “Data telah berubah. Klik di sini untuk memuat ulang”
    Jika mendesak, baris baru harus dirender hanya sebagai tambahan dan posisi scroll tidak boleh berubah

    • Kalau baris baru dimasukkan dengan animasi perlahan, dan klik dinonaktifkan saat data baru masuk, pendekatan ini juga bisa dilakukan
  • Di BeaconCMS, Svelte dan LiveView dipakai bersama
    Jelas ada use case yang baik ketika UI di klien perlu dikendalikan lebih halus, tetapi tim sebaiknya berhati-hati untuk mengadopsi Svelte + LiveView secara menyeluruh untuk segala hal
    Di Phoenix pun LiveView tidak selalu menjadi jawaban, dan kadang halaman render biasa sudah cukup
    Jangan memilih semuanya sebagai serba ada atau tidak sama sekali
    Seperti yang dikatakan tulisan itu, ada use case yang baik untuk keluar dari “cara LiveView”
    Jika waktu round trip 1.000 ms, memang perlu mempertimbangkan hal lain, tetapi ada juga tim yang tidak bisa menempatkan server yang dekat secara geografis karena alasan seperti biaya, sehingga manajemen state di sisi klien bisa menjadi solusi

  • Maksudnya, alih-alih mengelola state klien, akan mengelola state di klien dan server sekaligus?
    Walau ada kelebihan karena tidak perlu membuat API lain, itu tidak terlihat seperti perbaikan

    • State aplikasi web tidak sesederhana itu
      Selalu ada state yang harus dilacak klien dan state yang harus dilacak server, lalu di atasnya ada state sementara yang cukup berada di memori dan state yang harus dipertahankan antar-sesi
      Cara mengelolanya nyaris tak terbatas, dan di JavaScript, karena “apa pun yang dilakukan tidak ada jawaban benar”, akhirnya orang memakai cara yang ditentukan framework atau solusi tambal sulam, alias kekacauan
      Pada aplikasi single-page kompleks terakhir yang pernah saya kerjakan, klien dibuat melakukan sinkronisasi setiap kali halaman dimuat
      Semua state atau aset lokal diberi hash berbasis tanggal, dan jika berbeda dari nilai di server, server mengirimkan versi yang diperbarui
      Itu berlaku sama saja baik untuk variabel sederhana, objek JSON besar, maupun seluruh blob gambar/audio
      Jika klien melakukan sesuatu yang membutuhkan perubahan state server, ia mengirim pembaruan state itu lewat WebSocket, dan 99% aplikasi berbasis WebSocket
      Tidak memakai framework atau pola khusus; saat menulis kode lalu merasa “ini harus dilacak server”, state baru dikirim sebagai pesan ke server, dan server yang memutuskan apakah perlu disinkronkan saat halaman dimuat
      Untuk jenis manajemen state seperti ini, menurut saya mekanisme ini hampir yang paling sederhana
      WebSocket benar-benar sangat membantu dalam manajemen state
    • Pada akhirnya, rasanya suatu bentuk dari paradigma semacam ini akan menang
      Aplikasi nyata membutuhkan state di klien maupun server
      Server tidak bisa mempercayai klien, jadi harus memiliki state otoritatif, tetapi klien juga harus bisa merender ulang sebagai respons terhadap interaksi pengguna tanpa round trip
    • Beberapa hal memberikan pengalaman yang lebih baik jika sepenuhnya ditangani di sisi klien
      Jangan lakukan semuanya begitu; gunakan hanya saat masuk akal
      Hal lain yang saya suka adalah bisa memakai Svelte sebagai bahasa template alih-alih Heex
    • Ini lebih mirip generasi baru yang menemukan kembali ColdFusion, Web Forms, JSF, PHP, Spring, dan Rails
    • Ini tidak berbeda dari optimisasi yang dilakukan di ekosistem perangkat lunak lain
      Jika tidak diperlukan, tidak ada alasan melakukannya; alasan hal itu menjadi perlu adalah performa dan pengalaman pengguna
      Jika aplikasi web memiliki banyak interaksi pengguna sehingga membutuhkan JavaScript klien, dan banyak eksperimen sehingga bundle berbeda pada tiap request, orang akan ingin membagi logika antara server dan klien untuk mengurangi jumlah JavaScript yang dikirim ke klien
      Kalau tidak, aplikasi akan memiliki bundle JavaScript berukuran MB yang berisi semua kemungkinan kasus yang mungkin ditemui aplikasi
      Untuk aplikasi seperti versi web Photoshop, yang penggunanya memahami waktu muat awal, itu mungkin tidak masalah; tetapi pada aplikasi seperti Stripe atau Gmail yang diharapkan langsung dimuat, orang ingin mengurangi jeda awal halaman
      Semuanya juga bisa dipindahkan ke server, tetapi seperti yang dialami GitHub, interaktivitas halaman memburuk ketika tindakan pengguna yang harus merespons seketika membutuhkan round trip ke server
      Maka kecepatan cahaya dan distribusi server menjadi masalah
      Bundle juga bisa dimuat tertunda dengan async import dan semacamnya, tetapi JavaScript yang dimuat tertunda kemudian mengirim request lagi untuk mengambil datanya sendiri, sehingga muncul masalah waterfall
      Saat semua masalah ini ditemui, pada akhirnya orang akan mencari solusi yang memudahkan masalah rumit berupa berbagi logika/state antara klien dan server
  • Pendekatan ini punya batas kecepatan cahaya secara harfiah, yaitu “ada batas seberapa dekat server bisa berada dari pengguna”
    Langkah berikutnya adalah mengompilasi server ke WebAssembly dan mengirimkannya ke klien
    Dengan begitu, respons dapat dirender secara optimistis sambil menunggu respons server yang sebenarnya
    Kedengarannya agak gila, tetapi saya pernah melakukannya di proyek nyata dan rasanya seperti sihir

    • Bagaimana dengan persistensi? Menurut saya itu tujuan utama backend
      Menjalankan server di klien pun tidak menyelesaikannya, dan pada akhirnya latensi jaringan untuk persistensi tetap ada
      State server yang pada akhirnya harus menang juga adalah persistensi itu
    • Kedengarannya seperti overengineering
      Banyak overengineering memang sering diimplementasikan meski tanpa alasan khusus
    • Apakah ada alasan tidak cukup memakai Service Worker saja?
    • Bisa berbagi lebih banyak detail?
    • Kedengarannya sangat mirip dengan prediksi sisi klien yang dilakukan game multiplayer modern
  • Saya membuat LiveSvelte, jadi kalau ada yang ingin ditanyakan silakan beri tahu

    • Kalau memakai LiveSvelte, apakah masih ada alasan untuk tetap memakai JS Hooks?
  • Secara umum, saya selalu ingin membuat aplikasi dengan model seperti ini
    Berorientasi event, pembaruan real-time dua arah dengan server, event yang berurutan, serta state lokal/remote
    Saya tidak tahu LiveView dan belum pernah memakai bahasa keluarga Erlang, tetapi jelas rasanya mereka menangkap sesuatu yang penting
    Model request-response tradisional secara halus dan cukup sering menimbulkan masalah konsistensi dan data usang
    Jika 10 tahun terakhir adalah masa mengintegrasikan konsep pemrograman fungsional ke bahasa arus utama, saya berharap 10 tahun berikutnya mengarah pada pengintegrasian pemrograman berorientasi pesan yang memiliki state ke full-stack arus utama

    • Ada backend LiveView yang ditulis dalam JavaScript(http://liveviewjs.com), Go(https://github.com/canopyclimate/golive), Java(https://github.com/floodfx/undead), Python(https://github.com/ogrodnek/pyview)
      Sebagai catatan, tiga yang pertama saya buat atau saya bantu pembuatannya
    • Dengan asdf, erlang/BEAM/OTP dan elixir bisa dipasang, dan kalau sedikit berpengalaman memakai tooling, ini hanya butuh beberapa menit
      Jika mengikuti panduan sambil sedikit mencoba-coba, dalam kira-kira dua jam Anda seharusnya bisa menjalankan aplikasi chat Phoenix dasar di browser
    • “Mengintegrasikan pemrograman berorientasi pesan yang memiliki state, atau pemrograman reaktif, ke full-stack arus utama” dulu juga disebut MVC, sebelum Rails mendefinisikan ulang istilah itu
  • Ini solusi yang bagus
    Di aplikasi saya, saya memakai controller Stimulus yang reusable bersama LiveView, dan ini juga berjalan mulus
    Secara keseluruhan, pengembangan dengan LiveView itu menyenangkan, tetapi semakin sering saya memakainya dalam skenario nyata, semakin terasa juga keunggulan framework HTTP stateless seperti Hotwire
    Rasanya lebih berkinerja, lebih tangguh saat reconnect, dan mengurangi kebutuhan menempatkan lebih banyak server dekat dengan pengguna demi stabilitas

    • Saat Stimulus/Turbo pertama kali diumumkan, saya cukup berharap itu membantu menyelesaikan masalah yang dijelaskan penulis
      Namun Stimulus tidak menyediakan cara elegan untuk mempertahankan state di klien
      Pendekatannya seperti “state aplikasi Stimulus berada sebagai atribut di DOM”, jadi tidak lebih baik dari vanilla JS atau jQuery
      Saya memang belum pernah memakai Stimulus di proyek nyata, jadi ada kemungkinan value dan callback perubahannya memberikan pengalaman yang lebih baik daripada dugaan awal
    • Saya juga memakai Stimulus bersama LiveView
      Kombinasi ini punya tingkat kompleksitas yang pas, sementara Svelte saat dipakai bersama LiveView terasa menangani banyak hal yang sejak awal bukan masalah
      Yang dibutuhkan adalah vanilla JS atau lapisan tipis di atasnya, bukan framework penuh
      Toh tidak perlu banyak memakai JavaScript
      JS di aplikasi produksi saya tidak sampai 200 baris, dan beberapa controller Stimulus sepertinya juga bisa dihapus
      LiveView sebagus itu
      Saya juga membuat adapter hook Stimulus-LiveView yang sangat hacky, sehingga controller Stimulus bisa mengirim event langsung ke proses LiveView
      Dan LiveView, kecuali kalau terlalu banyak menenggak Kool-Aid ala fly.io, tidak benar-benar membutuhkan server yang terdistribusi secara geografis
      Putus koneksi juga ditangani dengan sangat baik
      Saya juga tidak melakukan apa pun secara khusus untuk mendukung update tanpa downtime
      Seluruh proses ketika klien kehilangan koneksi WebSocket, reconnect ke versi baru, lalu memulihkan state ditangani otomatis secara default
      Mau minta apa lagi?
  • Perusahaan kami mendapat manfaat besar dengan memakai LiveView bersama Alpine, khususnya karena kami tidak bisa mengizinkan eval di klien sehingga memakai mode CSP
    Saat pertama melihat LiveSvelte, itu tampak sangat baru dan belum terlalu teruji, dan masih ada dampak yang belum terselesaikan di lingkungan CSP yang ketat
    Sekarang saya senang melihatnya tampak cukup berguna
    Pola kami kira-kira bisa disebut LiveAlpine
    Jika komponen membutuhkan HTML, kami memakai HTML Component; jika ada state sisi server, kami memakai Live Component
    Jika membutuhkan perilaku atau state sisi klien, kami juga mendefinisikan komponen Alpine
    Jika perlu menerima event klien di server atau melakukan request HTTP, kami juga mendefinisikan Phoenix Hook