Dynamic environment variables but otherwise CSR
I searched around a bit and read the docs but didn't quite graps things I suppose. Using Router / Start, could we achieve behavior such that: we have dynamic runtime environment variables that are then also provided to the client, but otherwise completely opt out of any server-side rendering logic (and run loaders etc. only on the client). So the only SSR parts would be providing the proper runtime environment data (like an API endpoint, Sentry DSN etc.). This way we would have one build for all environments, but still stick to being almost completely CSR.
We currently use Next.js for our management dashboard but we don't need any of the Next.js functionality at all, and would much benefit from just having dynamic environment variables for things that need to be dynamic / set on boot, and otherwise be solely reliant on CSR + having the option of having API routes etc. if need be later (if we don't want to bloat our separate API for a one-and-done thing).
I guess this would also fit as a #router-questions , but oh well. :D
6 Replies
like-goldOPā¢3mo ago
Bumping this for visibility.. āļø
metropolitan-bronzeā¢3mo ago
I have a very similar use case both in past experiences with Next, the desire for as much CSR as possible, and for dynamic environment variables on the client at runtime.
Since our deployment strategy is Docker + a Node server, we decided to allow the root route to be server-side rendered, but every other route is not. Setting
defaultSsr: false
in your createRouter
call and then setting ssr: true
just on the __root
route works well.
Then, we extract all VITE_PUBLIC_
(we decided to stick with that convention) environment variables from process.env
and serialize them into a base-64 encoded string that gets injected into a <meta>
tag when rendering the initial HTML payload. But, beyond that and some other metadata, the initial payload is otherwise an empty shell.
To use this data in the app, we use another utility on the client to parse the value in the <meta>
tag back into an object. Some kind of getRuntimeEnv
utility will be needed to access these because import.meta
is going to be all your build-time / statically-transformed environment variables.
This approach has been working pretty well in Next, and we've adapted it to TanStack Start pretty easily. Compared to Next, I appreciate how TSS gives you very precise control over where the SSR boundary is.
All that said, if its not critical that your runtime environment variables be available to the client immediately, you could implement an API route to serve them and go full SPA mode.like-goldOPā¢3mo ago
Hmm interesting approach, thanks for the explanation! Sounds like a simple setup to try out as a PoC. Our use cases are pretty much identical to yours.
I wonder if the loaders are then run on the client only with defaultSsr=false as well, at least thats what Iād expect when disabling ssr
quickest-silverā¢3mo ago
not yet, but i am on that
metropolitan-bronzeā¢3mo ago
FWIW loaders/beforeLoad is not required for this setup.
You can use an async function as the
head
option when calling createRootRoute
and return any <head>
tags you want to add. I think its still a good idea to use createIsomorphFn
here:
__root.tsx
like-goldOPā¢3mo ago
Didn't think of that, nice!
Seems like I have everything I need to know in order to start planning a migration, when loaders can be opted out of being run in the server soon! š