Replies: 3 comments 2 replies
-
|
This is a really interesting idea for the framework! Dynamic rendering like this is a solid way to balance performance and SEO, especially since it avoids that 'double data' overhead you mentioned. A few technical thoughts from someone who has implemented similar patterns:
|
Beta Was this translation helpful? Give feedback.
-
|
I realised that point 3. (faster data than regular SPA by streaming it in) and 4. (no double data problem) needs a combined elaboration. Both of these cases involve kicking off the data requests on the initial request on the server (instead of on first render on client). I see two ways of achieving both of these in unison: Blocking or Streaming (deferred loaders). Blocking:On first request, server waits for the loader, before returning SPA shell + HTML embedded JSON payload together in the first HTML response. You could have a loader that synchronously (blockingly) runs on the server on the initial request, to just return a little bit of DB data, so the response to the user remains fast. The client gets the SPA shell + that little data, renders it, the user starts consuming it (e.g. a post), and then the SPA could use Suspense to lazy-load the rest of the data (e.g. comments to that post) in the meanwhile. In the SSR for bots case the lazy-loading is eagerly/blockingly executed, so the bot gets the full HTML on first request. Details (click to expand, perplexity.ai generated code)Unified Page Component (
|
Beta Was this translation helpful? Give feedback.
-
|
Yea I looked at something this recently. We do have a few things you can do today I think - One is you can render layouts as ssg or ssr only, but not the inner page, that's a nice balance. Another is you can have an SSR route but just bail early depending on the request. Just have the loader return something from the request you can then use to decide if you want to render the , add a supress hydration warning. If it's a bot you return if not you return full page. Only thing I'm not sure about there is caching, we may want to have some ability for loaders to set headers, I guess you can call our set headers helper but not sure if our docs are clear there and how well tested that it. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
A unique selling point for One could be that it makes it easy/streamlined to have SSR for SEO, but not incurring the rendering cost/time of SSR on the server for human users (they would get the SPA instead). SPA also aligns with the mental model for both PWA and React Native apps.
Cheaper server cost, due to less server processing time needed due to not rendering the HTML on the server for users. Offload the HTML rendering to the user's device.
No hydration needed, as opposed to SSR: Yes, doing this may mean that the first render of the HTML containing all the data is slightly slower for users (but the HTML shell arrives faster), since all the data in the HTML does not come to the client at first load. But that means that the client doesn't need to hydrate the HTML either, so it removes the annoying "visual but unclickable" state of pages that appear during hydration. If the SPA shell is served from the Edge (Cloudflare function or static CDN), then the user may even see the HTML shell faster than if waiting for SSR. (Besides, you could extract some data from the URL and show that in the HTML shell, like the post title, without needing to hit the DB.)
Faster data than regular SPA, by streaming it in: If, on the initial server request, the DB requests are kicked off immediately, and then the data is subsequently streamed in to the client, then you also avoid the latency that SPA's normally incur when kicking off the data requests on the client. (Requires a new feature: deferred loaders.)
No double data problem (costs time and bandwidth): You avoid the "double data problem" that NextJS has, which occurs when the same data is fetched and sent to the client twice: once embedded in the server-rendered HTML, and again in the JSON payload (NEXT_DATA) needed for client-side hydration with React. Downloading the data twice increases is a cost to the client in terms of download time (which increases TTI) and network usage (mobile $$$; could be important for low income countries), and time client side parsing overhead. Basically, One would only send the data once as a JSON payload (via a global script tag in the HTML head or body), for React to render (on the client), not also pre-rendered (on the server) inside the App structure in the HTML.
How could this could look without needing to have duplicate
page+ssr.tsxandpage+spa.tsxpages for every page:perplexity.ai generated response:
Dynamic SSR in Middleware (Single
page.tsx)Use one
page.tsx(due to global SPA/default mode) + middleware that fully renders DB content on-the-fly for bots:Why This Works
page.tsx(handles both client SPA + server props).Make
page.tsxacceptdataprop (server-fetched for bots, client-fetched for users). This is the standard "dynamic rendering" pattern—cleanest DRY solution without framework hacks. [reddit](https://www.reddit.com/r/TechSEO/comments/suqnqc/main_differences_between_prerendering_and_dynamic/)Beta Was this translation helpful? Give feedback.
All reactions