
Kweb: A new approach to building rich webapps, in Kotlin - pplonski86
http://kweb.io/
======
jnovek
I've been lucky to observe KWeb since its earliest days and some of the
missing context on the website, I think, is that the author takes the position
that the way we build webapps is fundamentally wrong.

From his perspective it seems that the "division" between frontend and backend
are an implementation detail that accidentally became of defining feature of
how we write software for the web. Websockets are a way to correct this by
making the delivery channel dumb and universal while focusing application
development in a single software architecture.

It reminds me of the principle of brutalist web design ([https://brutalist-
web.design/](https://brutalist-web.design/)). Brutalist design, while not
completely beautiful, makes me ask, "What were we trying for when we first
made HTML? Does the tool really fit those goals anymore?" While I hope that
KWeb grows up to be something big, at a minimum it asks a lot of questions
about why applications for the web are architected the way they are.

~~~
bloudermilk
The problem with this approach is that the “division” is so fundamental to the
performance of web applications that it can’t simply be abstracted away. When
real applications encounter latency and unreliable connections at scale the
abstraction will leak. At that time teams will be forced to dedicate efforts
just to overcome the deficiencies in the architecture.

~~~
renegadus
I don't think there is any reason, in principle, that Kweb can't be just as
efficient as any other web application.

This is because Kweb doesn't entirely abstract away the client/server
separation in one important sense. When you attach a callback to something you
normally do it like this:

    
    
      button.on.click {
        header.text("They clicked!")
      }
    

This is less efficient than it could be because it is needlessly doing a
server round-trip. So for situations where you're only modifying client state
you can do:

    
    
      button.onImmediate.click {
        header.text("They clicked!")
      }
    

When the user clicks it will be instant, as the instructions to modify the DOM
are "preloaded" to the client on page render.

Does that alleviate your concern? If not, can you elaborate on where you think
the bottleneck is likely to emerge?

~~~
bloudermilk
The example you make here is exactly what I'm referring to when I say the
"abstraction leaks". From the homepage:

> Kweb ... virtually eliminates the separation between browser and server from
> the programmer’s perspective.

In my opinion, we can't say the separation has been "eliminated" if I'm
constantly having to ask myself "should I handle this event on the server or
the client via `onImmediate`?"

What seems more likely to happen, is that inexperienced developers simply
won't ask the question at all and months later the customer will ask why their
dashboard page is taking 60 seconds to load. The senior engineers will be
tasked to fix it only to find out that the page is making dozens or hundreds
or thousands of N+1 round trips to the server.

This has been my experience being asked to come in to fix MeteorJS apps. Teams
of web developers not understanding that the client/server interface is not
free and that poor engineering practices have severe compound effects.

~~~
renegadus
I appreciate your feedback.

> In my opinion, we can't say the separation has been "eliminated" if I'm
> constantly having to ask myself "should I handle this event on the server or
> the client via `onImmediate`?"

Well, I said " _virtually_ eliminated" :)

I think it's an exaggeration to say that the programmer must constantly ask
themselves this, it's only relevant when adding an event listener. You'll get
along just fine if you never used onImmediate, it just means your webapp may
not feel quite as snappy as it could be.

To me this seems like a very small price to pay to avoid having to bifurcate
your application across client and server - particularly given that it's not
even compulsory, it's an optional optimization.

> What seems more likely to happen, is that inexperienced developers simply
> won't ask the question at all and months later the customer will ask why
> their dashboard page is taking 60 seconds to load. The senior engineers will
> be tasked to fix it only to find out that the page is making dozens or
> hundreds or thousands of N+1 round trips to the server.

An unnecessary roundtrip may add 200ms of latency across a typical internet
connection to the speed with which the page responds to an event, but I can't
think of any circumstances under which this would delay the page render.

Moreover, a website built without onImmediate should work just fine, it just
might not quite match the performance of a well-written client-side app.

> This has been my experience being asked to come in to fix MeteorJS apps.
> Teams of web developers not understanding that the client/server interface
> is not free and that poor engineering practices have severe compound
> effects.

There is only so much a framework can do to save programmers from themselves.
In this case the risk is that the app may feel a little more sluggish than it
otherwise would, a difference that users might not even notice.

It may be possible to automatically identify candidate event handlers which
don't appear to be modifying server-side state and provide a nice list to the
programmer, but I'd likely only invest time in this if it proved to be a
significant issue in practice.

------
ttty2
I agree on writing environment (client/server) agnostic code, but not in this
way. Js code should definitively run on the client and here is why:

\- Instant feedback, no matter how bad is your connection: here if I click on
something and there is no internet, I won't see a loading icon. You probably
have to hack it. \- I'm not sure how it will scale and if it scales will be
way more expensive than just using rest api (sockets are more expensive)

probably more problems.

I'm the creator of this game [http://bitplanets.com](http://bitplanets.com)
which has a lot of shared code that runs both on the client and the server
side. Some validation is done on the client (so you don't even hit the server
if it fails + get instant feedback that your action is successfull or failed)
and the same validation is done on the server side as well (so you can't hack
it).

Examples:

\- When you send a ship it will show a temporary ship immediately even if the
server didn't receive yet the ship. If the client validates most likely it
will be a valid ship (unless you hack it, but server side will deny your
ship). Then when the server comes back saying that the ship is valid then the
ship is not temporary anymore.

If you had a java backend everything would be so much more complicated. This
is what I mean by having agnostic code, this validation function doesn't
really care if is run on your client or on your server.

~~~
renegadus
> here if I click on something and there is no internet, I won't see a loading
> icon.

Fortunately, that's not so - Kweb has a neat way to handle it - outlined here:
[https://www.reddit.com/r/programming/comments/a4dtp2/kweb_a_...](https://www.reddit.com/r/programming/comments/a4dtp2/kweb_a_new_approach_to_building_rich_webapps_in/ebdrtet/)

------
toyg
Reminds me of the principles behind the original asp.net, all the way back in
2000. At the time there were no websockets, so it was done with constant post-
back, but the principle was fundamentally the same: develop like it were a
local app, the framework will take care of the rest. Let’s just say it didn’t
get very popular in my neck of the woods. I’ve since moved on to other things
so I don’t know what modern asp.net does, but I bet you can still code this
way if you really want.

(Not that you should, imho: trying to bypass the fundamental architecture of
the web is typically a way to end up in debugging hell.)

~~~
sixdimensional
First, there was ASP, which was a lot like PHP, ColdFusion or Perl/CGI -
mixing inline back-end code and HTML/JS/CSS/etc - but of course executing all
back-end code on the server.

ASP.NET WebForms came along and is still supported, and tried to make
developing web applications similar to developing desktop applications in
WinForms. I did that, it worked.. it was clunky at times (but it worked). Of
course, mostly this was all server-side with just HTML/JS/CSS interacting.

A long time ago the dominant model became ASP.NET MVC which is a typical
server-side MVC architecture.

Recently, Microsoft offered a new "old" paradigm through Razor Pages which are
a lot like old ASP was.

If you look at things like React (or the view layer in Angular, etc.), it
turns out that the web component / control model used in WebForms (server-
side) is quite similar to the client side model used in React. The main
difference of course being, one running client-side primarily (React) and the
other server-side (WebForms). It gets even more interesting as a comparison
when you talk about server-side React view rendering.

~~~
toyg
Yep, I was thinking of the original WebForms.

------
rkagerer
Doesn't blurring the client/server divide induce the programmer to unwittingly
introduce more latency?

~~~
renegadus
Kweb has a neat solution to this, I outline it in this Reddit comment:
[https://www.reddit.com/r/programming/comments/a4dtp2/kweb_a_...](https://www.reddit.com/r/programming/comments/a4dtp2/kweb_a_new_approach_to_building_rich_webapps_in/ebdrtet/)

------
setheron
Too much magic. Debugging this would be a real pain with everything happening
over websockets

~~~
mpweiher
I would expect it to be quite the opposite: it looks like a true hexagonal
architecture for the web, with the thinnest of adapter for the client part,
which is nearly perfect.

You can debug all your logic on the server.

I'd guess a/the big drawback would be no offline capability. But if you're
fine with that (many are), then why not?

~~~
renegadus
I'm kweb's creator, I hadn't heard the term "hexagonal architecture", I'll
read up on it, thank you for the kind words.

You are correct that, since kwebsites are server-driven, there is no
significant offline capability.

But then the requirements of many websites often rule that out anyway, my
strong suspicion is that this won't be a dealbreaker for many people.

------
renegadus
Note: reddit discussion here:
[https://www.reddit.com/r/programming/comments/a4dtp2/kweb_a_...](https://www.reddit.com/r/programming/comments/a4dtp2/kweb_a_new_approach_to_building_rich_webapps_in/)

------
ciconia
There's also LiveView coming to Phoenix (Elixir). This might be a new trend in
web frameworks.

------
lmm
Sounds like a similar approach to Wicket, which remains the best web UI
framework (possibly the best framework period) I've ever used.

~~~
renegadus
I used Wicket for a major project way back in 2007 and worked with the creator
of Wicket for a while - so it's almost certain I got some inspiration there :)
Wicket was probably the first time I saw a web framework and thought - "wow,
this web stuff can be elegant".

Wicket suffered because it straddled the transition from pure HTML to
HTML+AJAX. It could do HTML+AJAX, and their solution was elegant, but it was
an afterthought and Wicket wasn't really designed around it.

Kweb was designed from the ground-up for this world and this affords it many
advantages.

~~~
lmm
Glad to hear it. How Scala-friendly are the interfaces?

~~~
renegadus
Hmm, I'm not sure, but my guess is "not very" as I didn't really design it
with usage from other JVM languages in mind.

The reason is it depends on some stuff like coroutines - and since Scala
deprecated their delimited continuations plugin way back when, I don't believe
Scala has any equivalent feature.

May I ask why you ask?

~~~
lmm
I'm interested to use a framework with this kind of design, but I'm very much
committed to Scala (and could never give up HKT at this point).

~~~
renegadus
Ah, understood. If you're locked in to Scala then unfortunately Kweb probably
won't be a good fit :(

------
nimmer
Nim + Karax allow creating single-page applications without "magic":

[https://nim-lang.org/araq/karax.html](https://nim-lang.org/araq/karax.html)

Working example: [https://forum.nim-lang.org/](https://forum.nim-lang.org/)

~~~
renegadus
Interesting. Just for fun I created a side-by-side with Kweb of one of their
simple examples.

Here is kerax:

    
    
      var lines: seq[kstring] = @[]
      
      proc createDom(): VNode =
        result = buildHtml(tdiv):
          button:
            text "Say hello!"
            proc onclick(ev: Event; n: VNode) =
              lines.add "Hello simulated universe"
          for x in lines:
            tdiv:
              text x
      
      setRenderer createDom
    

Here is the equivalent in Kweb:

    
    
      fun main() {
        Kweb(port = 2734) {
            doc.body.new {
                button().text("Say hello!").on.click {
                    println("Hello simulated universe")
                }
            }
        }
      }
    

This compiles and works.

~~~
Matthias247
The first seems to add new DOM nodes with text on every click. The second one
doesn't. So they don't seem to be equivalent.

~~~
renegadus
Hmm, it seems to be adding things to a list but where is it adding a new DOM
node?

~~~
Matthias247
I would say in

    
    
         for x in lines:
            tdiv:
              text x
    

Whenever the DOM gets rerendered, it iterates over the the lines (or the
"model" in general), and creates DOM elements from it. At least it looks very
similar to React and Angular code, and they do exactly this.

~~~
renegadus
Ah, you're right. Ok, I think I can do that fairly concisely in Kweb also, if
I find a bit of time.

------
sorokod
Is there any documentation, API or otherwise available?

~~~
renegadus
Unfortunately that's one area where Kweb is currently immature, however beyond
what's on the website there are a number of examples that should help:

[https://github.com/kwebio/core/tree/master/src/main/kotlin/i...](https://github.com/kwebio/core/tree/master/src/main/kotlin/io/kweb/demos)

Also, if you use IntelliJ IDEA then the IDE will do a lot of the work for you
in figuring out the API.

------
xytop
What about mixing frontend with backend?

That’s terrible.

~~~
sambull
Back to PHP3 and coldfusion days

~~~
rckclmbr
There were a lot of things i really liked about coldfusion, like how easy it
was to build reports, and how easy it was to get started. cfdump is still one
of my favorite debugging tools. Everything else, not so much :)

