Stream: beginners

Topic: Compile to javascript? Build Single Page Application? SPA?


view this post on Zulip rofrol (Feb 10 2024 at 14:15):

Hello.
How to build SPA with Roc? I was using Elm previously.

I have found this for Elm programmers but can't find something about SPA https://github.com/roc-lang/roc/blob/main/roc-for-elm-programmers.md.

I see that I can generate static website

I see there are platforms but no web platform? https://github.com/zraexy/roc/tree/main/examples/platform-switching

There is this project https://github.com/roc-lang/roc/tree/main/examples/virtual-dom-wip but I think it is going webassembly way and is also WIP.

Thanks.

view this post on Zulip Anton (Feb 10 2024 at 14:55):

We don't have any SPA platforms yet but you can use Roc for the backend with the basic-webserver platform.

view this post on Zulip Richard Feldman (Feb 10 2024 at 14:58):

Roc doesn't compile to JavaScript, and the plan is that it won't. So in the browser, WebAssembly is the one way to run Roc!

view this post on Zulip Luke Boswell (Feb 10 2024 at 19:34):

I've had fun writing a web app using htmx. I wrote about my exploration https://lukewilliamboswell.github.io/roc-htmx-demo/

view this post on Zulip Shaiden Spreitzer (Feb 13 2024 at 14:12):

Richard Feldman said:

Roc doesn't compile to JavaScript, and the plan is that it won't. So in the browser, WebAssembly is the one way to run Roc!

