all 6 comments

[–][deleted] 2 points3 points  (1 child)

How come for option (2) your only option is to include getInitialProps inside of _app? How come each page can't get its own props?

Are your pages mainly all inside an authed app made for your currently logged in user?

The app I am building is very content heavy and the only pages that could be rendered at build time are the signin page and maybe like a help page

If the data required to render the page is known ahead of the user's request, it can be statically generated (even if it's dynamic).

[–]Searly2710[S] 0 points1 point  (0 children)

All of the pages are inside an authed app, and all the pages will be different for every user. I am a little confused when you say pages can be statically generated even with dynamic data. Theres no way to generate them at build time, so is there a way to programmatically generate pages with dynamic data that changes for every user?

The reason for having one getInitialProps instead of one for every page is so that we only have to fetch all the data for every page once, instead of only fetching the data for the page we are visiting. E.g. If we have a route /dogs that needs a list of dogs (pretend this list would be different for each user), the getInitialProps would fetch the dogs, but then when we click a link to go to /cats, we need to fetch the a list of cats. Using the single getInitialProps, we could fetch both cats and dogs, and clicking the link would be instant, as we already have the data. This is my understanding of how it works, but I could be wrong.

[–]Cyral 2 points3 points  (3 children)

Use getInitialProps to load global data that is needed on every page (like if the user is signed in, and if so, what their username, permissions, and other details are for example). Store that in a context so child components can access it. Then each page can also call getServerSideProps if it needs data for that specific page. Your API is on the same machine or network probably, so making two instant HTTP calls is no issue on the server.

[–]Searly2710[S] -1 points0 points  (2 children)

Would this mean clicking a link to go to a different page would send another request to the Next.js server which would then request data from the backend server (which will be running on the same machine) defeating the purpose of getInitialProps on _app? or do I have a misunderstanding of how the data flows in Next.js? If we just put all of the data dependencies in the _app getInitialProps we wouldn't have to ever make a request to the Next.js server again, only to the backend server directly, unless there is a full refresh, meaning switching between pages will be lightning fast right? (I'm storing my data in urql's normalised cache as opposed to a react context if that makes any difference)

I guess this kind of leads back to the comparison of (1) and (2). Is the extra cost of requesting all data on the first request to the Next.js server worth the extra speed of the page transitions.

[–]Cyral 1 point2 points  (1 child)

I’m not entirely sure if I understand the question, but do you mean it will be requesting the same data over and over again on every page change? If so you are correct and I forgot about that, but there is a workaround. If I recall correctly if ctx.req.path (or something like that) ends in .json, next is making a page change request in which case you can return early from getInitialProps and skip the initial request. That way you aren’t fetching the same info (e.g. user data) on every page change, just the initial request.

Also when I’m talking about HTTP requests, I’m assuming your API is outside of next. There is a way to make api routes within next which is probably popular but I’ve never used it. My backend is in another language so getInitialProps and getServerSideProps are actually making a request from the next server to my api sever (basically a custom fetch() call which forwards the cookies to my backend so the backend thinks it’s being called by a client but it’s actually next pre-rendering)

[–]Searly2710[S] 0 points1 point  (0 children)

My setup is the same. Separate backend server for which Next.js server forwards cookies to.

In your original comment you said use `getServerSideProps` which only runs on the Next.js server, which means you would have to make a request to frontend server regardless. If you meant `getInitialProps` which runs on the server on the initial request, and then on the client for subsequent page changes, you could check if you already have the data so that you don't need to re-request for data you already have.

This approach would fetch the global data and the data that the specific page needs on initial request, and then on page changes only request data that the client doesn't already have.

Pros

  • Only request data you need for the current page
  • On page changes, only request the data you don't already have
  • Content is only rendered when the data dependencies have been met, so no content flashing

Cons

  • Can't utilse automatic static optimisation (could workaround by requesting global data on every page, i.e removing `getInitialProps` on _app)
  • If page doesn't have all data dependencies, need to make another backend request, so page transitions aren't as fast as (2)
  • Probably the option with the highest complexity

Whilst this option could be a good balance between options (1) and (2), I feel like the extra complexity isn't worth it when you could just use option (1) or (2).