Hacker News new | past | comments | ask | show | jobs | submit login
Volt: A reactive web framework where your Ruby code runs both server and client (voltframework.com)
79 points by mooreds on Nov 12, 2020 | hide | past | favorite | 62 comments



Its such a great idea, but the site seems somewhat broken. I have a constant "Connection lost" banner flashing at the top.

But I will say that in terms of productivity, Clojurescript/Reagent has been a real red-pill experience. Functions that compile to both back-/frontend. Seamless data-transfer via Transit (access front-end vars from the backend, no conversions - and simple cljs function compiling directly to React components is a very potent cocktail.


I'm intrigued - what makes it a "red-pill experience" compared to a typical typescript setup for example?


For me, the real game changer is the REPL-driven workflow you get with both Clojure and ClojureScript, but it's really hard to describe the details of how it's different than hot-reloading in the React ecosystem. I've tried many times, but my explanations seems to mostly confuse people rather than enlighten them.

So let's use the words of others instead, here is the best explanation I know about why the Clojure REPL rocks: https://vvvvalvalval.github.io/posts/what-makes-a-good-repl....

Short version is: you can send snippets of code to your REPL from your editor, and because of the common structure of Clojure apps, you can usually evaluate content in the middle of a function without having to change any code. Basically unlimited introspection into a running program.

I used to program in PHP, C#, Golang, Ruby, NodeJS/JavaScript (both backend/frontend) and some others, and no language comes close to the dev experience of Clojure. I'm sure other lisps are similar as well, but haven't used anything else than Clojure substantially.


I went down the Clojure path once and wasn't nearly as impressed as you were, apparently.


Did you actively get into the REPL workflow? If you didn't, I don't think you took properly advantage of what the language offers. Bit like using TypeScript and using `any` everywhere.

If you did get into the REPL workflow, was it not helping you be more productive? Any showstoppers?


My complaints more reside with issues I ran into with the language itself. Mainly, meaningless exception messages and insane stack traces and poor tooling within my editor of choice (at the time).

Also, I take issue with a language that touts itself as purely functional, but then builds itself off of the JVM, forcing you to use objects under the hood. You end up with some kind of weird FP/OO Frankenstein's monster that isn't _really_ FP, but also isn't _really_ OO. Also, since it is on the JVM, there is _no way_ you can actually have truly immutable objects or data structures, as much as Clojure likes to think that is the case. It places a lot of trust on the libraries that make up your program not to go into reflection and do some really annoying mutations.

If that is the case, I'd rather just use something like Erlang or Haskell which are _truly_ functional languages, not just an OO system masquerading as a functional language.

I _really_ like the syntax of lisp, and Clojure provides some really good extensions of that syntax with the way they do parameters, but in the end I just couldn't get over the issues I had with the core of the language runtime.


What you do mean by making you use objects under the hood? Are you referring to calling into 3rd party Java libraries or the implementation details of Clojure data structures that are under the hood?

If the former, the usual thing in Clojure is to make an abstraction layer for them that doesn't leak mutability into your code (or just skipping those libraries altogether if that doesn't work). But of course some things are just inherently side-effectful anyways, where you have to be mindful to isolate/refactor things like IO the edges of the system.

