vugu / vugu

Vugu: A modern UI library for Go+WebAssembly (experimental)
https://www.vugu.org
MIT License
4.8k stars 175 forks source link

Support for other languages like rust and kotlin #196

Closed Remigius2011 closed 7 months ago

Remigius2011 commented 3 years ago

Is your feature request related to a problem? Please describe.

Last year I had practically the same idea as you, namely to build a react-like component framework that compiles and binds to wasm code, but written in rust. Currently there are several languages that have a wasm back-end. In any case it might be advantageous to support other languages as well (imo kotlin might be an interesting candidate, too).

Describe the solution you'd like

Describe alternatives you've considered n/a

Additional context n/a

bradleypeabody commented 3 years ago

It's definitely an interesting idea.

It's hard to say if it would be practical or not. There are a lot of things that Vugu does a certain way due to decisions made in the Go programming language.

The main benefit of such an abstraction would (or so it seems to me) be that a developer writing in one language could then move to another language and at least the markup aspect would be the same. Which would be cool, I just don't know how practical or useful it is in relation to the effort required. Many projects will just be written in a single language. And as with any library/framework developers would need to get used to the various idiosyncrasies of that environment, etc. Moving from Go to Rust or Rust to Kotlin, etc. there are bound to be some implementation details that slip into these markup files, and so I just wonder if it's worth the effort to try to unify things.

And I don't know if there is any realistic way to mix and match languages. I think things are still a very long way off from being able to have a project written in Go that imports Rust libraries and uses them as they were intended or vice versa - but I haven't looked into it in too much detail, I could be wrong about that.

Remigius2011 commented 3 years ago

Hi,

Thanks for your concern and sorry for not following up earlier.

Meanwhile I have done some research on the topic of native component frameworks and wasm. There seem to be multiple projects on this track:

(omitting Razor here because it seems it is not complied to native code)

I haven't found a kotlin native wasm component framework yet (even though https://reduxkotlin.org/ might be a step in this direction), but I think once a multilingual baseline for a wasm component framework is available, there will surely somebody from the kotlin scene be able to implement one.

Regarding interoperability, there is a proposal underway, which is about solving performance issues traversing the thunking layer between JS and wasm (or between wasm modules):

https://github.com/WebAssembly/interface-types/blob/master/proposals/interface-types/Explainer.md

Once these issues are solved, it will lower the performance penalty of invoking wasm from JS and DOM manipulation functions from wasm, and provide a better interface layer for invoking wasm functionality which may even be used for invoking other wasm modules. OTOH, the performance penalty for JS itself is maybe overestimated, as indicates this account of some benchmarks:

https://surma.dev/things/js-to-asc/

Of course there may always be other reasons than performance to use non-js languages in a web front-end (e.g. reuse of code and/or know-how, non-js obfuscation etc.). IMO, mix and match could be possible even today via JS. Either "universal" components could invoke each other by having child components hooking into the DOM, or by having a universal binding layer that each component is required to use (with bindings for all supported languages).

If I sketch the rendering pipeline roughly as follows:

reactive state -> virtual dom -> dom

where state updates result in an updated virtual dom which is compared to the pervious version to compute the final dom updates, we have observed that in our case (vue 2, worst case of literally several thousands of HTML elements), the computation of the virtual dom and the resulting updates is the largest part of the rendering effort in this chain (Chrome). As this is (in an assumed wasm version) completely detached from any interaction with the dom, it should be executed entirely in native code and hence profit from native performance without being slowed down by crossing the JS boundary. In contrast, less complex UIs might not benefit as much from a wasm implementation.

These are just very generic thoughts in the subject, so please forgive me if I am ignoring some facts that are obvious to you which might contradict them.

Cheers, Remi.

bradleypeabody commented 3 years ago

Thanks for that info.

solving performance issues traversing the thunking layer between JS and wasm

This part definitely makes sense, since it is a common and non-trivial problem.

the performance penalty for JS itself is maybe overestimated

Hard to say. The last time I timed this I was getting call times in the tens of microseconds, not super slow, but not fast either (function calls in native code on modern CPUs should be in the low nanoseconds). This was the observation that led me to ship data from wasm over to JS in big chunks all at once and then have JS use it from there with minimal calls back and forth.

reactive state -> virtual dom -> dom

Overall I agree with your analysis on this. Although it's not entirely clear to me which step is the slowest. I actually finally have a decent sized Vugu application which is starting to run into performance problems that I can begin to analyze, but I haven't gotten to it yet; hopefully soon, and hopefully it will help shed some more light on the matter.

If there were some common API for dealing with DOM synchronization, that could be re-usable across languages and seems quite valuable.

owenwaller commented 7 months ago

I am pretty sure this is not fixable.

There is no way to import, say a, Rust package/library directly into a Go program, regardless of the target OS and CPU ARCH set, and WASM in GO is just another OS and CPU ARCH combination.

You'd need to use CGO and then some form of FFI layer, which won't work in WASM as CGO isn't supported.

Importing anything based on the JVM is even harder as you'd need to embed a full JVM in the loading application and then worry about GO runtime -> JVM barriers

Vugu is based in Go. if you wanted Vugu in Rust/Kotlin etc, you'd take the design ideas in Vugu and build them again in Rust/Kotlin to have a Rust/Kotlin version of Vugu.

If you mean loading a WASM blob e.g. a library that was compiled from Rust to WASM into another WASM program (which say was generated from Go via Vugu) then you'd need some sort of shared library dynamic loading ability in the Web Assembly/Browser layer. I'm not clear if exists or not. Is this is the Web Assembly modules concept or not?