Shortcomings in LiveView - are there any I should look out for?

I think LiveView certainly has the technical potential to replace React/Vue, and for small teams that are already focusing on Elixir it will be a huge boon. I have been working on a project for the last couple years that has mainly involved converting a large amount of terrible, unorganized jQuery to a large amount of organized React+Redux, where I have been the sole BE support for a team of 7 FE engineers. It is an internal tool with standard stuff like async datatables, multi-step forms, modals, etc. Nothing fancy. In my estimation, I easily could have accomplished the same thing on my own with a designer with LiveView, probably in less time. However, I would guess that it is currently a lot easier to find 7 React devs than 1 Elixir dev currently.

5 Likes

Have you tried? I don’t think it is the case. It’s easy to find incompetent React devs, but good frontend engineers with good React experience are also very hard to get. There are also much more companies looking.

2 Likes

I was involved in the process yes. I’m not sure our experience was representative though because it’s a niche industry that tends to attract people with a specific interest in working in it, and deters others. I certainly agree it was very difficult to find extremely competent applicants, but my sense is that is generally the case when dealing with larger numbers?

This is one of the least pragmatic or measured takes on LiveView that I’ve seen yet, and the topic attracts plenty of hyperbole. I can’t imagine being able to advocate with a straight face that someone absorb the (re-)enginering cost of doing this for every page on their app without qualification or limitation or nuance. The hypothetical payoff here about skipping bundle parsing on each page view won’t break even for years, if ever.

2 Likes

Well, there’s always Turbolinks. You drop it into your project and initialize 1 line of JS and it works with a standard non-LV Phoenix app. Of course there’s differences with LV and Turbolinks, but they share the same benefits of not having to re-parse your CSS / JS bundles on every page transition.

It’s not hypothetical. It’s very well documented on the internet and many sites use this pattern. It’s why GitHub invented pjax all those years ago (Turbolinks is based on pjax) and they still use it today.

I mean, a prime example is https://changelog.com too. It’s a regular Phoenix app that uses Turbolinks. Try browsing that site by clicking the navigation links with and without JavaScript enabled. It’s a night and day difference to the point where I personally would never develop another app again without either Turbolinks or LV, and I’d only reach for LV if I needed the extra perks of what LV offers over Turbolinks.

1 Like

Depends on your target audience. A 10-year old laptop with one of the first Core i5 CPUs ever released makes a quick work of any website that has tens of MB of static content (but not huge bundles of JS making merry-go-round zig-zags in the code, obviously; there the CPU power means very little).

Browsers have been mercilessly optimising their parsing and rendering flows for decades now and they do it really well. It’s the huge soup of 20-stage JS loading and [re-]modifying the DOM that trips them (and even there the main culprit is latency; when you do 30+ round trips then of course the SPA website will be slow).

Obviously, if you expect most of your users to use cheap Chinese Android phones then it makes sense to offload the processing from the customer’s device to your servers by using LV – because those people won’t mind some latency, I imagine. But even though I am experimenting with LV currently and love it, I still don’t see myself religiously using it everywhere – especially on the landing pages!

And then there’s the hosting cost and hosting specifics. Most hosting services do well with the HTTP 1.1 model but how gracefully do most of them cope with persistent WebSocket connections? Call me a cynic but many business hope to get away with $25 - $50 hosting bill and you get what you pay for so not sure LV will fare really well there – remains to be checked.

1 Like

And that’s not the case for LV. You have to completely change the way you program your site. The views become stateful, which introduce a lot of complexity too.

I think comparing LiveView and Turbolinks is not fair, as LiveView is a lot more powerful and this is therefore more complex.

If that’s what I wanted I would go with Turbolinks anyway, as I could still program the way I did before and just add, as you said, 1 line of JS to get that.

Yep, that’s the case for Turbolinks, but in LiveView you have to know what you are doing, cause if you don’t understand LV well enough and do some bad code, you will get pretty bad UX (as discussed on the latency “problem”).

