šŸ’Ž Try Recall with a 7 day free trial!

TinyLog

When 5 minute job turn to days

August 22, 2022

Michael Salim

@IAmMichaelSalim

Hero image

Created using Midjourney - "japanese worker getting stressed in the office, black clothes, office setting, high stakes, monotone, high detail, 8k, --q 2 --ar 16:9"

Creating this blog section should be easy, right?

Well, hereā€™s what happened:

Server Env variables

The project is built on Next.js. It just happened that I had code lying around on my personal website for my own blog. Easy copy paste job right? Unfortunately, because these pages will be pre-rendered by Next.js, there were some issues.

For one, the whole project is currently server rendered. One assumption was on the environment variable. The code is relying on the fact that ROOT_URL can be found. The problem is that the variable is not built in. This is so that we can change the variable without rebuilding the docker image. This is problematic since that functionality will be broken. Thereā€™s also some guards preventing this from happening.

After some thinking, I decided to remove that functionality. It just doesnā€™t bring enough benefit to offset the downside.

In the first place, how often am I going to change the ROOT_URL? Probably never. And a docker build is just a command away.

Apollo SSR Issue

Recall uses GraphQL and Apollo for most of its queries. Getting it to work with SSR can be finicky. I use the next-with-apollo library to get this to play nicely.

All this was handled in the _app.tsx file. For those that donā€™t know, changes to this file is propagated to all your pages. Convenient if you have code that needs to run everywhere.

Apollo was also initiated here. This suddenly became an issue since some pages will be SSR and some will be static. So what do we do with Apollo?

According to next-with-apollo's documentation, any page with getInitialProps or getDataFromTree will be SSR.

So:

  • Some marketing pages wonā€™t need Apollo at all
  • Some can be pre-generated but will still need Apollo to do mutations (eg: The support page)
  • And last, most of the app will be SSR

Rendering Apollo conditionally

We canā€™t keep the logic in _app.tsx anymore since we canā€™t change how that renders depending on the page. Those that need SSR needs the getDataFromTree prop. Meanwhile, static page need them gone.

There are 2 options:

  • Somehow find a way to manipulate the prop depending on the page - unlikely to find a method to do it nicely.
  • Use a default ApolloProvider without SSR. Then wrap another ApolloProvider if we need the SSR capability (or the reverse). I tried it but there are issues with multiple provider when doing SSR.
  • Wrap the correct Apollo instance on each page - a lot of work and something to remember in the future.

I didnā€™t want to do the 3rd option. But I experimented with the first 2 along with other ideas. Those didnā€™t get anywhere. After a good night sleep, I decided to go ahead with it.

Bug when changing page

After some work, I did it! I just need to wrap a withApollo or withApolloSSR on every page.

Nope.

Each page can be rendered just fine when you open them directly. However, navigating from a page to another page wasnā€™t working. Apollo complained that it canā€™t find the ApolloProvider . This is odd. But after debugging some more, I decided that this is a lost cause.

So what now?

A separate instance?

There was another option that dare not dream. Run another Next.JS instance. One for SSR, one for those that can be statically generated. I could redirect the request to the correct instance.

With no other options in mind, I started working on a proof of concept. It didnā€™t go well.

Running 2 next instance in a custom server was not a good fit. I donā€™t even want to think about all the other issues ā€” having to write in the correct place, having to handle the routing. What about development built?

Maybe I could build and export one of it? But it was too much work.

I was devastated. All this work for nothing. Is it time to call it quits and revert everything?

Thinking outside the box

The fact that this ā€œblogā€ exists means that something went well šŸ™‚

I realized something:

I canā€™t get _app.tsx to change. But what if i modify the getDataFromTree method to be smart instead? Then that page can stay the same.

Diving deep into the next-with-apollo package, I found this line.

We want Apollo to be SSR when it runs in the server. So I just need to add a check for that.

As if by magic. Everything is solved.

After all thatā€¦ Just a single line to patchšŸ¤¦šŸ»ā€ā™‚ļø. Ok, there's a few more lines but they were trivial :)

There must be something to learn out of this. Well, thatā€™s up to you to get something out of this!

Maybe think before you code? Or perhaps donā€™t work during the weekend šŸ˜‚. Or maybe donā€™t sleep at 5am šŸ˜¶


Like this kind of content? Why not see the reason I started writing TinyLog

Browse all TinyLog

Ā© 2021-2023 EPICAT LTD

SupportPrivacy Policy

LINKS

PricingMy StoryTinyLog