All of the above while using Elixir and Phoenix framework at the back-end.
There is of course an appropriate time to use both approaches. I love making applications with Phoenix because it is fast enough to use server-side rendering. That is always my approach because I generally make internal programs that are not accessed by the outside. Therefore I am not worried about thousands of people hitting the application at one time.
I prefer client-side rendering, but I also hate frameworks. I think that (with EcmaScript 6
) it should be enough easy to write most of things on your own. It will always met your needs and you do not need to create hacks/workarounds to solve specific problem. Personally I’m looking at Elixir -> WebAssembly
and scenic
, so then I could write everything into one big umbrella app. I don’t prefer server-side rendering, because it’s something which server does not need to do and therefore it’s waste of resources. Server needs to work with multiple clients, but client needs to work with only one server.
To be honest I very rarely use client side frameworks anymore. I went all-in with one for a big project a few years back I regretted every day I was working on it. Badly burnt, I’m now very careful to not use them where they aren’t needed.
As @Matt says, Phoenix is fast enough that the speed of client-side solutions doesn’t represent a meaningful advantage over good old fashioned server-rendered apps. I try to build with progressive-enhancement principles (note: not the same as progressive web apps…) and the practises laid down in Resiliant Web Design. The bonus is I spend less time writing JS… I can also sprinkle them with things like Turbolinks to give me a halfway house between the two.
If we’re talking about a genuine use case for client-side rendering, then progressive web apps with offline modes and the goodies that go along with them are my preference. The result is a static site where the client side JS is “precompiled” so to speak and then “rehydrated” once the page has loaded. I don’t particularly like React, but to my mind Gatsby represents the best approach to these types of sites. That way I get to keep my Phoenix/Elixir app totally isolated from any rendering or communication with a Node pre-renderer.
What if it’s for SEO needs?
Would you please elaborate it further? What technology did you use? (React, Angular, Vue or anything else)
I need to check out scenic. I keep hearing a lot of chatter about it. I have been too lazy to check it out
I think there’s 3 reasons to render on server:
-
SEO - while google can crawl a lot of client-side-only JS rendered content (and I think it’s good at it), it’s still impossible to say how reliable it is in every case. Bing, last I heard was working on it with questionable results. Generally if you have pages you wanted crawled by search engines reliably, I’d argue you should render on the server. YMMV, though. You might still be fine with client-side rendering.
-
Faster time to render - I think this only might be true… depending on how it’s implemented. But if you fetch user-specific/dynamic data when you SSR, then hydrate on the client-side, the browser won’t need to run the JS code to generate HTML or call back to the server again to fetch dynamic data. It gets all the html including dynamic bits all in one shot.
ie. Even if the client fetches all your sites’ content faster if it’s rendered only on the client, it could still take longer to first interaction if your JS code renders HTML inefficiently, or has page jumps, or needs to call back to the server to get dynamic info. -
Your content is static.
Reasons to client-side render:
-
Cheaper on server costs than SSRing. That work is offloaded to the client.
-
You don’t need your content to be reliably scraped/crawled. <- YMMV depending on app complexity.
I’m not up-to-date with latest standards about SEO
, but it should be handled much differently than normal session. Basically if bot is searching for text then you should limit response size (DOM complication etc.) to match latest rules/spec for SEO
. There are lots of ways to do that. If everything could be written into one umbrella
app then children could depend on themselves and part of server
-side to handle bots could be done using client
’s shared API, but of course there is still lots of work to make such solution possible and enough easy.
We used React + Meteor, but to be honest the choice of framework is irrelevant. All the frameworks you mentioned use client-side rendering, and that’s what sunk us.
My main criticism was that this setup made complex things very simple, but simple things very hard. It turned out that we needed more of those “simple things” than we had anticipated. It gave us loads of flashy functionality right out of the box, but building that into a real world app, that people had to use everyday to manage large financial transactions was awful. I regretted my choice about 6 months in as it became clear just how hard it was going to be to get the app where we wanted it to be. Development was slow, and filled with dead ends. A lot of time was wasted as the frameworks matured, old dependencies were retired and new ones replaced them.
SEO was a perpetual nightmare. Even though we used a platform (Meteor’s own - Galaxy) that had pre-rendering built in, I was forever fighting it. The results from it would be totally random. Sometimes it worked fine, sometimes the pre-rendering engine couldn’t access the data on that page, so you’d get a load of identical, empty templates indexed… Over time, this inconsistency did real harm to our ranking in Google results. We saw a marked drop in average ranking from our old, server-rendered PHP app.
Loading speed was also an issue in our case. Page to page was fine as you’d expect - but sometimes our initial loading time was more than I was comfortable with. Even with code splitting, there were pages that I could never get fast enough and it impacted our conversion rates.
I made a bad choice of tech when considering my teams skill-set. I’ll hold my hands up to it, and I’ve learnt from my mistake. I let the “new-hotness” cloud my judgement and I introduced technology that was outside my teams experience and comfort zone. I had hoped that after some initial work learning new skills, we’d be back up to speed; but that wasn’t the case. The result was that a very proficient team was wasted as they fought to catch up with paradigms and languages that they simply hadn’t encountered before. Putting everything in JS has a real cost when the majority of your team isn’t comfortable with things like React and Redux’s nuances, which constantly caused confusion.
I’d also like to talk about JS dependencies…actually no I don’t. I haven’t got the stomach for it right now.
Simply put, using a client-side framework where it was neither necessary nor beneficial played a major part in sinking the company. Yes, the business was also deeply flawed in many other ways, but my choice of framework directly led to its failure.
I’ve also had side projects using other frameworks (Vue) suffer similar fates. My experience of client-side rendering and JS frameworks has made me very wary of using it in the future.
I’m using Next.js (react framework) for a project currently and it handles SSR by default, but also allows for exporting out as a static site. In this way you can switch back and forth depending on changing requirements.
All that to say, it’s not necessarily a debate between SSR and a javascript framework. You can have a javascript framework like react coupled with a build tool like gatsby or nextjs that builds a static site.
One benefit of using a popular JS framework (and why I chose react instead of phoenix html) is using well-built open source libraries. From error-handling and validation in forms (https://github.com/jaredpalmer/formik), to components (https://material-ui.com) with well-thought-out api’s… it makes building complex interactions relatively easy.
I think jdumont’s points were all solid. For small sites with relatively few complex interactions and/or teams without JS framework experience, I’d avoid it.
Hopefully tools like drab/liveview/undead become the future - and allow for some level of component/interaction type libraries with elixir.
That’s exactly the reason I jumped on a client side app. It was large, intricate and highly animated/interactive.
We ended up “walking back” from that though because it was too much in places, whereas I wished we’d “built up” to it.
I just want to be clear, I’m not against these frameworks at all, and don’t condemn people for choosing them. In many cases they are 100% the right choice, but that hasn’t been my experience so far.
Things like Next seem to have smoothed off a lot of the sharp edges I encountered. I didn’t have that flexibility (Meteor kept us tied to few options back then).
My current project may involve a lot of JS, so I’ll get a chance to explore the alternatives and compare.