Written by Yomi Eluwande✏️
In Next.js, data fetching methods play a crucial role in enabling server-side rendering (SSR), static site generation (SSG), and client-side data fetching for your React components. These methods allow you to fetch data from various sources (e.g., APIs, databases, external services) and use that data to pre-render pages or hydrate them on the client side.
In this article, we’ll explore the getInitialProps
, getServerSideProps
, and getStaticProps
data fetching methods. We’ll take a look at the role getInitialProps
played in previous versions of Next.js and the transition to newer and better data fetching methods.
Jump ahead:
- Understanding
getInitialProps
- Transitioning to
getServerSideProps
andgetStaticProps
- A deep dive into the
getServerSideProps
lifecycle - The role of
getInitialProps
in Next.js 13 - Optimizing
getServerSideProps
for performance in Next.js 13 - Migrating from
getInitialProps
togetServerSideProps
orgetStaticProps
Understanding getInitialProps
getInitialProps
is a method used in older versions of Next.js (versions prior to 9.3) to fetch data on the server side before rendering a page. It was the primary data fetching method used in Next.js before newer data fetching methods like getServerSideProps
and getStaticProps
were introduced.
In older versions of Next.js, getInitialProps
was the primary data fetching mechanism for both SSR and client-side rendering. It allowed developers to perform custom data fetching logic for each page and pass the fetched data as props to the page component:
// In older versions of Next.js, you would define getInitialProps like this:
import React from 'react';
const HomePage = ({ posts }) => {
// Render the list of posts
return (
<div>
<h1>Latest Blog Posts</h1>
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
};
HomePage.getInitialProps = async () => {
// Fetch data from an API
const response = await fetch('https://api.example.com/posts');
const posts = await response.json();
// Return the data as props
return { posts };
};
export default HomePage;
In this example, the getInitialProps
method fetches the list of blog posts from the API server-side. When a user visits the homepage, the server will pre-render the page with the fetched data and serve it as a complete HTML page. This approach helps with SEO, improves initial page load times, and ensures that the page has the necessary data before being served to the client.
Transitioning to getServerSideProps
and getStaticProps
The transition from getInitialProps
to getServerSideProps
and getStaticProps
in Next.js represented a significant improvement in data fetching and rendering strategies. This change was introduced to simplify data fetching, enhance performance, and provide better predictability in terms of when and where data is fetched.
Let’s start by looking at what the getServerSideProps
and getStaticProps
lifecycles are useful for, and how they each mark pages for rendering.
getServerSideProps
is a data fetching method that was introduced in Next.js 9.3. It is used specifically for server-side rendering (SSR). Unlike getInitialProps
, getServerSideProps
is only executed on the server side during the initial page request and not on subsequent client-side navigations. This change improves performance by reducing duplicate data fetching and provides better predictability of server-side data fetching.
getStaticProps
is another data fetching method that was introduced in Next.js 9.3, and it is used for static site generation (SSG). When using getStaticProps
, Next.js pre-renders the page at build time and fetches the data during the build process. The pre-rendered HTML pages are then served to users directly from the CDN, offering faster page loads and reducing server load.
These new data fetching methods ensured better performance by reducing unnecessary data fetching and improving the performance of your Next.js application by fetching data more intelligently. With getServerSideProps
, you know that data is fetched only during the initial server-side request, making it easier to understand when and where data is retrieved, and with getStaticProps
, the data will only be fetched at build time.
With the introduction of getStaticProps
and getServerSideProps
, Next.js users now have two different data fetching methods that are used to mark pages for rendering either at build time or upon each request respectively.
When a user requests a page that uses getServerSideProps
, the server will execute this function, fetch the data, and pass it as props to the page component. The page is then rendered on the server with the fetched data and sent to the client as a complete HTML page. This approach is known as server-side rendering (SSR), and it ensures that the page always has the most up-to-date data when accessed by users.
With getStaticProps
, you get the option to pre-render pages at build time, generating static HTML files with the fetched data. When you use getStaticProps
, Next.js runs the function during the build process (not on each request) and fetches the data needed for the page. The fetched data is then used to pre-render the page into a static HTML file, which is saved in the build output directory (e.g., the build
folder).
Now, when a user visits a page that was pre-rendered with getStaticProps
, Next.js serves the static HTML page directly from a CDN, improving page load times and reducing server load. This approach is called popularly known as static site generation (SSG), and it is ideal for pages with content that doesn't change frequently.
A deep dive into the getServerSideProps
lifecycle
As mentioned above, the getServerSideProps
lifecycle is used to fetch data on the server side and pre-render the page with the fetched data before sending it to the client. Unlike getStaticProps
, getServerSideProps
executes on each request, making it suitable for pages that require dynamic data or data that changes frequently.
The getServerSideProps
function takes a context object as a parameter that contains page data such as params
, res
, req
, query
, etc. Here's a breakdown of how the getServerSideProps
lifecycle works:
- When a user requests a page that uses
getServerSideProps
, the server-side code is executed first - The
getServerSideProps
function is called, and it fetches the necessary data from external APIs, databases, or other sources - The fetched data is then passed as props to the page component
- The page is pre-rendered on the server with the fetched data and sent as a complete HTML page to the client
- The client-side JavaScript takes over once the page is loaded, and any subsequent interactions are handled on the client side
When compared to the getInitialProps
lifecycle, getServerSideProps
is much cleaner and more predictable in terms of fetching data, especially when it comes to context switching between server operations and client operations.
With getInitialProps
, operations were being executed on both the server and client side, which sometimes led to duplicate data fetching during client-side navigation. But with getServerSideProps
, there was a clear understanding that data fetching logic in the getServerSideProps
lifecycle would be executed only on the server side during the initial request, eliminating the duplicate data fetching that might occur with getInitialProps
.
Example use cases for getServerSideProps
:
- Real-time data: If your page requires real-time data that changes frequently (e.g., live chat messages, real-time analytics), you can use
getServerSideProps
to fetch the latest data on each request - Authenticated data: When dealing with authenticated data that is user-specific and changes based on the user's session or permissions,
getServerSideProps
is well-suited for fetching this data securely on the server side - Dynamic pages: For pages with dynamic routes, where the content depends on the route parameters,
getServerSideProps
can fetch the data for the specific route during each request
In summary, getServerSideProps
offers a more straightforward and efficient way to fetch data on the server side, especially for pages that require server-side rendering and frequently changing data. It provides better control over data fetching, improved performance, and a smoother transition from the getInitialProps
lifecycle.
The role of getInitialProps
in Next.js 13
Despite the transition to newer data fetching methods, Next.js has maintained support for getInitialProps
for backward compatibility. This is because there might be existing projects that rely on getInitialProps
and transitioning all of them to the newer methods might be impractical in some cases.
To handle edge cases where getInitialProps
might still be necessary, consider the following scenarios:
- Complex data fetching logic: If your data fetching logic is complex and can't be easily achieved with
getStaticProps
orgetServerSideProps
, you might continue usinggetInitialProps
- Custom SSR logic: If you need custom server-side rendering logic that can't be achieved with the newer methods, you might choose to use
getInitialProps
- Legacy projects: If you're working on a legacy project that was built using older versions of Next.js and heavily relies on
getInitialProps
, it might be more practical to continue using it rather than rewriting everything
Optimizing getServerSideProps
for performance in Next.js 13
getServerSideProps
runs on every request, which means that if you're doing a lot of data fetching or computations, it can slow down your site. There are a few things you can do to optimize the use of getServerSideProps
for performance in Next.js 13.
One is to make sure you're returning the required props
object with the props
property, which can help reduce the number of repetitive calls. When you call getServerSideProps
, Next.js creates a server-side request to fetch the data. This request can be quite expensive, especially if you're doing a lot of computations. If you return the required props
object, Next.js will memoize the request and reuse the result for subsequent calls. This is important because it means that Next.js doesn't have to make multiple requests to the server to get the same data, which can significantly improve performance.
Another way to optimize the use of getServerSideProps
in your project is by taking advantage of smarter caching. It works by caching the results of your request based on the content that was requested. For example, if a user requests a specific page, Next.js will only cache the data for that page. This means that if another user requests a different page, it won't have to load the entire site from scratch, which can save a lot of time. This is different from traditional caching, which simply stores the entire site in a cache and serves it to all users.
Another benefit of smarter caching is that it allows for "incremental updates". This means that if you make a small change to your code, only the affected parts of the site will be updated in the cache.
Migrating from getInitialProps
to getServerSideProps
or getStaticProps
Migrating from getInitialProps
to getServerSideProps
or getStaticProps
involves updating your data fetching logic to the new data fetching methods introduced in Next.js. The migration process depends on whether you want to achieve server-side rendering (SSR) or static site generation (SSG). Here's a detailed overview of the steps involved in the migration:
Migrating to getServerSideProps
(SSR):
- Remove
getInitialProps
: If your page components usegetInitialProps
, you need to remove it from those components - Replace
getInitialProps
withgetServerSideProps
: Replace thegetInitialProps
method with thegetServerSideProps
method in your page components. The structure ofgetServerSideProps
is different fromgetInitialProps
, and it returns an object with theprops
key containing the fetched data - Pass props to the component: With
getServerSideProps
, the fetched data will be automatically passed as props to the page component. You can access this data using theprops
parameter of your page component
Let's consider a simple example where you have a blog application, and you want to fetch a list of blog posts from an external API to display on the homepage:
// Before migrating from getInitialProps
const HomePage = ({ posts }) => {
// Render the list of posts
};
HomePage.getInitialProps = async () => {
// Fetch data from an API
const response = await fetch('https://api.example.com/posts');
const posts = await response.json();
// Return the data as props
return { posts };
};
// After migrating to getServerSideProps
const HomePage = ({ posts }) => {
// Render the list of posts
};
export async function getServerSideProps() {
// Fetch data from an API
const response = await fetch('https://api.example.com/posts');
const posts = await response.json();
// Return the data as props
return {
props: { posts },
};
}
Migrating to getStaticProps
(SSG):
- Remove
getInitialProps
: If your page components usegetInitialProps
, you need to remove it from those components - Replace
getInitialProps
withgetStaticProps
: Replace thegetInitialProps
method with thegetStaticProps
method in your page components. LikegetServerSideProps
, the structure ofgetStaticProps
is different fromgetInitialProps
, and it returns an object with theprops
key containing the fetched data - Data revalidation (optional): With
getStaticProps
, you can also include therevalidate
option in the returned object to specify how often the data should be revalidated and regenerated. This is useful when you want to update the data periodically without redeploying your application
Using the same example use case as above, here is our code before and after migrating from getInitialProps
and getStaticProps
:
// Before migrating from getInitialProps
const HomePage = ({ posts }) => {
// Render the list of posts
};
HomePage.getInitialProps = async () => {
// Fetch data from an API
const response = await fetch('https://api.example.com/posts');
const posts = await response.json();
// Return the data as props
return { posts };
};
// After migrating to getStaticProps
const HomePage = ({ posts }) => {
// Render the list of posts
};
export async function getStaticProps() {
// Fetch data from an API
const response = await fetch('https://api.example.com/posts');
const posts = await response.json();
// Return the data as props
return {
props: { posts },
};
}
Conclusion
In summary, migrating from getInitialProps
to getServerSideProps
or getStaticProps
involves updating the data fetching logic and method signatures to improve performance, predictability, and context switching in your Next.js application. Depending on your use case, you can choose between getServerSideProps
for server-side rendering or getStaticProps
for static site generation.
LogRocket: Full visibility into production Next.js apps
Debugging Next applications can be difficult, especially when users experience issues that are difficult to reproduce. If you’re interested in monitoring and tracking state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.
LogRocket is like a DVR for web and mobile apps, recording literally everything that happens on your Next.js app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.
The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.
Modernize how you debug your Next.js apps — start monitoring for free.
Top comments (1)
Hey,
Is there any reason to use page router now that app router exists?