Phoenix LiveView vs SPA

Most of that comes down do the problems of distributed state. If article is modified by both the server and the client you need some way to consolidate state. Ultimately you either need CRDTs or some other means of getting rid of conflicts between concurrent changes. While there’s e.g. automerge on the js side of things I don’t know of any CRDT implemented in elixir and js besides maybe phoenix presence.

That’s also the reason why I personally don’t see the problems with dropdowns and other similar UI components. Their state doesn’t overlap the state on the server. Say I have a dropdown, where the list of links is handled by liveview. The state for list items is completely separate from if the dropdown is open. The open/close state should imo never be handled by liveview, while the list of items needs the server for getting updated. That’s why the alpine.js integration with liveview works so well – whenever liveview updates alpine does apply it’s local changes on top. One likely could do the same with react or vue or whatever, but there’s just not many people using those libraries like that.

1 Like

I think the emphasis on SEO, and it being an argument against using an SPA is not at all universal.

Depending on the target audience for the application, I.E a business app vs something like twitter, github or a forum…SEO is not really important. If the app is behind a login page, sacrificing UX for the sake of SEO is not really defensible.

That is the purpose of a marketing site, which promotes the features, and problems your app is trying to solve. The marketing site will be completely static, and have the SEO nobs dialed to the max, with a link to login to the actual app.

In my case, this is pretty much 100% of what I build…so moving rendering to the server for anything but improving metrics like Largest Contentful Paint is only costing the business compute - as mentioned before, client side rendering is free distributed computing…

And if you think the app you are building is going to be Twitter, GitHub scale, and actually see meaningful organic growth from SEO - you are already a bit of a unicorn, imho.

One way I have dodged the slow paint and abrupt rendering of an SPA is to apply some full page inline CSS animation on the served HTML. Allowing the browser to immediately show some indeterminate loading screen. This is pretty common for say a desktop/mobile application to require a loading screen or indicator before actually launching - I do not think this is bad UX, and actually expected if the App has enough data/interactivity…

EDIT: Also, pretty sure LiveView would not work that great for an App like Twitter, or GitHub - or at least at that scale. So say you did build the next Socially Responsible Twitter with LiveView - wonder how the engineering would evolve…I imagine the thought of an SPA would come up in the board room because the servers are starting to cost a bit too much. This same argument applies to the Redex library I have posted about - there is definitely a threshold of scale that likely means server side in memory state is a bad idea…

2 Likes

Aren’t some of these concerns addressed by using css only solutions for things like drop downs and animations? JS has a clear role in web apps but it is probably overused for things that don’t really need it.

I think one of the bigger arguments for something like React, is the very composable and reusable nature of the components. Attempts are being made for similar APIs in LiveView though which might open up the door to some interesting LiveView component libraries/toolkits…

1 Like

If those things shall be properly accessible you need JS. Most of the css solutions – while working – are just hacks.

1 Like

What do you mean by “properly accessible”?

At the most basic level keyboard shortcuts.

I’m already seeing real benefits from being indexed in search engines, it’s not about scale but visibility. As a content platform, SEO is crucial. It doesnt even have that much to do with scale. Not having a worldwide scale doesnt mean you shouldn’t care about your content being discoverable.

What I’m pointing out is that SPA have their drawbacks. Business apps are also not universal. Of course you will make your desicions based on your target and use case . What I’m talking about has to do whith this kind of pain points:

Once you need to serve content that can be indexed and be interactive to users, things get muddy. I don’t want to run a node server to do ssr or go back to being an spa just because the content I serve also has a fair degree of interactivity. And the alternative has a lot of cognitive load derived from the constant switch between Phoenix and js, which is less than ideal.

If your audience has capable devices, which is not the case in many parts of the world.

Things like aria attributes and such need js to be modified.

Yes this is true, but we can probably agree that the vast majority of web apps are not public, and tools built for internal or business purposes with a very small userbase. And possibly sensitive data that has the exact opposite requirement…

This is also true, and if you are in a developing country and building something for say the government, then yea it might be a disservice to your users to build an SPA. But, will the same be true 5 years from now? This depends on what grows faster, complexity/size of SPAs or availability of decent compute device’s + connectivity in the developing world

Something I think I am leaning towards doing is having a read-only version of the site shown to bots/non-JS users - like what Discourse does (if you turn off JS you’ll see what I mean). This isn’t something new mind, vBulletin was doing the same thing over a decade ago and out of all the forums back then they were almost always consistently ranking higher.

