Part 43: Choosing the Best Data Fetching Strategy in Next.js
[Pages] Data Fetching

As we explore the various ways to fetch data in a Next.js application, it's essential to choose the right strategy based on your specific requirements. With options ranging from static generation to server-side rendering and client-side data fetching, the decision can significantly impact the performance, SEO, and user experience of your application. Let's review the available options and decide which approach is the best fit for our use case.
Overview of Data Fetching Options
1. Static Generation with getStaticProps (Option 1a)
getStaticProps (Option 1a)Description: Fetches data at build time and includes it in a statically generated page.
Advantages: Fast page load times and excellent SEO since pages are pre-rendered and can be easily indexed by search engines.
Use Case: Ideal for content that doesn't change often or needs to be the same for all users.
2. Incremental Static Regeneration with getStaticProps and revalidate (Option 1b)
getStaticProps and revalidate (Option 1b)Description: Similar to static generation but allows pages to be regenerated periodically.
Advantages: Combines the benefits of static generation with the ability to update content automatically without redeploying the site.
Use Case: Suitable for dynamic content that updates occasionally, like product listings in a shop.
3. Server-Side Rendering with getServerSideProps (Option 1c)
getServerSideProps (Option 1c)Description: Fetches data at runtime on every request, generating the HTML page dynamically.
Advantages: Ensures fresh data for each request.
Drawbacks: Slower than static approaches and may not be necessary for all use cases.
Use Case: Useful for content that changes frequently and must be up-to-date for every user.
4. Client-Side Fetching from External API (Option 2a)
Description: Fetches data directly from the backend API in the browser.
Advantages: Access to fresh data on every page load.
Drawbacks: Exposes the backend API to the browser, which may not always be desirable.
Use Case: Appropriate when it's acceptable for the browser to interact directly with the backend API.
5. Client-Side Fetching via Internal API Route (Option 2b)
Description: Fetches data from an internal API route hosted on the same Next.js app.
Advantages: Protects the backend API and allows for data transformation before it reaches the client.
Use Case: Best when you want to control data flow and transform data on the server.
Decision-Making Guide
Choosing the best option depends on the nature of your data and your application's requirements. Here's a simple flowchart to guide your decision:
Is the data the same for all users?
Yes: Consider server-side approaches like static generation or ISR.
No: Client-side fetching might be more appropriate.
Can the data change?
No: Use Static Generation for fixed data.
Yes: Use ISR to update data periodically without full redeployment.
Is it okay for the browser to access the backend API directly?
Yes: Client-side fetching from the external API is fine.
No: Use an internal API route to mediate data access.
Need for SEO and fast page loads?
Consider server-side approaches to pre-render pages.
Applying the Best Choice
For our shop website, where product data can change and we want the site to update automatically without immediate urgency, Incremental Static Regeneration (ISR) is the optimal choice. This approach allows for periodic updates while maintaining the benefits of static generation.
Here's how to implement ISR for our product list:
// pages/index.js
import Head from 'next/head';
import Title from '../components/Title';
import { getProducts } from '../lib/products';
export async function getStaticProps() {
console.log('[HomePage] getStaticProps()');
const products = await getProducts();
return {
props: { products },
revalidate: 5 * 60, // revalidate every 5 minutes
};
}
function HomePage({ products }) {
console.log('[HomePage] render:', products);
return (
<>
<Head>
<title>Next Shop</title>
</Head>
<main className="px-6 py-4">
<Title>Next Shop</Title>
<ul>
{products.map((product) => (
<li key={product.id}>
{product.title}
</li>
))}
</ul>
</main>
</>
);
}
export default HomePage;Cleaning Up
With ISR chosen as the best approach, we can remove other data fetching options and the related files from our project to streamline our codebase:
Deleted Files:
pages/api/products.jspages/index-1a.jspages/index-1b.jspages/index-1c.jspages/index-2a.jspages/index-2b.js
By focusing on a single, effective data fetching strategy, we're ready to continue developing our shop website with a clean and efficient setup. This choice ensures our application is performant, scalable, and easy to maintain.
Last updated