Hi, would like to share a demo of new Web Framework, Twitter clone
It's reactive, the UI updated automatically after you change the model.
Examples
Current state - experimental, the web framework code is public and examples are working, but it's not polished, no docs, going to be changes and there are some issues with threads...
Neat stuff! And thanks for making the accompanying video.
Looks like you're using deno to build out the JS too. If I may ask, what are the advantages of using Deno in this context?
Regarding the nim part - is the plan eventually to incorporate some Websockets tech? Lots of those new HTML-on-the-wire frameworks seem to rely heavily on Websockets for the more responsive/dynamic aspects.
Thanks :). The answer for both questions - because of simplicity.
Proper JS packager like WebPack would be a better option but it would require more code to write and maintain.
Websockets are also better, but require to write and maintain more code - on the client - to handle reconnections and unreliable networks, there's socket.io library, but it's quite large. And on the server too, as Websockets require server capable of maintaining lots of parallel connections. Also, I remember seeing benchmark, showing that for the request/response latency for websockets are no better than for old fetch call.
"Proper JS packager like WebPack would be better than Deno, but it would require more code to write and maintain."
Oh sorry I didn't mean to insinuate deno was a bad choice. Quite the opposite, Deno looks like next-gen tech that looks much more pleasing to use than NPM. The fact that it can manage dependencies client-side was new to me. I personally hate using Webpack, as its massive, and requires more code to maintain.
And that's an interesting point about Websockets too. Tbh I've never thought to compare latency times between websockets and a fetch call. But as you've said, websockets does introduce a minimum overhead that fetch doesn't. At the very least, ping/pong handlers.
why not leverage karax? Karax is FrontEnd framework, like React.JS
The whole point of ThisFramework is to eliminate the FrontEnd. So there's no nee for FrontEnd frameworks, be it React.JS or Karax. You write Server code and it magically turned into Interactive UI.
With Karax/React.JS/Svelte/Vue/Angular you need to develop following components:
Server (Models, Controllers, API) <-> Client (API, Models, Templates)
With ThisFrameowrk you need:
Server (Models, Controllers, Templates)
Deno looks like next-gen tech that looks much more pleasing to use than NPM
Agreed, Deno is huge simplification, no package.json, node_modules with couple of hundres dependencies, npm, build configs etc. :).
@mikebelanger about the WebSockerts, the framework itself are message based, so in the future websockets could be added very easily. Basically all that needs to be done is to implement this transport interface, currently it's implemented with fetch.
interface Transport {
send<A extends { action: string }>(action: A): Promise<void>
on(listener: MessageListener): void
}
You write Server code and it magically turned into Interactive FrontEnd UI.
doesn't that mean any UI interaction requires talking to the server? if so, I don't see the improvement over karax or equivlent for frontent + some backend
I took it up! Here's a link to my repository: https://github.com/ajusa/simple-twitter
I've only been using Karax/Jester for a week, and I've Norm a bit before then. The total number of lines comes out to be 98 if I'm not mistaken.
Some of the code is... pretty ugly to be honest. I'm not quite used to handling state with Karax, and I'm sure that I left some bugs in there. Using both jsony/json probably didn't help (jsony refused to serialize from a type to JSON for some reason).
The other thing that was a bit painful was arbitrarily adding an id to each post in the loop, just so that the right index would get updated. I think this is akin to key in Vue, but I'm not super sure either. An async API is needed for kajax as well, writing callbacks is painful.
Other than that though, this was pretty fun! Thanks @dom96 for Jester, and @moigagoo for Norm. I was able to reuse the model definition from the backend in Karax without many issues. I would also appreciate any feedback from someone with more experience in Karax than me, I know that this isn't the best code to solve this problem!
Wrt handling state, I recommend this article: https://moigagoo.svbtle.com/exploring-karax
I wrote it three years ago but I still haven’t found a better solution to components and states in Karax since.
Nim in Action contains a full chapter dedicated to creating one with Jester and Nim's standard library (which I noted you are not using, why?), the main .nim file comes out to 62 lines of code.
@dom96 Thanks for example, but it's not interactive, it's like plain PHP or Ruby on Rails.
I took it up! Here's a link to my repository: https://github.com/ajusa/simple-twitter
@ajusa thanks for the effort of writing Twitter Example with Karax. Looks nice. There's less code on the Server and in the Client-Server API than I expected....
I'm going to take some time and think about it it... I will be back :).
P.S.
@dom96 As for the standard library, I do use it. My extensions are mostly addons like seq.is_empty, or fixes for old functions written with var, or fixing conflicts with iterators, or extending hard to use modules like re which seems to be written in low-level C-style.
I'm going to take some time off and think about these two approaches again... :).
Yes, things to consider:
Good idea, however since this is a new framework I'd like you to keep this in mind by looking at the problems elixir/liveview and laravel/livewire are facing and how you could possibly solve it in your implementation.
The issue with liveview (and the like) are:
Livewire and Liveview use Alpinejs (designed by livewire developer) to 'sprinkle' js interactivity and use Tailwindcss for styling. But, using this approach for a large app might not be easy to maintain.
I feel that to solve this, you could team up with the Karax team (instead of making a bunch of competing frameworks) and allow both frameworks to intergrate with each other in a modular fashion where both could exist in the same application and serve their specific use cases (and maybe add tailwindcss support too).
A discussion on the Elixir forum explained that Liveview cannot be used for high interactivity/SPA/web app that uses the browser as a runtime e.g. a google docs clone can be built with an SPA framework like angular/karax(has anyone tried?) but not with Liveview. I think the community could benefit with an integration...hope what I said was helpful :)
-Poor performance in regions far away from the server (+- 10 second lag for a response to a button click) e.g server in US/Canada and client device in Asia/Africa etc.
Each tool has limitations, as far as I know this approach doesn't work well in high-latency networks.
One easy technic to improve user experience in such cases could be to communicate clearly what's going on, for example by showing a progress, so user realises that it's ok and need to wait a little bit. The framework actually does that, when you click on something the spinner should be shown (the CSS seems to be broken right now so it won't displayed properly right now, I need to fix it :)).
-Poor performance in low bandwith regions (partially due to websocket usage?)
Strange, there should be no issue here. The high-latency is the problem but the bandwidth is not. The data sent, gzipped html is quite small. And the LiveView additionally optimises html sent (it does diff on the server, so only tiny diff is sent), so very little data is sent over network. I guess the issue is seen if someone bind keypress event in the text field with the server action.
I had issue with websockets in some other project, it worked poorly on 3G network, so I had to remove it and use fetch and it worked well. That's why I didn't used websockets here and used plain fetch instead in this framework. From my understanding websockets itself is good, but too low-level, you need to write a higher-level wrapper around it that would handle reconnects, timeouts etc. I don't know such wrapper library (socket.io is too large), and don't want to write the code myself.
-High data usage (server request for every simple click, websocket usage again?)
Hmm, don't think that's an issue, any site with pictures would dwarf the gzipped html, even if it's sent for each click.
-Poor scalability (Best for internal apps/POC/simple mostly static sites/known number of users)
Phoenix LiveView does the DIFF on the Server, it requires stateful server, but it's optimised and fast. Maybe could be if the load is really high, or maybe some mistake made in the code ending up in slow code.
ThisFramework does diff on the Browser, and is stateless, so it should scale same way as other plain old stateless web servers like PHP/Ruby with full page reload.
I've been using HTMX quite a bit recently, so I went ahead and updated the Simple Twitter repository I had https://github.com/ajusa/simple-twitter. With HTMX, you have something similar to the original post where interactions hit the server, but you control where the HTML goes. This usually means increased performance as you are manually specifying where HTML goes after doing a request. This still has the same latency issue however, for example if you clicked "Edit" in my updated code and have lots of latency you'll need to wait for the Edit form to be fetched. The Karax version doesn't have that issue. However, with stuff like Cloudflare workers (Nim runs on that with the JS backend) and AWS Lambda, latency is becoming less of an issue.
For what it's worth, the HTMX version is around 60 lines of code, without crazy golfing (I did use the fancy syntax that Norm offers, but that was it). It also uses my WIP forms library https://github.com/ajusa/dalo, which helps slightly with clarity. If you're willing to live with the potential latency issues, I think that this is a really solid stack to build web applications in Nim. I'm still experimenting with https://hyperscript.org/ (from the HTMX folks) to see if that could help reduce latency by moving certain interactions to the client side, but it isn't quite as clean as it could be.