19 ms·
A LiveView Is a Process
- whalesalad 3y agoThe term 'assigns' has always rubbed me the wrong way. Context or "view context" has always made more sense.
- pavlov 3y ago“Assign” also rubs me the wrong way because it’s a needless nouning of a verb. The word is “assignment” and it’s only four letters longer.
- edvinbesic 3y agoNot sure what you mean. assign ə-sīn′ transitive verb 1. To select for a duty or office; appoint: synonym: appoint. 2. To set apart for a particular purpose or place in a particular category; designate: synonym: allocate. 3. To give out as a task; allot.
- pavlov 3y agoLiveView uses “assign” as a noun.
- sodapopcan 3y agoSure that's not a great reason not to use something. If you want you can think of it as short for "assignments" just as "conn" is short for "connection" or "attrs" is short for "attributes". Just consider a coincidence that this shorthand has the same name as a verb.
- srik 3y agoAgreed, I think it was chosen because they creator comes from the ruby-on-rails world.
- derekkraan 3y agoI'm glad someone has written about this. I actually wanted to write this very blog post, and even made a crappier version of this flow chart. Why? Because people think they know what LiveView is, but they don't, because the pretenders out there (LiveWire, StimulusReflex and all the rest) are poor imitations. Don't sleep on LiveView.
- Alifatisk 3y agoI would not call out StimulusReflex and the rest like that, it all boils down to the language runtime they are built upon. They are good at what they are trying to accomplish in my opinion.
- derekkraan 3y agoYes, it does boil down to the language runtime. But that doesn't change the fact that they don't reproduce half of what LiveView can do. They didn't have to call themselves "LiveView for Ruby!" I meant it more as a PSA: if you've tried any of these other projects, you still owe it to yourself to give LiveView a try!
- Alifatisk 3y agoYou’re right, the claim of an equivalent to LiveView is a bit far fetched. https://github.com/liveviews/liveviews https://github.com/liveviews/liveviews
- stanmancan 3y agoThe best part about Livewire is that it was appealing enough to try out but bad enough that I left PHP/Laravel and moved to Elixir/Phoenix for the real deal.
- Scarbutt 3y agoOTOH, those other languages have decent ecosystems.
- 3y ago
- Alifatisk 3y agoYou misspelled "Phoenix LivViews"
- peregrine 3y agoThanks fixed.
- Etheryte 3y agoWhile the charts are nice for illustrating the flows, they could use a little bit more love. The process flowchart doesn't need to have any crossing lines, but it has multiple. While removing the crossings is a small change, it reduces cognitive load considerably.
- cush 3y agoThis is my gripe with mermaid, and is where excalidraw really took over the space. Sure mermaid can be stuck in any text file, but it's not worth the tradeoff of the diagram being unreadable.
- peregrine 3y agoYea I should have used excalidraw instead of mermaid, thats on me. I am trying to focus on writing good content and I try to not get stuck on the stuff I'm bad at which is making nicer charts.
- ketzo 3y agoHey, getting the work out there is always better than it sitting in the drafts waiting to be perfected! Thanks for the great article.
- jeremyjh 3y agoI suppose this is good basic information for people new to Erlang/Elixir, but I don't feel like it does a good job of explaining the significance of the fact that state is stored in a process, compared to other frameworks which would store the state in a dictionary and retrieve it for each event/request as its dispatched in an event loop or whatever. I'd think the dictionary approach is functionally equivalent in most respects, and could even imitate how crashes are handled in Elixir. The framework has to implement more code to do this (e.g. messages between processes might be something some frameworks don't bother to implement because its such a hassle, while its almost free in Elixir), but that doesn't matter at all to users of the framework if the features are there.
- weatherlight 3y agoIn essence, the dictionary approach you're referencing isn't entirely dissimilar to Elixir's process-based state management, and you're absolutely correct that, at a fundamental level, they both accomplish a similar task: preserving state across requests. However, I'd argue that the key difference lies in the granularity of control and the inherent characteristics of the Erlang/Elixir process model, which is designed to excel in concurrent, real-time, and distributed systems. For instance, in Elixir, every LiveView session is an isolated process that runs concurrently. This is native to the BEAM (Erlang's virtual machine), not an add-on. It's this built-in process model that allows LiveView to handle many users simultaneously, manage state efficiently, and push real-time updates, all while maintaining high performance. Fault isolation, too, is a baked-in benefit of this process model. A crash in one process doesn't affect others. While it's certainly feasible to engineer fault isolation in a different paradigm, it's a baseline guarantee in Elixir, reducing a considerable amount of potential complexity from the get-go. Elixir's supervision trees further provide a robust way of handling failures, automatically restarting processes when they crash. Implementing a similar mechanism outside of Elixir can be quite intricate and might not offer the same level of reliability. Additionally, Elixir processes facilitate straightforward and efficient inter-process communication, making it easier to build distributed and concurrent systems. Other frameworks could implement similar features, but it might not be as effortless or as integral a part of the programming model as it is in Elixir. So, while the dictionary approach can mimic some aspects of Elixir's processes, Elixir's model provides a more complete, integrated solution for building highly concurrent, real-time systems. The fact that many of these features are "almost free" in Elixir does matter, as it can reduce the complexity of application code, improve robustness, and increase developer productivity.
- osener 3y agoIs there any widely used and public web or mobile app with its entire UI built with LiveView?
- swlkr 3y agocars dot com uses it
- benzible 3y agoElixirConf 2022: "The Launch of Elixir and LiveView at Scale on the New Cars.com" https://www.youtube.com/watch?v=XzAupUHiryg https://www.youtube.com/watch?v=XzAupUHiryg
- suciptoid 3y agofly.io dashboard use LiveView
- a_bored_husky 3y agoYou can find some here: https://github.com/caspg/made-with-liveview https://github.com/caspg/made-with-liveview
- kgeist 3y agoCan a LiveView process migrate to a different machine/VM? For example, there's a scheduled maintenance and I need to shut down one of the machines/containers. The main advantage of stateless architectures for me is that state is not bound to a specific machine -- so you can easily add/remove machines, state is not lost if application dies, etc.
- sodapopcan 3y agoNot without doing that work yourself, no. I take a more classic web approach to LiveView which is to say I persist any important state right away. Like any multiple-step forms I would never store in server state, I'd persist each step. Of course that doesn't help if someone is halfway through filling out a form. If the socket disconnects then re-connects then you don't lose your work but not if you do a restart. I do wish there was a built-in way to store state on the client until it's submitted, we may get there, though! The true value of LiveView for me is the simplicity of not having to write yourself a web API to interact with your own backend as well as the dead simple real-time features. If you don't need the latter, that's fine, but having worked on collaborative apps that was a giant pain is what led me to LiveView.
- jeremyjh 3y agoNo, and while there is a capability to hot reload releases (so that you could preserve state while deploying an update, for example), in practice almost no uses it because it is complicated. In practice, if you care about this aspect of user experience you may have to take some reasonably small steps to preserve state information in the client. Form state gets preserved automatically for most purposes, though there may be some forms that need to implement a call-back to preserve state, as explained in the docs: https://hexdocs.pm/phoenix_live_view/form-bindings.html#recovery-following-crashes-or-disconnects https://hexdocs.pm/phoenix_live_view/form-bindings.html#reco...
- throwawaymaths 3y agoI think liveview live reload uses hot reloading, so that's definitely a very nice ergonomic improvement that basically everyone uses all the time
- floodfx 3y agoI think it is more exciting and more innovative to think about LiveView as a new architectural approach to building reactive applications. Yes in Elixir land it is a Process and there are some amazing things about the BEAM. But LiveViews have the potential have an impact beyond just the Elixir ecosystem and folks should embrace that. I’ve been a part of porting the Phoenix LiveView Protocol to both Javascript (https://LiveViewJS.com https://LiveViewJS.com) and Go (https://github.com/canopyclimate/golive https://github.com/canopyclimate/golive) backends and supported a friend that is porting it to Python. Ironically I think taking LiveViews outside of Elixir could actually make it easier for folks to adopt Elixir-based LiveViews in the future.
- jolux 3y agoPorting this is cool but why would people adopt Elixir if they can have LiveViews in their preferred language?
- weatherlight 3y agoErgonomics matter. Because outside of Go (and maybe Rust) it will be very difficult to actually do what Elixir does, with the same level of concurrency and fault tolerance, etc, with the same ergonomics. Ruby/Rails/StimulusReflex does something very similar, but kind of falls over unless you replace ActionCable with AnyCable which is written in Go. So now, you have to support Go and Ruby runtimes. Some developer who decided that the above was a nightmare to work with, __might__ start a new project in Elixir, to get something that actually does what Elixir does instead of just mimicking it. I'm not sure I buy this, personally, but I can understand the argument.
- troupo 3y ago> Because outside of Go (and maybe Rust) it will be very difficult to actually do what Elixir does It's just as difficult in Go and Rust. BEAM, the Erlang VM that powers Elixir, is not just about lightweight processes. It's also about guarantees that neither Go nor Rust provide. E.g. to do what Elixir does you need robust process supervision trees. You can imitate, but not replicate those in other languages.
- mrcwinn 3y agoI absolutely loved working with Elixir and LiveView. I made a decision to migrate to Python/Flask to simplify our infrastructure and move application code into one language, but I’ll miss it nonetheless!
- ashton314 3y agoThe real "aha!" moment for me with LiveView came when I was using LaTeX to render a PDF in response to some user actions. The first time I did something like this, I did some janky polling on the client side. Other (bad) solutions involved blocking the client process or just praying that the PDF would render in time before the HTTP request timed out. With LiveView, it works like this: - user pushes a button to render the PDF - the LV process calls `Task.async(fn -> do_work({data, self.pid()}))` so the worker process has the PID of the LiveView process itself - when the job completes on a different thread, the worker sends an Elixir message using the standard and highly-flexible built-in mechanism with `send()` to the PID of the LV - the LV gets the message and updates the UI and/or initiates a download of the rendered PDF automatically It is so simple to get this workflow going. It's super efficient. Perfect for low- to mid-range load on a web app. Perfect for one-person development.
- throwawaymaths 3y agoTask.async already implements a result message so you're reduplicating the effort hete. You can listen for the task.async callback from LiveView.handle_info directly, instead of having the asynchronously run function send back the message. You may want to store the ref and pid of the task in the assigns. From the docs: "Alternatively, if you spawn a task [via async] inside a GenServer, then the GenServer will automatically await for you and call GenServer.handle_info/2 with the task response..." Also if you prefer sequencing the response manually the way you're doing, Task.start_link is probably more appropriate. Note that the way you're doing it now your liveview's message queue will leak with unhandled Task.async responses and down messages (probably not a big deal given your problem domain). If you do go the Task.start_link way, you do get two way binding (if the task dies the liveview will restart itself).
- ashton314 3y agoOk, that all sounds much better. Thanks for the reply! It’s been a hot minute since I’ve used LV—so much good stuff happening. I think it’s a testament to the power of the platform that the obvious dumb solution worked so well for me. Lol
- diob 3y agoIs it a good experience for folks with high latency internet?
- lewantmontreal 3y agoWith higher latency the experience suffers. As an example liveview page navigations work via websocket which is not cacheable so navigating back/forward always needs to make a request. You really need some edge setup like fly, or only serve a geographically local audience.
- HappMacDonald 3y agoUnfortunately no matter how local you push the CDN: somebody with a crappy connection to their ISP, or a crappy router in their home, or on a tenuous wifi link in their back room or at a coffee shop will drown in the input lag all the same and inexperienced users (those whom this is more likely to happen to) will be the ones to fall into unstable interaction orbits with the UI such as spam clicking the button that doesn't appear to have acknowledged their press. The real best solution for this one major drawback I am aware of would be for Liveview to be able to generate some JS handling in their front-end widgets, more like Lambdera. That, and/or run a BEAM on the user's machine via WASM so that they don't have to dirty up their hands in even the slightest amount of javascript lol! xD
- gangstead 3y agoIt can be pretty bad especially for UI updates that you are used to being handled client side. Example: You click on an upvote button and it changes color, but there's 1 second of latency. SPA: Color updates immediately, the "upvote pressed" http/websocket call to the server arrives one second later. LiveView: liveview.js sends "upvote pressed" over the web socket, one second later the liveview process on the server gets the message, patches the dom and replies, one more second later the button changes color. Meanwhile the user has pressed the button 2 more times wondering why the color isn't updating. There are phx-hooks (https://hexdocs.pm/phoenix_live_view/js-interop.html#client-hooks-via-phx-hook https://hexdocs.pm/phoenix_live_view/js-interop.html#client-...) to address this with small targeted bits of js where you can add event listeners but it can get messy quickly.
- no_wizard 3y agoLegitimate question: is there anything Elixir / BEAM is particularly bad at? I've seen it start cropping up in some Fintech circles so I'm wondering if this language has some serious juice for concurrent data analysis or something.
- ashton314 3y agoAny algorithm that needs mutable data to be performant would be a bad fit. Numerical number crunching isn’t stellar either. That said, there are ways to extend the BEAM with C or Rust code to make those areas performant. I’ve written one such extension (called a NIF; forget what it stands for exactly) and it wasn’t all that hard.
- HalcyonicStorm 3y agoIt is historically not great at number computing. This is being addressed by a relatively new project called Nx. https://github.com/elixir-nx/nx https://github.com/elixir-nx/nx It is not the right choice for CPU intensive tasks like graphics, HFT, etc. Some companies have used Rust to write native extensions for those kinds of problems. https://discord.com/blog/using-rust-to-scale-elixir-for-11-million-concurrent-users https://discord.com/blog/using-rust-to-scale-elixir-for-11-m...
- zerr 3y agoBesides the different data transfer mechanisms (XMLHttpRequest vs WebSockets), isn't it similar to AJAX-enabled ASP.NET WebForms?
- auraham 3y agoThat diagram was really useful. LiveView itself is complex but that diagram help me understand how messages are handled within the LiveView process.