SSR/SSG: How to share context between client and server
I am trying to implement a Design System of sorts using SolidJS (my prior experience is with React) and ran into this challenge:
How can we provide dynamic context that is both available when rendering document <html>
as well as to components that need to consume it at both SSR and CSR time?
I was able to wrap the server side rendered document with a provider and everything works fine here š„³ (which means that most of the features I am looking at will be straightforward to implement).
But the context is not available anywhere inside the start-client
tree.
Is there a known strategy to achieve this?
Thanks in advance šāāļø6 Replies
Easy to reproduce adding these 3 files to the Solid Start
basic
template.I see.. it's because the Document doesn't hydrate. To support CSR mode I needed to break it out. This complicates things a bit because your signal would never trigger update anyway even if we made it available higher up through middleware.
So you want to put something on the body? The easiest way to do it would be server render it non dynamic and use an effect to write and update it in the browser.
Thanks for answering. I was suspecting/fearing this š¬
The (technical) use case(s) are indeed to have control over
<html/body class>
and/or style and inject <style tags>
and/or other assets into the document based on route/context.
Two business cases for this, that I have encountered recently
- multi-brand design systems
- A/B testing design system iterations
- "theme" variations based on feature flags
In these scenarios, the SSR time rendering is a requirement to prevent "flashes of..." and to guarantee overall š© tip top core metrics and user experience.
Note: There are other business cases for having full dynamic control of the document.
š¤ This is typically achievable via the render content > render document
pipeline, as in ReactHelmet ... <MetaProvider>...<Meta/>
.
ā Is there anything fundamental / architectural that I'm missing that prevents generalising this approach so that one could do something like
and then something like
Yeah.. which is always hard with streaming as the head has to go first. Solid Meta does do that for MetaTags/Title but we don't have anything for augmenting tags it wouldn't create. It's a bit tricker. Old SolidStart actually handled this incidentally because it wrapped HTML and Body but it basically was impossible to get SSR: false mode working with it.
The biggest challenge for how things are currently is that the Document component is never sent to the browser
It is not part of the client bundle
But I wonder if there is a way to be smarter about this at bundling time. Now that the lines are drawn so to speak. That would only be the first step. We still don't hydrate the head (had issues with browser extensions). But the HTML/Body tag would work.
Got it (I hope). I wasn't familiar with the streaming architecture / flow.
It does not render app first and then the document
When streaming it sends the document first and then streams updates to
assets
, scripts
and children
And there is (yet) no way to stream updates to the <html>
and <body>
tags.
š¬ Did I get it right?Yeah. Mostly. We can update things up to the first flush so it is often better to wait to start streaming until we've done a first pass, loaded critical data, but we've already rendered stuff at that point and we have special mechanisms to collect assets at that time. Anything misssed when it starts streaming today, gets added client side after the fact. We have plans to improve streaming of assets but updating
<html>
and <body>
would need to be special cased as well. And I admit I don't have a plan for that currently.