- Blogs
- Detrás del Lienzo
- Best Practices for Fetching Data in Next.js
Detrás del Lienzo / 4 min de lectura
Best Practices for Fetching Data in Next.js
Efficient data fetching is key to creating a smooth and fast user experience in Next.js apps.
In this article, we’ll explore how our development team learned to optimize Next.js data fetching by using server components for initial data loading and client components for managing interactivity.
We’ll share some best practices for creating custom hooks that optimize code and reduce redundancies, providing a solid approach that enhances both performance and the development experience.
When to Use Server Components vs. Client Components in Next.js?
One of the main decisions when working in Next.js is determining when to use server components and when to opt for client components. The general rules we use are the following:
- Server components are ideal for static content or data that doesn’t change with user interaction. Since they run on the server, they offer fast loading and optimize the overall page performance.
- Client components are ideal when we require real-time interactivity, such as with forms that feature immediate validation, dynamic filters, and interactive charts.
Best Practices for Performance Optimization in Next.js
In a recent project for a client that manages a Storyblok site with numerous blogs and filters, we opted for a hybrid strategy.
We used server components for the initial data fetching, improving both SEO and TTFB (Time to First Byte) to provide a quick initial load.
We then transferred this data to a client component that managed interactivity and real-time filters.
This hybrid approach allowed us to deliver a smooth user experience without compromising performance.
Based on this experience, we realized that data-fetching strategies in Next.js rely on understanding the content and required endpoints.
Here are some key practices that have been effective for our team:
Caching Strategies in Server Components
There are three main options for handling cache in Next.js:
- force-cache. Caches data indefinitely. Ideal for data that rarely or never changes.
- no-store. Disables caching, causing each API call to be made in real time.
- next.revalidate. Sets a time window to revalidate the cache. Useful for data that requires periodic updates.
We select the most appropriate caching strategy depending on the nature of the content. We found next.revalidate
particularly useful for content that changes frequently, as it balances performance with providing fresh data.
Incremental Static Regeneration (ISR)
For pages that are mostly static, we use ISR with getStaticProps
, which allows pages to regenerate incrementally without a new deployment. This technique is useful for content like blogs or product pages that are updated occasionally.
We Used Custom Hooks to Standardize Data Fetching
To avoid redundancies and improve consistency, we developed custom hooks to facilitate data fetching.
One example is a reusable hook that receives the endpoint and other properties, like the number of items to fetch. This pattern helps reduce boilerplate and simplifies fetching configuration across different application modules.
This approach saves the team time and minimizes errors, as we can manage any adjustments to the fetching strategy from a single point. Additionally, hooks allow developers to focus on business logic without worrying about repetitive technical details.
How Learning When to Use Server or Client Components Impacted Our Efficiency
Learning when to use server or client components significantly improved the efficiency of our development efforts and the performance of our application. Some of the benefits include:
- Separation of responsibilities. Server components handle backend logic, while client components manage interactivity. This division makes the code more modular and easier to maintain.
- Reduced client-side JavaScript load. Using server components reduces the amount of JavaScript needed on the client side, improving page load times and performance. This is effective for high-traffic applications.
- Optimization of SEO and load times. Pre-rendering data in server components improves the user experience and enhances SEO, as search engines can index content without relying on JavaScript.
The client was pleased with the results, as the site maintained interactivity while also handling high traffic volumes without sacrificing load speed.
What Did We Learn From Our Experience Fetching Data With Next.js?
We learned that an effective data-fetching strategy when working with Next.js in Storyblok comes with some challenges. One of the biggest hurdles was integrating Next.js with Storyblok while using server components.
Storyblok provides an integration that includes live editing, which requires using a Provider as a client component, causing all components under its hierarchy to act as client components as well.
This limited our use of server components and required additional adjustments to maintain the desired performance without compromising the live editing experience.
Despite the challenges, learning to use server and client components in Next.js appropriately has been a powerful strategy for enhancing both performance and development efficiency.
Having a structured approach to data fetching and using custom hooks helps us maintain clean, optimized code and deliver outstanding results to clients in both interactivity and load speed.
As an agency dedicated to pushing the limits of what we can do to provide better results to clients, we constantly look for ways to learn and adopt the most effective strategy for every project.
If you found this post useful, read our blog and developer resources for more insights and guides!