When I think about how I want to build apps moving forward, I think I want to separate, with different versions for no-js, desktop web users, mobile web users, mobile app users, desktop apps etc. It’s reached a point where these are now sufficiently different and a simple responsive site isn’t really going to do them all justice. This is why I was drawn to Dave’s Elixir course so much - you build the app in Elixir and then use Phoenix for the web layer (or even multiple layers) etc. (There was a good discussion about it here.)

This is something I am thinking about more and more too.

I am reserving judgement for now tho. I am going to finish learning Svelte and then re-evaluate how I feel and how I am think I am personally going to build apps moving forward. Will definitely be keeping an eye on these threads in the meantime.

1 Like

I think you should give React another look also, its functional approach and simplicity really shines when combined with Elixir - the context switching between JSX <-> Elixir is not bad at all. (its honestly no worse than writing eex,leex templates…)
I pretty much only use map, reduce, filter and relatively simple string manipulation in JS - all of which is immutable and feels quite a bit like piping stuff between Enum functions. And event handling is just passing around simple function references, to onChange, onClick etc props…

As long as you use arrow functions - problems with this essentially disappear. I do recommend understanding why though.

You can get very far with just react-router, and setting up React with phoenix is 1 additional babel config/plugin, do not even need to touch the webpack config.

Couple other recent additions to react, like Hooks - really changed everything.

Drop something like Blueprint in the mix - and you can have a damn near production ready prototype in a day or two…(it comes with a built in hotkey API that is decent) NVM it uses a decorator…they need to add a hook API

Another package that covers all data fetching and global state concerns is react-query. Have not actually used it, but am considering it for the React integration for whatever Redex/LiveData become…

recoiljs also deserves an honorable mention - if you do need global UI state its a pretty nice way of achieving it, without complexity like Redux I have also not used it but came from some facebook engineers so should be OK…only problem is they use the term Atom - which is very much NOT the same as an erlang atom

React performance is something that is improving with each release - it might not be as fast as Svelte - but its unlikely svelte has any room for improvement - the react team has been working on interesting things like concurrent mode - when that becomes stable - lots of large React apps will be faster with just a simple npm update This all kinda ties back to the huge amount of engineering that has gone into it - if SPAs are a naïve idea - probably would have realized by this point we were just digging ourselves into a deeper and deeper hole… OR maybe we just don’t realize it yet :stuck_out_tongue:

1 Like

Another approach to this is just building a static site (Gatsby or w.e)…if the content is not something that needs to be immediately published - you could do something quite simple via an API that writes a JSON file to a storage bucket - and on a regular basis like every evening it kicks off a build, deploying and SEOing the newly added content… of course this also has scaling issues if you are building 100k + pages(unless done incrementally) - but if you want really good SEO - you cant beat serving static content. This is also not a bad idea until you DO reach scaling issues, and then you re-engineer when you actually have users actively publishing content all the time…

In my particular case, the content is user generated, akin to reddit, so it is immediatly published.
For other cases, your solution may work, but it adds another moving part to the stack.

The reason you can have, say, gatsby, next.js, nuxt, sapper, etc, and don’t suffer from the disconnect between what the backend knows about the markup and what the frontend knows about what to enhance, is because both the browser and node can evaluate the same code(more or less, but you get the idea). With this stack it doesn’t matter if you build an SPA or not, because the client always receives all it needs to show content to the user or crawlers.
But this isn’t the case with Phoenix, so despite having an excellent templating engine, if you want to avoid the disconnect you need to spin up a node server and let it handle the frontend. You can mix them of course, but at some point you think “this would be SO MUCH EASIER(and maybe cheaper) if I could just do everthing in js”, so that’s why I think we see MPA or SPA, and not much in between(maybe github is one of those rare specimen that take the in-between route).

For some stuff, it doesn’t really matter who knows what. A dropdown or an image cropper, for instance, can be built with whatever frontend tool you want.
When you have content that needs a roundtrip to the server to perform some action and reflect the results in the client, however, it does matter and drives the way you design everything. It can be a page navigation to not lose state on some layout pieces(like a chat miniwindow), it can be a change on how certain pieces of content are displayed.

