trpc
trpc copied to clipboard
Enable SSR per page (NextJS)
Instead of having a global setup to enable SSR with withTRPC
wrapping _app
, we need to use it in a per page basis because our app is really big, and some parts need to be static and we don't host in Vercel but in a K8s environment.
I spent the few hours trying to understand why withTRPC
would not work wrapping a page. It seems like somehow the query is not being sent after the first prepass.
Could be added, but nextjs is deprecating getInitialProps, harder so with the new router they're planning. Happy to take PRs that enables this on the next
branch though.
If you're planning on adding the feature, please make an RFC in discussions and/or message in the contributors channel on discord to get help! 🙏
Thanks for your idea. I agree this is good but not something I personally will spend time on, will actually leave it open for a bit if someone wants to take it on.
@KATT Hello Alex, just spent some time implementing my own version of withTRPC
that supports SSR per page. Given that there are multiple upcoming changes in both NextJS and TRPC v10, I didn't implement it with a PR into the main library.
However, please look at this CodeSandbox or the repo carlosbaraza/trpc-ssr-config-per-page which contains the simple TRPC example with my custom implementation to support SSR configured per page.
Let me know if you think the pattern of manually adding a TRPCProvider
in the _app
is a good one. We also have Apollo configured for SSR in our application, so we need to manually add the Provider in the right part of the tree, because there are multiple providers and wrappers in the _app
, so wrapping everything with a HOC would not cut it.
That's super impressive! I'll def get back to you on this :)
That's really cool, it's easier to understand what's going on that way. And it's very normal to have BlahProvider
s in _app.tsx
. Our current next.js app has six of them so far. It might unlock some other possibilities like more easily passing data to the TRPCProvider from other react hooks, etc.
Given getInitialProps
is "legacy" and may not be available at all in Layouts, I wonder if it could go a step further and put the responsibility in the user's hands, while providing useful helpers. Maybe something like:
const Page = () => {
const query = trpc.useQuery(['foo'])
return <>{query.data?.greeting || 'no data'}</>
}
export default Page
export const getServerSideProps = trpc.serverSidePropsPrepass(Page)
or, if people prefer to stick with getInitialProps
while they can:
const Page = () => {
const query = trpc.useQuery(['foo'])
return <>{query.data?.greeting || 'no data'}</>
}
export default Page
Object.assign(Page, { getInitialProps: trpc.initialPropsPrepass(Page) })
(haven't dug into the implementation, so not sure if serverSidePropsPrepass
and intialPropsPrepass
would even need to be two separate functions)
@mmkal that serverSidePropsPrepass
is an interesting approach. I found it quite frustrating that the recommended way in Apollo now is to prefetch the queries in the getServerSideProps
function. We like fetching data at the component level, because it keeps units of logic independent from each other, and it makes it really hard to know what would be the queries in a particular page. To SSR, this requires traversing the whole page tree to find the particular queries that would be made. It has performance implications, but the DX is much better, so it is a tradeoff we are willing to tolerate.
Do you have any idea if implementing serverSidePropsPrepass
would be possible?
Was about to open a similar issue, getInitialProps
in _app
goes against Next.js best practices and defaults, this should really explicitly be decided on a page-by-page basis using the standard getServerSideProps
/ getStaticPaths
/ getStaticProps
fns. Looking into the preliminary _withTRPC implementation, I wonder if it makes more sense to put the double rendering/prefetching logic into _document
like Apollo does with getDataFromTree (usage example). Especially with v10 approaching here's a virtual thumbs up from me to anyone who manages to integrate this on time. 👍 (I'm definitely having my eyes on it, but can't commit to anything right now)
I don't think Next.js is going to / can deprecate per-page getInitialProps
. Even if they don't include that exact method in the upcoming layouts proposal, they MUST include a way to prefetch data and then do SSR on the server only.
Maybe something like this: https://github.com/vercel/next.js/discussions/29117
Other frameworks like Sveltekit are making ways to do this, and it's absolutely necessary to have the best user experience (server rendering + client route transitions that can optionally prefetch data before the route changes).
At my company, we are going to use getInitialProps
per page as it's the best option for now.
If someone wants to make withTRPC
ssr (or similar) work on a per-page basis, I'd happily merge it.
I'd want it to have and example project running through e2e testing using Playwright with javascript disabled to show that the data fetching works on the server.
App layouts is too close, we won't spend time on it but if someone feels inclined to have a stab at it we'll happily merge it