(And yep to echo a sibling comment, Clojure is not a purely functional language, and doesn't pretend to be one)


> What you do mean by making you use objects under the hood?

im referring to, at runtime, literally _every_ data structure you use in Clojure is an object.


That doesn't make Clojure any less functional. No matter which language you use, eventually it'll compile to machinecode and thats imperative by nature. Your code however, can be whatever it wants to be.

In certain scenarios, the object boxing does come with a high pricetag in terms of performance, but there are always ways around it and usually only a few functions need tweaking. I will concede however, that those few functions typically end up losing their elegance.


You ar going to have to stick to FP theory and stand back from computers if semantically invisible mutability under the hood disturbs you a lot.


Exceptions and stack traces I agree with you can be a bit ridiculous, probably because I'm not used to Java at all.

> Also, I take issue with a language that touts itself as purely functional

Seems to be a common misconception that still hasn't died.

Clojure doesn't tout itself as a "purely functional" language, and as far as I know, never has. It tout itself as a "practical general purpose" language where you can be pure and impure, depending on what you do.

What Clojure does advocate for, is the approach that _most_ parts of _most_ programs should functional, but you should be able to go away from that paradigm when required/wanted.

> It places a lot of trust on the libraries that make up your program not to go into reflection and do some really annoying mutations

Just for the record, in reality and practical terms, I've never had this happen to me. Now I haven't done Clojure development for more than 2 years or something, but if it was a real problem, I'm guessing I would have hit this at least once before. But never have I had a Clojure library unexpectedly mutate things it wasn't supposed to.

So yeah, if you're looking for a purely functional language, go with a language that actually tries to be purely functional, because that's not what Clojure aims for, it aims for practicality.


> Exceptions and stack traces I agree with you can be a bit ridiculous, probably because I'm not used to Java at all.

Even if you are used to java, the exceptions and stack traces in Clojure still don't make sense. This is coming from someone who was writing Java in their day job while learning Clojure at home.

> Seems to be a common misconception that still hasn't died.

Probably because it is not a misconception?

Right on the Clojure main site, it states it is a functional language, and that Object Oriented programming is overrated. With the language being built on top of the JVM you _cannot_ avoid objects (the bytecode generated by Clojure is riddled with objects). Clojure is a language that claims to be functional while building its foundations upon one of the most well-known object-oriented systems out there.

This is like building a house on top of a concrete foundation, laying some boards over the top to cover it up, and claiming the house is 100% wood. It just....isn't.

It also makes the claim that Clojure data structures are immutable. That is 100% not true, as ANY object or data structure can be mutated on the JVM at runtime with reflection.

If Clojure truly doesn't aim to be a functional programming language, then maybe they need to update their website.

> Just for the record, in reality and practical terms, I've never had this happen to me.

If you use any java libraries in your Clojure projects, there is a very high chance you will run into this. One of the 'strengths' that Clojure lays claim to is being able to leverage the Java ecosystem, while at the same time apparently also claiming that you shouldn't use libraries from Java (or if you do, write a wrapper for it).


https://clojure.org/

> Clojure is a robust, practical, and fast programming language with a set of useful features that together form a simple, coherent, and powerful tool.

> Clojure is predominantly a functional programming language

https://clojure.org/about/functional_programming

> Clojure is impure

> most parts of most programs should be functional

In the end, it doesn't matter what you can do deep down in the JVM. In Clojure land, the data structures you pass around are (mostly) immutable, unless when you use explicitly mutatable data structures.


Ruby used to be my primary language for many years and I used its REPL extensively in my day to day and found it immensely useful. Is Clojure's REPL different/better than the IRB and pry REPL workflow?


Yes, absolutely. Either it's wrong to call IRB/pry a REPL, or it's wrong to call what Clojure gives you a REPL, unsure of which one.

But basically there is a massive difference. Basically the Clojure REPL is not another process you type into, then you copy paste code into your editor. No, you usually write code like you do in your editor, then you can select snippets of code that gets evaluated in the REPL, in the context of your application, with all the running state already there.

I advice you to take a look at the link in my previous comment, which explains it better than I can, and also adds more information about why the Clojure REPL is so different, especially if you embrace it in your development workflow.

In case you missed it, here is the link again: https://vvvvalvalval.github.io/posts/what-makes-a-good-repl....


Doh... I should actually read and not just gloss. Sorry about that! I'll check out that link, thanks for the reply :)

(replying as a sibling as I suppose we have hit maximum depth)


I appologize for the late reply, its been one of those days :)

Im overdue for a blogpost on my Webdev setup/stack, but in short the main power comes from

1) Seamless transfer of data from back- to frontend and vice versa. If my DB contains a DATETIME I can load this in Clojure as a java.sql.Timestamp and pass it to the browser where its converted to a js/Date - Free data-sharing between front- and backend is a big productivity boost.

2) My usual backend Cloure code, also works in the frontend. That means I can move functions or use libs in the browser that also work in the backend - It also means that my Javascript code is now fully functional, which means 10x shorter and about 10x more robust.

3) Everything is REPL driven. Anything surprising happens in the browser I can inspect those vars that are effected in the REPL, toy with them, fix problems and update instantly. Hunting bugs is much faster this way.