All in all I agree with you, that for the views that are default HTTP requests, Turbolinks makes total sense. My comment is tied to the fact that LiveView is a different tool, that solves a different problem. I know Rails people worked on Turbolinks lately, don’t know what they did there, but as far as I remember, a lot of the stuff you get on LiveView you don’t get with Turbolinks, like the live sync for example. And live sync by itself is a big monster to tackle, that previously would involve some nasty JS, even using Turbolinks or AJAX/PJAX + server rendering.

1 Like

I really would like to know @chrismccord’s take on this (sorry for the mention, I know you’re a busy guy and I will not be mad if you don’t respond).

My question being basically: if I create my project using mix phx.new my_app --live, should I stop using mix phx.gen.html ... in favor of mix phx.gen.live ...? Should I focus on writing every single view in LV?

And if not, what do you think about using Turbolinks to get those blazing fast page transitions even for non-LV views? Would they work together well?

2 Likes

And just realised I entered a side discussion on this post and didn’t put my thoughts about the actual shortcomings. IMO this is the biggest (and maybe only) shortcoming for LV:

(replace “site” by “views”)

I recently was talking to a Rails friend about LV, and this was his comment: “My problem is that it overcomplicates HTTP + HTML + JS. If a socket is sending pieces of HTML, I would argue that is not even ‘web’ anymore”.

I don’t agree with him to the bone, but I get his pain: learning to program this “new way” is not a simple task, and using basic HTTP request + Turbolinks was “good enough” for most cases.

That’s why I got to my current step-by-step when developing views:

  • Start the HTTP request way
  • If the views starts to get complex and needs JS to handle some complex interactions or even live sync, rewrite it to LiveView, a it is not a complex job, as you can totally rewrite a basic view to LiveView without using any events, and then actually introducing the LiveView events, pushState and etc. where is needed after that.
1 Like

Speaking of Rails and LiveView, there is the Rails version too.
Looks like the LiveView ideas are spreading to another communities

1 Like

I wouldn’t rewrite existing features, but from scratch if I am already using LiveView, I would personally use LiveView for every HTML interface that I’m building. If we’re comparing purely CRUD, it will be the same lines of code as controllers + dead views. And if you later need interaction or real-time updates, you’re a few LOC away from writing those features. Normal caveats apply here – pre 1.0, potential breaking changes, etc. Dead views are also fine if that’s all you want need :slight_smile:

5 Likes

After playing around with @chrismccord’s suggestions I have to revise some of my criticism regarding latency. I still think the current defaults are not an optimal experience for users on slow connections, but LiveView v0.13.0 gives you a lot of tools to improve UX for these cases.

I had great success with this small change in app.js:

NProgress.configure({ parent: '#app', minimum: 0.3 })

and root.html.leex:

<div id="app">@inner_content</div>

This renders the progress bar right above @inner_content (but below any static header navigation). I think this provides clearer feedback regarding what content is dynamic and makes your site feel snappier.

I’ve also experimented with a semi-transparent css-background which makes it a lot easier to grasp the loading state on slow connections, add something like this to your app.scss:

#nprogress .spinner {
  top: 0px;
  background: white;
  height: 100%;
  width: 100%;
  opacity: 0.3;
  transition: 0.5s opacity;
}

#nprogress .spinner-icon {
  margin: 20vh auto;
  width: 50px;
  height: 50px;
  border-width: 4px;
}

It’s obstrusive and doesn’t provide much benefit on fast connections though, so I wouldn’t recommend it as a default. Hope this helps.

5 Likes

Yeah, I too was a little disappointed that so many of the Phrenzy projects were games or in general assumed low to zero latency between client and server. They’re neat in their own way, but they don’t really demonstrate compelling use cases for live view in my opinion.

We use live view for complex form flows, modal toggling, and pushing data to clients as backend state updates.

I think the challenge with using LiveView well is finding the balance between what belongs in minimal JS state and what belongs on the LiveView.

Examples:

Collapsable Navigation Bar

