As someone that writes Elixir at $DAYJOB, I was really looking forward to replacing some JS with LiveView. However, after having used it for a simple feature, I'm not entirely sure if I will continue to use it. I realize it is still pre 1.0 and that there is still a lot of work being done on it.
My biggest complaint is that if your server restarts for any reason (say, a rolling restart), you currently lose all state that was on the server[0]. There appears to be some kind of workaround for forms currently, but for anything more complex, I would need to write JS in order to attempt to not have my page get reset to the default view. So if I need to write JS already, I may as well just write JS (or something that transpiles or JS/WASM) to have fewer moving parts.
In my ElixirConf keynote, I highlighted how automatic form recovery is on the roadmap, provided we can determine that such a recovery is possible on reconnect. More advanced dynamic forms will require manual recovery, and as you said it can be done today, with 20 lines of JS:
https://gist.github.com/chrismccord/5d2f6e99112c9a67fedb2b85...
We are going to formalize the idea of a "stash" to send back up client state on reconnect, which would remove the need for this JS entirely. It is also worth noting that if someone packaged up that 20 line gist into a JS package, your application or anyone else could do `<form ... phx-hook="SavedForm">`, so "need to write JS anyway so might as well write a JS app" isn't quite accurate because it's a tiny escape hatch that doesn't require throwing away or rewriting any feature. Writing 20 lines of JS to keep shipping LV features is much different than rewriting an entire application in JS. I would actually argue the fact you have the escape hatch in this scenario is one of the merits of the library. Anyways, I hope we can keep you around once other features continue to land :)
Yes, in the above gist the connect are params used, so connect params are a general purpose mechanism for state recovery. In the above example a form is used, but on mount you can do whatever you'd like with the data. Thanks!
Will the data in the “stash” need to be verified on the server? Currently I treat connect params as user data and parse and verify it. I’m unclear if a more general data stash would cause potential security issues.
Secondly, has there been any discussion for supporting server side draining or moving the process to another node?
Other than State issues ( I am glad it is being work on ), How will LiveView works if your client is in say AUS / New Zealand and your Server is in US or EU with 200ms+ latency?
Poorly according to some of the demos/experiments I've tried, which AFAICT were running on the US West Coast (I'm in the UK).
For some stuff this will matter (the test was a game, which isn't what I'd use LiveView for in production), but for others, where data has to go to the server anyhow- the delay is there, even if my nice JS frontend disguises how long it takes.
That is the thing I am wondering if there are any innovative way to solve this. If you are building a small Internal Web App, or if your business is mostly operating locally within region and not globally, LiveView could very well be the best thing since slice bread, but once you add 100ms+ to it, its experience quickly worsen to the point JS is far better.
Deploy to multiple datacentres round the world, and always route an app user to the same one? But then you've got distributed databases to contend with (if required - or slow lookups against a central one).
I'd like to think Edge Compute could be used.
At the end of the day we're up against the speed of light and our options are limited.
Thanks for mentioning, this is good to keep in mind. I'm just getting started with LiveView for the first time on an internal admin. I don't have an educated opinion yet, but I'm excited about it after watching all of the ElixirConf talks.
An issue that I was having is that LV did not have any releases on hex. So you had to pull from github and pray you got a working version. This was recently fixed though, so you should always try pulling for hex if you are able.
My last "problem" is less of a problem with LV and more of a contraint of my system. I cannot guarantee that everyone using this application will have network access 100% of the time. So for a certain subset of my users, LV would not be ideal.
The author, Caleb Porzio (https://calebporzio.com/), was inspired by Phoenix LiveView to build something something like this for his preferred language/framework.
This looks very different from LiveView. In particular, as explained in Livewire's documentation on state management [1], state is either stored in a back-end service like Redis, or re-sent to the server with each request, depending on the type of property. And according to the home page, Ajax requests are used. With LiveView, a persistent WebSocket connection is used, and state is stored in memory in an Erlang process.
It was initially implemented with websockets but that meant having to actually run a websocket server alongside the PHP app to work. Caleb went the simple route by just sticking to AJAX instead. It's a difference in how PHP is typically run (mod_php or fastcgi) vs how Erlang runs (standalone server).
On his blog, he posted some videos earlier this year about the process of coming up with what eventually became Livewire, as well as a bunch of discussion on his podcast No Plans To Merge.
I’m curious to see how well it scales. One of the big selling points for Phoenix LiveView is that the BEAM is able to handle millions of concurrent connections.
Thanks for sharing, this looks really interesting. I keep hearing about LiveView, but not knowing Phoenix, it never really clicked for me. This really clarifies it for me.
That’s a nice writeup of the same sort of concept, not surprised to hear it coming from the Laravel community.
> 4. PHP re-renders the Blade template and sends back the HTML
I’m curious if it does serverside diffing too. From the LiveView talks it sounds like it sends tiny diffs across the wire rather than a lot of html each time.
Currently the diffing is done client-side, but on a recent podcast Caleb mentioned he went back to see how LiveView is doing things now and I'm sure he'll look into lightening the payload sizes similarly.
I have been meaning to play around with Elixir, Phoenix and LiveView for a while, it seems like it could replace client-side JS frameworks (e.g. React) for many use cases, especially the ones that already fully use server-side rendering.
Has anybody with lots of React experience made that switch? How is it going?
I switched my work project from Vue (which worked pretty well) to LiveView, and I’m not looking back. As the article mentions, not having to run a javascript build chain is fantastic. Writing modern JS isn’t too bad, but the complexity of writing a data api (whether JSON/rest, websockets, etc) on both the server and then client, and handling JS async data retrieval methods, is a huge turn off to me for writing new features. At least for me, being the solo developer. Big teams might find the data/UI split convenient for other reasons.
Plus, it’s fast. Rather it feels faster than it should be. Perhaps since instead of waiting for JS to retrieve data, parse it, and render, and then update, you just need the JS to update the DOM once the data arrives. Of course my vue pages were using REST endpoints for data so perhaps a websocketed vue page would feel more responsive.
LiveView still has a bit of maturing to do, but I’m really enjoying it. I’m really bullish that writing dashboards, admin pages, internal corporate tools can all be done an order of magnitude easier with LiveView or similar while still scaling decently.
Same here, we just deployed a React/Next.js app and it's been a veritable nightmare. Productivity was much worse than a normal server-side framework with a JS layer on top, especially since we've got experience with Elixir which has worked great for us.
Soon we're starting another project, and we'll go with Phoenix (which we're already using as a backend and GraphQL server) with LiveView sprinkled here and there where we need better interactivity.
Check out our "temporary assign" documentation – you only hold on to the state you need. That said, you are right that a LV application will necessarily use more memory than a stateless JSON API, but there is more nuance to the story. A LiveView application will use less resources under application operation than a single page app, for example:
- because LiveViews are stateful, we don't have to refetch/reload the state we need on every "request". Things like current_user, current organization, preferences, etc. So what we lose in memory load, we gain in reduced DB and system load, caching strategies, etc
- because LiveViews are stateful with change-tracking, we actually can send less data than the best hand-written SPA/JSON application you could write. So what we lose in memory load, we gain in reduced latency and overall data on the wire.
Not only that, but a lot of the state is essentially the same for many/all users/connections and can be shared.
Let's say in a chat app with a Redux setup I'd maintain channel users, messages, own profile details etc. in the app's own local state. With LiveView I'd only need to store the user specific stuff in this user's own state. Some of which I'd store in the socket.assigns of Phoenix Channels subscriptions even now with a conventional Redux setup.
This is an awesome example, thanks for sharing! Are you doing any sort of optimisation on the server side, or is it parsing the entire page of markdown on every key press? Have you stress tested this on really long content just out of interest?
It’s parsing the entire Markdown content on each key press right now, which is definitely suboptimal for a product but fine for my needs.
It should certainly be possible to make this more efficient by either doing some smarter diffing of the in-progress document or using an operation-based update mechanism.
LiveView doesn’t yet have event debouncing built in, but it’s in the works, I believe, and that would help, as well.
That said, it’s currently fast enough writing a post of this length that while writing, I notice no significant lag in the live updates. By the time I stop typing and look at the preview, it’s up to date.
They rolled out debounce and throttle fairly recently. There's also some very compelling work on a component abstraction (runs in same Liveview process).
This is against a Heroku hobby server. Latency is very low, as I’m on the East coast where I believe this server is.
Using LiveView, of course, requires taking round trip latency for your users into account. It currently won’t work well for some use cases where optimistic UI updates may help hide some latency. I think I read something about there being some optimistic updating in the works for LiveView, though, long-term, but I’m not sure how it’ll be done.
I’m curious why the author used phx-change function for the form, I believe a better way to do this would be the phx-keyup function attached the text field.
There’s more than one field here, it’s just not discussed in the post. The title is a separate form field that is validated and updates live on every change event. `phx-change` gives me the whole form state, which is what I wanted.
My biggest complaint is that if your server restarts for any reason (say, a rolling restart), you currently lose all state that was on the server[0]. There appears to be some kind of workaround for forms currently, but for anything more complex, I would need to write JS in order to attempt to not have my page get reset to the default view. So if I need to write JS already, I may as well just write JS (or something that transpiles or JS/WASM) to have fewer moving parts.
[0] https://elixirforum.com/t/liveview-and-rolling-restarts/2397...