The Perils of Rehydration – A Realization about Gatsby and React
joshwcomeau.com
joshwcomeau.com
Whenever you try to precompile or even just cache an HTML file that relies on run time data, you are going to have to build your application in a way that is sympathetic to that. In most cases, you're going to have to figure out how to fetch the missing data on the client side and populate it into the template/runtime context.
This is an issue in Ruby, PHP, Javascript, React, Angular, Python... every single application with caching or compilation.
By simply keeping all the state, logic, and rendering on the server, all sorts of issues are avoided and various optimizations are possible, and I get full server-side rendering for free!
The client-side, meanwhile, via websockets, only sends events to the server and diffs whatever chunks of markup are sent back. Most of this is via server-side provided attributes (phx-click, phx-change, etc.), but for the slightly more 'exotic' stuff I can add my own events.
Obviously there are cases where this solution isn't practical, but this hasn't been the case for the vast majority of my projects.
Also Phoenix is written in Elixir which could easily handle millions of stateful connections.
As with any stateful solution it has problems scaling. I'm not sure LiveView is the right answer.
Memory might become an issue though, I suppose. Every user's state will be in-memory in 'their' LiveView process.
On the other hand, there's much less state needed than with a client-side solution like React, because it can be very quickly fetched when needed.
Next and Gatsby make it seem like you can just directly translate your front end React experience to SSR but in practice there are, as you say, some significant differences.
Even in this case, a loading solution works just fine, but it's the exact same pattern. You'd just `return <Spinner />` instead of `return null`. You also face the same issue, if you don't wait until post-mount.
Asynchronous state updates regardless if they come from UI events or data fetching should be handled the same on the rendering side in my mental model. This has nothing to do with SSR/SSG.
If one would just write client side rendered code as if the whole application was a SPA, then this problem never arises as long as there is a clear separation of concerns between GUI and state management.
A React component doesn't have to know where its data is coming from nor where it is rendered. Wrapping a component in a 'client only' higher order component seems to add unnecessary complexity and brittleness by complecting the rendering tree with side-effects and state management:
What if at some point there needs to be a different render of this component with data fetched during build time?
In my opinion the example illustrates how moving state management out of components (Redux and so on) is a more sane idea, compared to encapsulating local state and side effects into components.
The component in question should not render content during build time, it is a UI element that represents the login state, which you certainly do not want to have pre-rendered at all, let alone be indexed.