4) Clojurescript functions compile to React components, zero boiler-plate: (defn banner [img txt] [:div.bannerclass [:img {:src img}] [:h1 txt]]) as an example. Thats a complete component, it will only update when the params update.

But like I said, its a bigger talk that I'll hopefully have some time to dive into sooner rather than later.


Baked-in immutability for a start. Then there's REPL-driven development, Lisp ergonomics and a real functional core. 'Tis a joy to behold.


> Seamless data-transfer via Transit (access front-end vars from the backend, no conversions

Very interesting!

A quick search did not yield any results. Could you provide a link to some article or code examples explaining this?


klipse.tech usually have good introduction material for various Clojure topics, including Transit! Here is a good breakdown with examples too: https://blog.klipse.tech/clojure/2016/09/22/transit-clojure....

Otherwise the canonical source is here: https://github.com/cognitect/transit-format


It should also be noted that, at least in my experience, you don't use the transit readers/writers directly as in the example post, but have a library like https://github.com/metosin/muuntaja do that for you.


I remember being very excited about it years and years ago but, as far as I remember, the maintainer stopped updating it and nobody was up to pick the project up.

Unfortunately the blog does not have dates but the last update on the repo is 5 years ago.

I believe this project is basically dead.

EDIT: This is the post from the maintainer I remember seeing: https://github.com/voltrb/volt/issues/357


Seems really interesting but (alas) hasn't been updated in 5 years.


I've heard that https://hyperstack.org/ took up this mantle?

Hmm, I just checked and it looks like it hasn't seen much work lately either.


Hyperstack is still fairly active, it just has a very small dev team. They're responsive on their slack channel if you ever need help.


Looks like the author was looking for someone to take over but doesn't look like that happened: https://github.com/voltrb/volt/issues/357


If you're looking for something similar (in terms of fullstack Ruby, but without Opal) go check out https://matestack.io - recently published v1.0, small but motivated team and under active development!


I think this page should link to https://opalrb.com/ - the .org domain seems to be squatted by some casino.


They mention Opal and include a link; it goes to a website for a casino.

Volt is a reactive web framework where your Ruby code runs both on the server and the client (via opal).


I noticed that too. The copy on the casino site is especially odd.

Opal Ruby to JavaScript Compiler It is source-to-source, making it fast as a runtime. Opal includes a casino comparison compiler (which can be run in any browser), a corelib and runtime implementation. The corelib/runtime is also very small.



I think your link to opalrb is incorrect. It is going to opalrb.org which....seems to be an online gambling site.

it should go to https://opalrb.com/


Ah! That link was so weird. The org site even contains this... interesting statement:

"Opal Ruby to JavaScript Compiler It is source-to-source, making it fast as a runtime. Opal includes a casino comparison compiler (which can be run in any browser), a corelib and runtime implementation. The corelib/runtime is also very small."

Casino comparison compiler?!


I just read that. That is....weird.


I've been loving the experience with Liveview. I'm currently working on an mvp for a client with it and its been amazing.

1. no friction thinking for thinking about communication between the frontend and backend.

2. js interop has been great. The hooks system allowed me to seamlessly plug in dropzone and stripe elements while keeping the rest of the frontend as elixir.

3. I can have the frontend pages react to pubsub channels and react to events from other parts of the system and update the page instantly.

3. super fast with SSR.


Is latency an issue? Applications that are only used within an organisation or within a company of a local region, where Latency wont be an issue. I am wondering if say your App is hosted in US while the user is in Singapore or Japan, what the experience will be like when you have an RTT of ~200ms.

Otherwise I really like the idea of LiveView / LiveWire / StimulusReflex, cant wait to see it mainstream.


Yes, it definitely can be. LiveView will create real problems when the user is many hops from the server. I say this as someone who has gone all in, but currently we're UK based and only serving the UK market. Multi-region scaling for liveview will certainly be 'interesting'.


Interesting, can you elaborate somewhat? What is the type of issues you are facing?

Isn't the issues pretty much the same for normal single page apps as well? Most single page apps require data loads for many actions causing maybe not interface latency, but rather data load latency.


I don’t have any experience about scaling Multi-region, but I think for these kinds of ‘apps’, the way to keep response times down is to have multi-region DB and servers. Is that true?


Thx. I really hope Phoenix team will provide a sort of default way for Multi-Region Set up. Just thinking about that complexity cause me headache.


Can't you put a load balancer in front of several elixir servers? So that the load balancer can point you to whichever is closest.

Then just share the database connection between these elixir servers.


Not straightforward as it sounds. Where is a center for all of those nodes? The edge server part is easy with Fly.io, but distributed "problem" and latency are still not great for realtime application selling worldwide.

The latency between the edge servers and the database server will give you bad UX with current "mount/3 gets called twice" strategy. Going from edge to db twice is really bad in my experience. Now you would think about adding read-only postgresql nodes on at least 3 nodes (US, EU, and Asia), $$$$.


The diff payload is also hard to get right. Morphdom is fast (not that pretty), `toString(diff)` is really slow in my application (impossible to implement smooth virtualized list, even served on localhost)


Does Liveview have baked in support for optimistic UI updates? If not, does anyone know of such a framework (any language, really) that does? That has been the deal breaker whenever I looked into similar frameworks.


Not baked in but you can use AlpineJS with LiveView as they both don't use a virtual DOM.

You can do optimistic UI and interactions that don't warrant a round trip to the server like toggling a drop down.

See the blog posts below. They explain it really well.

http://blog.pthompson.org/liveview-tailwind-css-alpine-js-mo...

http://blog.pthompson.org/alpine-js-and-liveview


sadly it does not. but you really need to either have very limited update scopes or the framework would need to bake in your business assumptions in order for offline mode to work properly. It essentially requires being able to run some business rules client-side


True enough! To me the true unrealized potential of these frameworks is abstracting away where and how exactly all the Rails/Laravel/Elixir business logic runs. If something need to run on the client, I want the framework to create the necessary JS of my backend code for me.

While I am sure there is a shit load of edge cases that would make this very hard to fully solve for all cases, I feel like a generic promise-like-structure shared between backend and frontend would already go a long way here.


It needs a universal template spec. Something like Markojs (but they can only be rendered by nodejs server), but sever languages know how to render (ssr) with data, and client know how to rehydrate into parts of client side program.


I keep seeing a Connection Lost alert on the site that is blocking the navigation bar


Same. All attempts to open a websocket connection seem to result in a 502.


Is this similar to what's behind Stimulus Reflex?


It does use websockets, like Stimulus Reflex. As for the rendering piece, it seems to be a different approach (SR is essentially dynamically rendering partials inside of a Rails view - obv I'm dramatically oversimplifying that)


I experimented with Opal and Volt several years ago. It was nice but I didn’t really have a use case since I don’t do much front end development. I am primarily a Lisp developer and Ruby is close enough to being a Lisp.


Development has stopped since 2016.

Anyone has any idea why? Watching the youtube video of "Building a Todo" using Volt from 2015 brings me back to my memory of seeing the Youtube video of Rails for the first time.


So after reading the github issues it seems the maintainer stopped in 2016 and since then no one continued the effort.


It's dead guys, last update 2016. RIP


I was really excited about Opal a few years ago and the burst of activity it enjoyed for a while, but as time has passed I've become convinced that frontend code should be frugal and opt-in as much as possible. I don't want a giant wad of isomorphic code shipped to the browser.

But writing frontend (and Webpack-friendly!) code in Ruby is still fun, which is why the modest ambitions of the Ruby2JS project excite me and I'm happy to contribute to that project nowadays.


To me it seems way more difficult to learn how to write psudo html ruby code than it is to just write html and js. I feel like Rubyists are always doing everything they can so they dont have to write JS. i.e. Coffee Script, Opal, etc. lol


I don't think its about avoiding Javascript as much as it is that Rubyists just really love writing Ruby, at least its that way for me. Javascript and React pays the bills now, but I was primarily a Ruby dev for a decade and I really do miss it.


s/Rubyists/Most backend developers/


(2016) and dead, last commit Jan 2016


An unfortunate choice of name.

See Volt DB, an in-memory database that's been around for 10 years and raised $41M. Registered trademark.

https://www.voltdb.com/

https://www.crunchbase.com/organization/voltdb




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: