Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fetch data only once in a Next.js app and make it accesible to all the app, both in server and client

I'm working on a Next.js app that needs to fetch a config file from a remote server before initializing. I want to request the config file just once per call to the server before rendering the app server side. After that, I would like to be able to get the same config in the client without having to make a second request to the remote server from the browser.

I have tried to achieve this by using getInitialProps function either in _app or _document files and then use the React's Context API to make the configuration visible to every component but unless I'm wrong, this will run the code that requests the configuration both in server (on the first call from the browser) and client (on every page navigation).

I have also tried to create a server.js file, request the configuration from there and store in a variable within a ES6 module. However, I couldn't make this approach work because apparently the Next.js React app can't access the same modules than the server.js because they are actually two different apps. Again, I could be wrong.

Basically I would like to know if Next.js offers any kind of "bootstrapping place" where I can perform app initialization tasks that generate data that can be sent to the React app Next.js will initiate.

like image 727
Markel Arizaga Avatar asked Sep 02 '19 15:09

Markel Arizaga


People also ask

Can I use fetch in NextJS?

Data fetching in Next. js allows you to render your content in different ways, depending on your application's use case. These include pre-rendering with Server-side Rendering or Static Generation, and updating or creating content at runtime with Incremental Static Regeneration.

What is dynamic data fetching?

No fetching 9.2.2. Dynamic fetching via queries 9.2.3. Dynamic fetching via profiles. Fetching, essentially, is the process of grabbing data from the database and making it available to the application.


Video Answer


2 Answers

You are correct in that anything in getInitialProps in _app.js or _document.js will be run on every server request. Once you get your config, you can pass it down to the components in pages as props. From there, I think you have two choices:

  1. Now that the app is bootstrapped, run the rest of the app as a SPA client-side. This would prevent any future SSR from happening. Obviously, you lose the benefits of SSR and the initial page load is likely longer, but then it would be snappy afterwards.
  2. After getting the config in _app.js, send it as a cookie (assuming it's not too big to be a cookie?). On future requests to the server, the cookie will be sent automatically and you would check the cookie first - if it doesn't exist, get the config. If it does exist, skip that more expensive bootstrapping because the app is bootstrapped.

So I think it really depends on whether you want a single page application bootstrapped on the server but then entirely client side after that (option 1) or server side rendering per page while minimizing expensive bootstrapping (option 2).

Nothing prevents you from sending multiple cookies from the server if that makes sense for your app and bootstrapping. And remember not to make it a HTTP-Only cookie because you'll want to read that cookie client side - after all, that's what you're looking for - the client side configuration generated on the server.

like image 59
I'm Joe Too Avatar answered Oct 22 '22 05:10

I'm Joe Too


Despite we ended up leaving Next.js for this and other reasons that made us decide Next.js was not the best option for our use case, we kind of mitigated this problem as follows while be sticked to it, I hope it makes sense to anyone. Also, by now maybe Next.js provides a better way to do this so I would read the Next.js docs before using my approach. Final note: I don't have access to the code anymore since I change to a different company so maybe there are some points that won't be 100% as we made it.

There is goes:

  1. We created a module that was responsible to request the config file and keep the results in a variable. At the moment of importing this module, we ensure that the variable is not already present in window.__NEXT_DATA__. If it is, we recover it, if it's not, we request it to the remote server (this will be helpful in the clint side rendering).
  2. We created a server.js file as described by Next.js docs. In this file we make the call to get the config file and store it in memory.
  3. In the body of the function passed to createServer we add the config file into the req object to make it accesible to the app in the getInitialProps functions server side.
  4. We made sure that the getInitialProps using the config file returns it, so that it will be passed to the components as props and also serialized by Next.js and made available to the client in the __NEXT_DATA__ global Javascript variable.
  5. Given that the config ended up in the __NEXT_DATA__ variable in the server, using the trick described in the step 1 makes the app not request the config for a second time.
like image 4
Markel Arizaga Avatar answered Oct 22 '22 06:10

Markel Arizaga