[HN Gopher] StimulusReflex, or LiveView for Rails
___________________________________________________________________
StimulusReflex, or LiveView for Rails
Author : nanna
Score : 179 points
Date : 2021-01-15 11:41 UTC (11 hours ago)
(HTM) web link (docs.stimulusreflex.com)
(TXT) w3m dump (docs.stimulusreflex.com)
| cpursley wrote:
| I appreciate the work put into this, glad to see SPA alternatives
| and can understand using this for existing Rails projects.
|
| I'm curious why would one would choose this over Phoenix LiveView
| for a new project? How are the two different?
| freedomben wrote:
| I use Phoenix primarily (for web apps) so I of course agree
| with you, but the obvious answer is "anyone doing rails can add
| this easily without changing languages/stacks." That alone
| addresses a massive segment, probably much much larger than
| Phoenix
| hpvic03 wrote:
| The Ruby/Rails ecosystem is massive, and remains extremely
| productive and pleasant to work with.
| sodapopcan wrote:
| I would love it if Elixir grew in popularity but I'm also happy
| other ecosystems are hopping aboard this ship. I absolutely
| love working this way and hope it becomes more of the norm.
| fareesh wrote:
| Instinctively this looks like something that works great for
| simple concepts. Does anyone have any experience integrating this
| for a complex project or UI? Would love to hear more.
| [deleted]
| wim wrote:
| Closing the gap between server and client in terms of app
| development is definitely the answer. Also agree with the pitch
| that the currently popular approach of simply moving everything
| to the client has made tooling incredibly complex (although it's
| getting better). It's great to see new tools like this being
| built.
|
| Moving everything to the server instead also closes the gap, but
| the obvious problem is that this introduces a lot of latency for
| UI interactions. Ajax page loads/Turbolinks works so well because
| it actually makes things faster with almost zero effort.
| Introducing a similar method for every UI interaction though is a
| different matter, and I don't see how the latency won't be
| noticeable.
|
| For instance, The TodoMVC example's server seems to be far enough
| way from my location that creating a task has noticeable lag.
| Sure it's just an example, but without introducing some client-
| side/optimistic rendering, that's going to be hard to avoid (and
| that would defeat the purpose of having all your logic in one
| place, on the server). Not sure how this is addressed here?
| sodapopcan wrote:
| Even with tooling getting better, you're still faced with
| creating an API to the backend that has a high chance of your
| frontend being the only ever consumer of it. You're also faced
| with duplicating logic on both front and backends in many
| scenarios (though of course this can be mitigated with a node
| backend? I don't know... I've never used node).
|
| As for latency, this is over websockets. It becomes a problem
| if you are connecting to a server across the ocean but
| otherwise, it's incredibly fast and feels just as snappy as JS.
| I actually also haven't used Stimulus Reflex, just Phoenix
| LiveView so I'm not sure if they are exactly the same, but the
| TL;DR is that they are sending VERY tiny payloads over
| websockets. This video explains it well (though it's also a
| demo of LiveView): https://www.youtube.com/watch?v=MZvmYaFkNJI
| nickjj wrote:
| > the TL;DR is that they are sending VERY tiny payloads over
| websockets
|
| If you have a server in NY and you happen to live in Germany
| it's going to take about 100-120ms to do a network round trip
| in a best case scenario (high quality wired cable connection)
| even with a 1 byte payload. For most websites running in 1
| datacenter that means a massive population of the world is
| going to feel that latency.
|
| That's why I'm not sold on using LV and websockets for
| everything (such as transitioning from page A to B, etc.).
| Hotwire Turbo Drive / Frame uses HTTP which means you can
| cache responses and send back 304s when the content doesn't
| change. HTTP feels like the right protocol to do this, and
| then you can save Websockets for when you need to broadcast
| relatively small amounts of new / updated / removed content
| to 1 or more connected clients. That's what the Hotwire model
| provides.
| e12e wrote:
| > which means you can cache responses and send back 304s
| when the content doesn't change.
|
| Unless I misunderstand - that's still a round-trip to fetch
| and return a 304? Or are you thinking an edge cache closer
| to the end-user?
|
| (I don't disagree that websockets aren't a universal
| solution - but if used as server push - it's difficult to
| see how plain http could have lower latency? Long polling
| would be similar, but probably (even) harder to scale if
| you want 10k+ open connections?).
| Existenceblinks wrote:
| Yeah, am silently on your side on this point everywhere you
| go! Because I already said once and done a good fight.
|
| Stateful (I mean really keep things in assigns) sounds like
| an inefficient caching. Not all assigns are per user,
| caching the same things on each process is redundant. And
| to share these things as one set of data is to put them
| somewhere else, most likely in a process under the root
| supervision tree. And there's less point for using LV.
|
| Folks forgot how fast Phoenix.View rendered from controller
| was (a hello page is microsecond!) it's pretty damn good.
| sodapopcan wrote:
| I addressed this in another reply but TL;DR, these
| solutions are totally use-case dependent and they don't
| pretend to be one-size-fits-all (or at least LiveView
| doesn't).
| wim wrote:
| Oh definitely, totally agree the status quo of duplicating
| logic is unnecessary.
|
| And I realize this is using websockets, and that the payloads
| are tiny, but you can't fight the speed of light ;), so it's
| more of a latency concern (vs bandwidth). So in order to
| truly keep all the state and rendering with the server, even
| the smallest UI interaction would require a round-trip, and
| unless you'll have end nodes all across the country, that
| seems like it will noticeable.
|
| With some actions like "search", "save" or "reload" I would
| expect a spinner and delay anyway, so that's not a problem.
| But if opening a dropdown menu or adding an item to a list
| (like in the example) feels slow that might not be the best
| user experience. But perhaps it's not a problem in practice,
| I haven't seen too many examples.
| sodapopcan wrote:
| Yep, it definitely can be a concern! It takes a lot of
| distance before latency starts to be noticeable so it all
| depends on our use-case. These tools aren't one-size-fits-
| all. Lots of people are building things that aren't going
| global--at least not right off the bat--so these tools
| provide a way of moving very quickly out of the gate (no
| need to build an API for yourself, no need to duplicate any
| frontend and backend logic). If you do go global, you're
| probably in a good place to start serving your global
| customers from servers closer to them--the company I work,
| for example, for has to do regardless. And that fits under
| "a nice problem to have" which can be solved after your
| business has been validated.
|
| But yes, there are many cases where this will not work.
| It's just a verrrrry attractive option when it can.
| [deleted]
| benzible wrote:
| In the Phoenix LiveView world, the solution has been to use
| Alpine.js for user interactions that don't involve loading data
| from the server [1]. Alpine and LiveView are the AL in the
| "PETAL stack" [2]
|
| [1] https://dockyard.com/blog/2020/12/21/optimizing-user-
| experie...
|
| [2] https://changelog.com/posts/petal-the-end-to-end-web-stack
| heleninboodler wrote:
| I hope their form validation demo is just a toy and not an actual
| example of real email validation code, because it doesn't handle
| '+' in the localpart, which is a very commonly used character. I
| don't see any custom validation code in the demo source, though,
| so it kind of looks like they have a builtin "email" validator
| that's broken, which makes me question the production-readiness
| of this thing.
| rolae wrote:
| That was a regression in version 3.4, fixed here:
| https://github.com/hopsoft/stimulus_reflex/pull/418
| adenozine wrote:
| Does python have anything like this?
| adparadox wrote:
| More of a port of Laravel's Livewire (so only AJAX calls, no
| websockets), but I've been working on something similar for
| Django at https://www.django-unicorn.com/. I also detail other
| options at https://www.django-unicorn.com/docs/#related-
| projects.
| julianrubisch wrote:
| https://pypi.org/project/django-sockpuppet/
|
| It's a SR clone, the maintainers are actually very active in
| our community :-)
| shinryuu wrote:
| or link to actual repo ->
| https://github.com/jonathan-s/django-sockpuppet
|
| (I'm the maintainer).
| m4r71n wrote:
| Django does: https://github.com/edelvalle/reactor
| tbran wrote:
| htmx [1] (formerly intercooler) is sort of similar, although
| the server instead returns html fragments.
|
| Here's an example [2] of using it for infinite scroll (instead
| of pagination).
|
| I'm pretty excited to try out django-sockpuppet from an
| adjacent comment!
|
| [1]: https://htmx.org/ [2]:
| https://engineering.instawork.com/iterating-with-simplicity-...
| rkangel wrote:
| This comment I have just made applies equally to Python as to
| Ruby I think:
|
| https://news.ycombinator.com/item?id=25791181
| theptip wrote:
| What's the missing feature? Native M:N green threads? Seems
| to me that Python's async is a fair bit more mature than
| Ruby, so the comparison here is not obvious to me.
| rkangel wrote:
| The conclusion I have come to is that the way you interact
| with the concurrency model is just as important as what the
| model is underneath. Erlang (and Elixir) have got both
| levels right - M:N scheduling underneath, and the actor
| model (with excellent library support) on top to best take
| advantage of it.
| Robin_Message wrote:
| In many ways, this is very cool.
|
| But, I have to admit, I don't love it. I would love to have an
| integrated environment where client/server doesn't matter, but I
| don't think this gets far enough. Working in a spread of html.erb
| with special tags plus some Javascript doesn't feel great to me
| compared to React.
|
| I like their TodoMVC app, since that gives a simple, minimal
| starting point. Getting persistence in that few lines of code is
| nice.
|
| However, it has also at least one bug compared to canonical
| TodoMVC. I think the problem of this kind of too-clever binding
| is that it makes this kind of bug easy to introduce; whereas
| something with clear one-way data-binding like React, for all it
| can be verbose and annoying, tends to make it easier to get this
| sort of thing right.
|
| (The bug? Click an existing todo to edit it, start typing, then
| press escape. The edit is meant to be discarded, but instead
| you'll see a flash of the old value and then the new value is
| persisted. It's not the worst bug ever, but shows that even in a
| simple app, experts can subtly screw up important behaviour.)
| hpvic03 wrote:
| Here comes the classic HN middle-brow dismissal :)
|
| TodoMVC is meant to be a minimalist demo, not a battle-hardened
| app.
|
| We switched from React to Reflex 7 months ago. We have fewer
| bugs than we did with React, and we ship things about 3 times
| faster.
|
| 5/5 of us strongly prefer Reflex over React. Including one of
| us who was a big React aficionado beforehand.
|
| Just wanted to put that out there for anyone considering
| Reflex, a bug in TodoMVC is not a harbinger of a bad framework.
| Robin_Message wrote:
| That may be fair :)
|
| Personally, I enjoy React on the front-end but don't
| currently like any back-end framework, so Reflux may well be
| better in aggregate.
|
| (FWIW, I have a PhD in computer science and big part of that
| was on web applications and frameworks for them, combined
| with ~15 years commercial experience mastering web
| development, so this wasn't meant to be a middle-brow
| dismissal. As I said, it is exciting, I'm just not convinced.
|
| I think there is some merit in the argument that too much
| cleverness can be dangerous. Battle-hardened is tricky; I
| agree TodoMVC is meant to be a minimalist demo, but if a
| minimal demo can have subtle bugs caused by the cleverness of
| the data binding, how much more so a real app with a much
| more complex data model?
|
| But I guess it does eliminate whole other classes of bug, so
| I can believe it works less buggy and more productive better
| than React+some back end.
|
| I certainly find the current front/back split endlessly
| painful. I am also excited by the new React Server Components
| which might be another good solution to that.)
|
| EDIT TO ADD: I guess what I was trying to say is: I found
| this interesting, and I looked at it, and then I found this
| bug in the example, and I wonder if this framework might make
| a bug like that more likely because the power of making some
| things easier is obscuring what is happening in some cases,
| and I don't know if that trade-off is worth it.
| treis wrote:
| My experience bears this out as well. Things that "just
| work" usually don't do that and/or come with a list of
| significant caveats.
| sodapopcan wrote:
| I love hearing this story! I'm not in the job market since I
| love where I work at the moment (though don't love our tech
| stack) but I'm really hoping to find something, preferably
| using LiveView, for my next move. It's really nice to hear
| about companies having success with this kind of tech! It's
| the first tech I've been really excited about since learning
| Rails eight years ago (which was far too late!)
| k__ wrote:
| Isn't Reflex a Haskell framework?
|
| Switching from React to Reflex isn't just switching a
| framework, but a whole stack.
| [deleted]
| cargoshipit wrote:
| Has anyone used LiveView and this enough to give a comparison of
| the dev UX? I've mainly used LiveView for a side project and have
| quite enjoyed it.
| thomasjk wrote:
| Using StimulusReflex in my latest project, been a good experience
| to work with. The community on Discord is very active and
| helpful, and the docs are top-notch.
|
| Check the StimulusReflex Expo for interactive demos w/ code
| samples: https://expo.stimulusreflex.com/
| [deleted]
| augustl wrote:
| FWIW, I'd add a word of caution for this architecture. Coming
| from an SPA, it feels just like your average react/redux app,
| except you put your redux state on the server. Your server now
| maintains the state of all active clients, and you get network
| lag on all stateful UI interactions.
|
| Now that Google will index SPAs, I'd strongly consider a SPA
| where the server just generates meta tags (for SoMe link previews
| etc)
| IggleSniggle wrote:
| > you get network lag on all stateful UI interactions
|
| Isn't this kind of a good thing, though? Now your UI can't lie
| to you about the true application state, making you think
| something worked or completed when in fact it's still
| interacting with the server. /s
|
| I like SPAs because they can work offline / on spotty network
| connections. I don't like SPAs because they are often unclear
| about whether or not they are fully synchronized with their
| backend. I kinda wish people writing SPAs just wrote totally
| offline apps _first_ that then had an independent
| synchronization mechanism with their respective backends as a
| general rule.
| lawwantsin17 wrote:
| The docs are so full of opinions and sales speak it's disgusting.
| miki123211 wrote:
| > This entire round-trip allows us to update the UI in 20-30ms
| without flicker or expensive page loads.
|
| A lot of people have much worse ping times than that. Try using
| this on a satellite connection for example, and your experience
| won't be very pleasant.
|
| On my internet connection, which is pretty average by polish
| standards, the best ping I can get is 30ms, and that only happens
| when the server I ping is just one or two hops away. I probably
| won't be able to go under 100ms when the server is in the US.
|
| It seems like this approach sacrifices runtime performance for
| development speed. I feel like it might often be a good tradeoff
| to make, but it's a tradeoff nevertheless, and we should
| recognize that. Separate layers for frontend and backend
| introduce complexity, but client side code is client side code,
| you can't go much faster than that.
| akanet wrote:
| I can imagine this simplifying the development of B2B SaaS tools
| that are primarily about presenting and interacting with data.
| The bit about broadcasting to a large number of clients is harder
| to see the value of in a Rails application when so many
| approaches work simply enough already.
|
| As for replacing rich frontend rendering libraries in more
| complex apps - it seems dicey. Part of the virtue of React is
| that it simplifies the visual presentation of the frontend based
| on a constellation of data. Things like highlighted elements,
| hover states, and dragging items. It seems difficult to enable
| that level of polish while the backend is making dom-level
| changes based on the explicit data that you have to deliberately
| send over the network.
| amoitnga wrote:
| was looking for this sort of comment to confirm my bias. I'm
| trying to figure out what is it about how I feel about reflex:
| the idea that even with this you still have to reach for js
| libs or am I just being lazy. I guess a little bit of both
| maybe.
|
| But it's true, even though our app is pretty straight forward
| crud, we still need things like autocomplete, drag and drop,
| tabs, modals, form validation etc. Just having js being js and
| ruby being ruby seems easier for me to parse and work with.
| tra3 wrote:
| I love that Rails continues to evolve. I've invested so much time
| in it that it's good to know that Rails is still a viable choice
| for modern work. If someone's creating new cool stuff like this,
| then I'm not the only one.
| joelbluminator wrote:
| I feel the same. I'm invested and I actually like developing on
| it (biased of course). I don't see any reason to worry about
| Rails jobs disappearing, Rails is here to stay. It's soon
| turning 20 forchrissake!
| raffomania wrote:
| To me, this looks like one of the few real ways out of the
| madness that is modern frontend development. Excited to see the
| approach gaining adoption!
| whalesalad wrote:
| I don't think this holds up anymore. Tooling has come so far.
|
| I have never in my life been as productive as I am inside of a
| Vue/Tailwind code base at this point.
|
| One of my clients is a fairly vanilla Rails 4 app (which is
| arguably a friendly place to be - although slow) and it's not
| even close. I miss Vue and having a full "app" environment on
| the front-end side constantly. Jumping back and forth between
| these projects is like going from a hot and steamy comfy
| jacuzzi into an icy cold pool.
| freedomben wrote:
| I agree with you, but it took a long, long time to get that
| good and comfortable with react (in my case) years actually
| since I don't only do frontend.
|
| For people who haven't already climbed that mountain and
| learned a new "language" I agree with GP. This could be a
| game changer.
|
| My only regret is that for a while now JavaScript had
| basically been the standard. As good a development as I think
| this is, it will really in more fragmentation and less
| general purpose devs.
|
| Nevertheless I think it's good, and web assembly was always
| going to do this to JavaScript ecosystem anyway.
| rorykoehler wrote:
| The JavaScript framework era always felt like a bandaid
| while we figure out something better. I'm convinced
| liveview is the future.
| sodapopcan wrote:
| You can certainly still use tailwind here.
|
| Otherwise, the point is that you won't have to jump back and
| forth--you can just stay on the backend. I've actually never
| used Stimulus Reflex, but in LiveView, I'm writing very small
| bits of JS maybe 2% of the time.
| ericb wrote:
| Speaking of, DHH looks like he's using tailwind with Rails,
| so the use-case is getting some love! DHH created this gem:
|
| https://github.com/rails/tailwindcss-rails
| porker wrote:
| > I have never in my life been as productive as I am inside
| of a Vue/Tailwind code base at this point.
|
| For what kind of app? Crud, frontend to a SaaS, something
| else?
|
| I am still finding form-heavy apps needing frontend+backend
| form validation to be faster to write entirely server-side.
| Which is painful as more and more I have field types that are
| best off as JS widgets, and enhancing server-rendered forms
| is a pain.
| anonygler wrote:
| A tiny payload from the world's slowest backend framework.
|
| The Rails community has spent years resisting the future. Ember
| was an attempt to jam Rails into JavaScript and it's been a
| miserable, confusing, slow mess that every team utterly regrets.
|
| Rails has spent years and years pushing server-side rendered
| partials. Now the Rails community has yet another "new" approach
| that involves writing yet more Ruby instead of JavaScript.
|
| If you adopt any of these Ruby-for-frontend solutions, your
| future efforts to scale will be severely hampered as you've glued
| so much stuff down in Ruby. Plus you'll have trouble hiring JS
| developers, because who wants to learn something so unserious as
| this?
|
| Write your web frontend in JavaScript. Either be a polyglot or
| create silos.
| rkangel wrote:
| It's worth pointing out that the Phoenix Web Framework (which
| LiveView is built on) came into being because the creator Chris
| McCord tried to build something like LiveView in Ruby and
| eventually ran into fundamental limitations due to how
| concurrency was handled. He looked around, discovered Elixir and
| the rest is history.
|
| I'm very interested to learn what has changed since then that
| made this possible, or made it work better. Or whether those
| problems are just being "lived with".
| bestinterest wrote:
| There's a project called AnyCable which replaces ActionCable to
| give Rails the real-time performance equivalent of LiveView.
|
| See this https://evilmartians.com/chronicles/anycable-
| actioncable-on-...
|
| Looks like having 20,000 idle clients connected to a server
| sits at only 380MB and Erlang is at 737MB.
| deedubaya wrote:
| I've had good success with AnyCable
| jakswa wrote:
| Thanks for posting this. I need to try it out. I'm
| specifically curious about how it performs when a certain
| amount of those 20k connections are busy and generating
| traffic. If I'm understanding, the anycable-go connection to
| ruby is over RPC? So individual websocket messages generate
| requests to ruby? I could see this performing better for idle
| connections, that's for sure.
| julianrubisch wrote:
| I'm really excited for Ractors in this content and how/if
| they could improve the Ruby side
| ksec wrote:
| I remember there were still latency issues, with 99th
| percentile being well over 100ms.
|
| Cant find the link to the article though.
| bpicolo wrote:
| > Looks like having 20,000 idle clients connected to a server
| sits at only 380MB and Erlang is at 737MB.
|
| That's with Go, versus with anycable itself. Anycable-go
| looks like 798?
| PedroBatista wrote:
| Wish I had the time to really study Phoenix's LiveView and
| implement the same in Java.
|
| AFAIK there's no equivalent for this in Java and I mean the same
| not kinda-the-same but not really like Vaadin or God forbid GWT.
| scns wrote:
| Wish?
| PedroBatista wrote:
| thks
| dnautics wrote:
| Good luck. Liveview depends strongly on features of the erlang
| VM that you won't get right without a deeper understanding of
| erlang (how do you clean up a websocket connection when the
| actor exits early, say due to throwing an exception - that's
| zero lines of code in lv), you're probably better of taking
| inspiration and writing it from scratch.
| entangled999 wrote:
| So in your opinion in Java land resources are always leaked
| when some exception occurs? That's a bit far from the truth
| pibefision wrote:
| Russ Hanneman feels positive about stimulus reflex
| https://www.youtube.com/watch?v=utxCm3uLhIE
| wes-k wrote:
| Ha that was well worth the watch, ty!
| bithavoc wrote:
| How did they get the actor to play this, amazing.
| [deleted]
| arusahni wrote:
| Assuming Cameo?
| julianrubisch wrote:
| It's called ,,money"
| sudhirj wrote:
| DHH recently introduced Hotwire https://hotwire.dev/ which
| already does something similar. Any idea what the difference is?
| julianrubisch wrote:
| in one word: morphdom (https://github.com/patrick-steele-
| idem/morphdom)
|
| also, StimulusReflex predates Hotwire for 1 year and is already
| pretty hardened :-)
| sudhirj wrote:
| So this receives the full HTML page and does a near-zero-
| damage "morphing" as opposed to Hotwire which either does
| full page dumb replacement or asks you to define which
| sections to replace? Does that sound right?
| nickjj wrote:
| > as opposed to Hotwire which either does full page dumb
| replacement or asks you to define which sections to replace
|
| It's not that dumb in practice because for a lot of things
| Hotwire uses HTTP instead of WebSockets which means you can
| take advantage of what HTTP has to offer such as caching.
|
| That means if you decide to dynamically load a menu's
| contents with a Hotwire Turbo Frame then it's only sent
| over the wire once and assuming its content doesn't change,
| it'll serve a 304 content not modified for future requests.
|
| For pushing updates with Turbo Stream which is done over
| WebSockets, I'm pretty sure it'll push that snippet of HTML
| (let's say a user's comment) over WebSockets and then
| either append or prepend it to the DOM based on however you
| configured it to be inserted. And if you edited that
| comment later on, it will replace that snippet of HTML that
| was previously sent (since it's the same ERB template). It
| won't re-render the full page.
| julianrubisch wrote:
| There are a lot of wonderful upsides to this approach,
| yes.
|
| It's just... people think those technologies are
| congruent but the overlaps are actually minimal.
|
| For any rather sophisticated UI you can (and will want)
| to use both.
|
| For example: repaint a data visualization. With Hotwire
| you can only replace it and start fresh, with SR you can
| just surgically morph data attributes without
| disconnecting your stimulus controllers
| rolae wrote:
| Exactly.
|
| Basically all you to is to call a remote procedure, which
| you can do by adding a simple `data-
| reflex="click->Todo#toggle`. In the remote method you
| change something about the state (for example db, redis).
| The server rerenders the page and morphs the difference.
|
| If you need more control you can get it by defining which
| elements to render and to morph.
| joelbluminator wrote:
| Well Hotwire is running on Basecamp (or Hey?) , its not some
| half arsed solution...
| julianrubisch wrote:
| For sure! It just doesn't really overlap.
| [deleted]
| HorizonShadow wrote:
| They don't really have any overlap.
|
| Hotwire is for replacing frames with content when navigating
| through anchors or form posts.
|
| StimulusReflex is performing RPC, then diffs the old page and
| the new page, updating changed elements.
| agd wrote:
| One difference is that liveview / reflex are stateful whereas
| Hotwire (turbo) is not. This has varying performance
| implications. Turbo will do repeat work server side and
| payloads will typically be bigger, however development may be
| simpler due to lack of state and memory usage server side may
| be lower.
|
| Turbo also has the possibility to gracefully degrade when js
| is not available (although I doubt this will be taken
| advantage of much in practice).
| freedomben wrote:
| This is a great point. Plus not all platforms, hosts, and
| proxies for that matter will allow web sockets.
|
| Especially for an established rails app, allowing web
| sockets can require architecture changes.
___________________________________________________________________
(page generated 2021-01-15 23:02 UTC)