So coming back to the topic of Phoenix LiveView vs SPA, I believe this is where I think LiveView shines, because it allows you add behavior to the markup not without the need to write js, but without the need to spin an additional server to handle the frontend and without having your presentation pieces split between clientside libraries and backend templates. And I believe it’s for this very reason LiveView is coupled to the DOM and it’s not just a data diffing/syncing library. Most people don’t have the scale of github or twitter, and Phoenix channels have already proved to scale very well, so I believe LiveView can take you quite far. If you do reach a really big scale, I would say you’re making enough money to hire a bigger team and maintain more complex stacks.

I hope this makes my stance more clear. I’m not in the SPA or anti SPA team, because I understand both approaches have their places and I’ve already tried both extremes(FWIW, most of the user facing content of my project is phoenix templates intertwined with js enhancements, and the backoffice is mostly handled by js alone). But when you want to sit in the middle ground and keep your stack small, there’s a lot of dragons to tame. You can’t have the cake and eat it too, I guess. It’s a very very wide topic and there’s a lot of factors to have in mind.

I’m not using LiveView because I have some concerns about memory usage with potentially infinite data sets in the client(infinite scrolls), but it does solve real problems for a wide variety of use cases.

1 Like

I know Vue has Quasar, it is great. Was was new for Svelte a few months ago?

https://sveltematerialui.com/ for instance. Also Svelte-prosemirror, Sapper, you can check https://madewithsvelte.com/ and find a whole lot of bindings for other libraries. Before Svelte 2 it wasn’t popular enough and it was lacking on community-made bindings and libraries in general.

2 Likes

Yea would not do this unless it was the only type of content. I am pretty impressed with the JAM stack ideas though. They are doing a good job of replacing the usage of systems like WordPress/Drupal - which imo are a stain on the web and we would be better off without. They did serve a purpose, but are now a liability. There is a huge amount of web development done in that space, the public site that is not an app but maybe needs some sort of CMS functionality - and is better off not being dynamic in that it just adds a larger attack surface - and running costs. The future of most static/marketing sites with any cms requirements are better served with something like netlifycms

You are right about this - at least our current state of Phoenix + JS integration is not helping to tame the dragons…The difficult position the phoenix team was in when deciding what to do in regards to static asset management and the stumbling with brunch as the initial bundler is I believe what led us down this path, and did not leave a positive impression of the JS community with the phoenix team…
The migration to webpack has been good - but I think something to bridge the divide more cleanly like what the guys behind asset_import have done would be a step in the right direction…

I think we have somewhat concluded this discussion and it is clear there is room for LiveView and SPAs and even fully static sites. Factors such as the team building it, the users/target market, the requirements of the UI; its the age old answer of ‘it depends’…

1 Like

React does indeed look like the best atm, at least from the various sites I’ve seen using it. Some do feel a little too similar (bit like when Bootstrap took off) so it’s good to see more UI kits coming out. I will definitely check it out at some point but I want to see how I get on with Svelte first. I like that it’s the newest of the bunch and that we may be able to help shape the direction it may go in by providing feedback etc.

I’m enjoying seeing the Svelte portal grow on Devtalk too, could be worth keeping an eye on for anyone interested in Svelte :003:

Just read ALL comments on this thread, I was “yes” “yes” multiple times. It’s quite many good points if I have to quote. I had done a project using phoenix channel with SPA 3 years ago. Currently I am on a project that produces worst case of leex diff, client patch (via live_patch) tooks 7 seconds! And then I switched view layer to Elm and just push pure data (push_event/3) down, and it now takes ~ 1 second! (Bonus: 7MB memory for components diff tracking is now 0.9MB)

Compared to low level phoenix channel + SPA, liveview + SPA is a lot easier. (Server + Client) side routing for free!, push_event/this.handleEvent for free…

So I agree with many points in this thread, liveview without presentation/view layer is still super solid (again, push_event, this.handleEvent, routing (live_patch, handle_param etc). I kinda think all those phx- stuff should be js API. Keep those form stuff since it goes to server anyway. Finally yeah, there’s still room for liveview + SPA indeed, basically liveview + virualdom lib + vanillajs lib + custom element should work well together. Not re-inventing lots of thing on their own virtual[king]dom; the web platform today has many borders (no micro frontend thanks!)

3 Likes

This is one of the more clarifying threads about this subject I have seen, and in general, you summarized very well the possibilities that are open to getting full advantage of Phoenix LiveView when doing SPAs.

1 Like