What would it take to modify the compiler to emit javascript instead of, say, llvm?
The readme (https://github.com/roc-lang/roc/blob/main/crates/compiler/README.md) lists a number of steps. Where, and what kind of changes are need to allow targeting javascript (or any other scripting lang)?

How to implement platforms when compiling to javascript is a different question. My main interest here is if it is possible at all, and if so how, too parse + convert Roc to javascript, turning Roc into a viable replacement for Elm

view this post on Zulip Richard Feldman (Feb 13 2024 at 14:16):

it's an explicit non-goal of the project to emit JavaScript, but if you wanted to try it yourself on a fork, the minimal change you'd need to make would be to add a new gen_ crate (like gen_llvm or gen_dev) which would go from mono::ir to whatever output you wanted

view this post on Zulip Hannes (Feb 13 2024 at 14:22):

A better (or maybe just easier) way to use Roc in the JS world would probably be for someone to create a platform that compiles to wasm and provides access to parts of the JS stdlib. Then you would load the wasm file in JS and hook up the wasm calls to JS calls. It would be weird but i think it would work, right?

view this post on Zulip Richard Feldman (Feb 13 2024 at 14:24):

right, in general that's how wasm in the browser works :big_smile:

view this post on Zulip Richard Feldman (Feb 13 2024 at 14:25):

the wasm itself is basically only capable of doing calculations, so wiring it up to some amount of hardcoded JS is necessary to be able to do any interesting browser stuff

view this post on Zulip Hannes (Feb 13 2024 at 14:34):

Great! So someone just needs to write that hard coded JS file that exposes all of the effects in the JS stdlib and that's basically the same as compiling to JS :sweat_smile:

view this post on Zulip Pearce Keesling (Feb 13 2024 at 15:56):

Something I've always seen handwaved in wasm "code sharing" or the like is referential integrity. A lot of JavaScript optimizations rely on it and I worry that dropping a wasm bundle in would prevent any sort of "share you business logic using a roc module that your existing code can use" migration path

view this post on Zulip Pearce Keesling (Feb 13 2024 at 15:57):

The nice thing about compile to JS is that there is no to/from wasm conversion that breaks those optimization (obviously there are other pitfalls, but that's just one)

view this post on Zulip Brendan Hansknecht (Feb 13 2024 at 16:33):

If you want JS compilation, why not just use Elm?

view this post on Zulip Brendan Hansknecht (Feb 13 2024 at 16:34):

"share you business logic using a roc module that your existing code can use" migration path

Also, I'm not really sure how a wasm bundle stops this, can you explain more?

view this post on Zulip Brian Carroll (Feb 13 2024 at 23:26):

What is referential integrity? Is it related to referential transparency?
I've done a lot of webassembly work but I'm not following this point.

view this post on Zulip Pearce Keesling (Feb 14 2024 at 05:08):

For sure, let's say that you have a mobile app and a web app and you want to share some logic in a common roc module (basically along the lines of kotlin multiplatform), elm won't run in a non-browser environment so I don't think that's an option.

view this post on Zulip Pearce Keesling (Feb 14 2024 at 05:10):

Referential integrity is basical JavaScript's way of saying pointer comparisons. It is a common optimization to check object (essentially pointers to records) equality by just comparing the references themselves. If they reference the same object they are equal , or perhaps more importantly if they don't have the same reference you assume they are not equal

view this post on Zulip Pearce Keesling (Feb 14 2024 at 05:11):

From what I understand of wasm, if I'm using any data inside of wasm from js-land then I have to marshall it across the wasm-boundary, and then if I return the data I would marshall it back across the boundary and end up with a different reference (and in this case most likely a deep copy), this would make it unusable in a lot of common js patterns.

view this post on Zulip Pearce Keesling (Feb 14 2024 at 05:12):

For example selectors in redux rely heavily on referential integrity in order to avoid triggering re-renders, if the reference changes each frame then it can't avoid doing deep comparisons which are slow

view this post on Zulip Pearce Keesling (Feb 14 2024 at 05:14):

The way most wasm-based web frameworks do stuff is they shift as much as possible into the wasm side so all that is ever marshalled across is the minimal DOM changes, no application data

view this post on Zulip Pearce Keesling (Feb 14 2024 at 05:15):

This isn't a problem outside the browser because there doesn't have to be much marshalling to cross the C ffi. Presumably a platform could just "understand" a roc type and it's all good to go

view this post on Zulip Pearce Keesling (Feb 14 2024 at 05:20):

Note: I should have used the term referential equality not integrity. Related concepts but not exactly the same, and probably confusing that I used the wrong one

view this post on Zulip Pearce Keesling (Feb 14 2024 at 05:27):

I also think it is totally fine to say "swapping out a redux store in a react app for a roc module is not a use case we think is in scope". Just pointing out that there are reasons people like compile to js over wasm for some use cases

view this post on Zulip Luke Boswell (Feb 14 2024 at 20:32):

@Pearce Keesling have you seen the virtual dom example? That might be good to see some ideas for managing the WASM boundary and sharing logic on front and back ends.

view this post on Zulip Pearce Keesling (Feb 14 2024 at 21:17):

Yeah, I think that is a great strategy for when a whole slice of your ui is going to be in roc. I don't think it avoids the problems when you're embedding just logic into a react app.

view this post on Zulip Pearce Keesling (Feb 14 2024 at 21:19):

For example a real use case we have at my company. We have a list of transactions that's 10s of thousands of times long. If I want to update a single transaction I need to send it all across and then update a value and send it back. In order to use wasm I'd need to find a good "cutting point" to minimize the amount of serialize/deserialize I have to do. If it's just js I can plug it in way easier

view this post on Zulip Brendan Hansknecht (Feb 14 2024 at 22:38):

Given how roc handles effects, I think it will always have some complex edges in this area. Fundamentally a good "cutting point" is required to use roc in general. That is what a platform hopefully is.

view this post on Zulip Brendan Hansknecht (Feb 14 2024 at 22:43):

I do agree that wasm makes this more complex. For this cutting point, you might:

Any of these might mitigated the issue, but fundamentally, performance would need to be measured.

view this post on Zulip Pearce Keesling (Feb 14 2024 at 22:53):

Absolutely, all of those are reasonable routes. It's all about tradeoffs

view this post on Zulip Richard Feldman (Feb 15 2024 at 17:45):

Luke Boswell said:

Pearce Keesling have you seen the virtual dom example? That might be good to see some ideas for managing the WASM boundary and sharing logic on front and back ends.

I think a really interesting concept is using this pattern for targets other than the browser

view this post on Zulip Richard Feldman (Feb 15 2024 at 17:46):

like in general if you have a Roc function whose purpose is to quickly return a description of how you want the UI to look, and then the platform's job is to translate that into actual visuals...

view this post on Zulip Richard Feldman (Feb 15 2024 at 17:47):

you could implement something in the browser which does that, sure, but in theory you could do the same in Swift on iOS, calling the Roc function via Swift's C FFI

view this post on Zulip Richard Feldman (Feb 15 2024 at 17:47):

and same thing on Android

view this post on Zulip Richard Feldman (Feb 15 2024 at 17:47):

same thing on desktop, etc.

view this post on Zulip Pearce Keesling (Feb 15 2024 at 17:48):

I noticed that one of the open native devs is working on decoupling react native from react. I think I tagged @roc_lang in the tweet thread. That might be a super interesting foundation to build on since react native is essentially a C FFI for native views

view this post on Zulip Luke Boswell (Feb 18 2024 at 06:34):

@Pearce Keesling any chance you could dig out a link? that sounds interesting.

view this post on Zulip Luke Boswell (Feb 18 2024 at 06:40):

Also, somewhat related to the above.

I've been expanding on my roc+htmx demo, refactoring it and generally tinkering. I think it's a good sandpit for developing basic-webserver features and trying out ideas.

But I wonder if anyone else would be interested in tinkering with it also? I thought I might ask because if anyone would be interested in making PRs and generally adding random features then that might be fun.

There is no overall direction or anything, I'm just doing the next thing that pops into my head, a random exploration of different ideas for building web apps with Roc. To be honest, I have spent most of my time just rebuilding things I've already built and refactoring.

I want to challenge myself to write up a blog article every now and then to capture some of the things I learn along the way.

It's currently sitting in a private repository... I should probably make it public anyway.

Thoughts?

view this post on Zulip Pearce Keesling (Feb 18 2024 at 16:12):

This is the tweet in particular but he's been posting a lot about it this week https://x.com/birch_js/status/1757743078738469145?s=20

view this post on Zulip Jeffrey Mudge (Feb 20 2024 at 00:56):

Luke Boswell said:

I've been expanding on my roc+htmx demo, refactoring it and generally tinkering. I think it's a good sandpit for developing basic-webserver features and trying out ideas.

But I wonder if anyone else would be interested in tinkering with it also? I thought I might ask because if anyone would be interested in making PRs and generally adding random features then that might be fun.
...
Thoughts?

I've been wanting to learn htmx and expand my limited roc knowledge, so this is cool. I went ahead and created a PR with a feature to add a button to mark a task as completed. https://github.com/lukewilliamboswell/roc-htmx-playground/pull/1

If you don't want to merge it, I won't be offended. I'm just thankful that you created the playground and gave me a good spot to experiment.

view this post on Zulip Luke Boswell (Feb 20 2024 at 01:18):

Awesome :heart_eyes: I can have a closer look at this later. It's hard to read on my phone, but super cool. How did you find roc + htmx + sqlite? I think they're a pretty nice combination so far.

view this post on Zulip Jeffrey Mudge (Feb 20 2024 at 01:30):

I find them pretty nice! There are some rough edges and oddities to roc for me still, but building the client side interaction in the element attributes feels good. Having a server side elm-like language is amazing, and the unexpected bumps are an indication of the promising future. You'd already done the hard work with the sqlite stuff, so I just had to write a query and use your existing connection, so I don't feel like I can comment on that too much, but it does seem like a good choice.

view this post on Zulip Jeffrey Mudge (Feb 20 2024 at 01:34):

Sorry about the formatting changes in my PR. The roc formatter is set to auto format when I save. I probably should have tried to isolate that to a single commit, or turned it off. But I wasn't intending to make a PR when I started messing around, I just wanted to see if I could get it to run, and then wanted to see if I could add a feature. It was only when I'd finished that I thought I should make a PR out of it.


Last updated: Jul 06 2025 at 12:14 UTC