Completely doable in LiveView BUT with a huge caveat: rolling deploys will reopen everbody’s nav bar. To avoid this you suddenly need to centrally manage this information, but even that is a crappy solution because it’s not really a user specific preference, it’s a device specific preference. You could throw it in the URL, or in local storage, OR have a hacky form that holds the state, but all of these introduce a lot of weird indirection.

Ultimately, we went with a phx-hook and store this state client side.

Complex overview of a Shipment

Great scenario for liveview. There is a lot of interpretation of underlying data that has to happen, and we get to do it all in Elixir. There’s a fair bit of state as well, because shipments in progress can change, and that can affect things the user is doing. Managing that state in a functional way is a lot more sane to reason about than previous iterations we did in React.

That said, we still need JS to handle Google Maps.

10 Likes

Also don’t forget the server resources for possibly additional websocket connection and the liveview processes. I’m wondering if this might be a potential place for an optimization, where you can set a liveview to “static”, until you actually need the interactivity.

2 Likes

The platform is well suited to opening a websocket connection for every user as a matter of course. I agree you need to plan for scalability with websocket considerations in mind, but I also think for many users this is not something to dwell on or make careful choices up front for. We are well served by vertical scalability, and when you need to scale horizontally everything also just works LiveView/PubSub wise, so I really mean it when I say a websocket for every user is normal business for elixir and phoenix users.

You could conditionally call liveSocket.connect() based on some selector and you’d achieve this, but you’d need to manage loading states for this “permanent static” thing. It’s not something I’d optimize for until a real need came about.

4 Likes

I’m not worried about scalability, but rather the fact of being mindful of resources. It seems wasteful to have liveview running for completely non-interactive pages, but I also have no idea if there’s actually worthwhile difference. It’s not a pressing matter for sure, but would be great when addressed at some point. I’d certainly feel more comfortable starting a project with liveviews over controllers if such an option existed.

3 Likes

My point was not the LOC, but actually LiveView’s being totally another beast, you work with it totally different than people are used to work on web frameworks in general, so there is a learning curve.

Anyway, nice to know your go to strategy, maybe I just am being a bit averse to the change of mind, will try out a side project using only LiveViews.

Just wondering now: is the plan in the future to extract Phoenix.Controller and Phoenix.View out of phoenix? I mean when (and if) LiveView gets adopted and people use the way you say (no dead view and controllers at all), there is no point on having those modules on the main phoenix app.

1 Like

It’s a different paradigm, so there are some ideas to learn, but I think it’s a vastly simpler model for newcomers vs traditional web development. A large number of abstractions fall away entirely, and there is in general less to think about, less to name, and less plumbing involved.

Not going to happen. Note that controllers and views are still the goto for API development and pages that require writing to the cookie session.

2 Likes

Yeah, so my “shortcoming” could be rewritten as: “it’s hard to convince old web developers to adopt” :joy:. Anyway, nice job so far, I have being watching the progress on it for some time. I have to tell you my expectations were high about LV, so recently tried it out for a demo on a talk I gave and expectations were met and exceeded (for the ones who are wondering, here is the project repo and you can check it out live, details on the readme repo)

Oh, true, cookies… :smiley: Thanks for all the answers

3 Likes

I very much love that LiveView:

  • allows you to create interactive forms/components without having to think about the API to load content from your server asynchroniously at all. Being able to create search forms, sortable/filterable tables etc. without needing to think about that is a very big win.
  • makes it very simple to synchronize state between multiple pages of the same user (say: what someone has in their shopping cart) or also different users (collaborative dashboards).

The main thing that I’d like to see improved in LiveView right now, is to have a slightly larger well-defined JS-API, which would allow other developers to step up to create their own integrations with it.
For instance, right now it is only possible to hook your LiveView elements to one phx-hook. This is fine if the final developer is the one supplying custom JS code, but it very much hampers the creation of re-usable add-on libraries.

I however have no doubt that this will improve, in one form or another, as LiveView matures.

7 Likes