What's new in Caching of Next.js 15?
Caching is like temporarily saving information, so when a user visits your website again, it can load faster. It prevents repeated fetching of the same data, reducing the need for reprocessing and improving performance. But there are situations when you want to show real-time data, and caching can be a problem if not managed well.
Pre-requisites
What is Partial Prerendering (PPR)?
Partial Prerendering (PPR) combines static and dynamic content on a page.
- Static Content: Parts of the page that don’t change often (like images or text).
- Dynamic Content: Parts that change based on user actions or frequently updated data (e.g., new comments or notifications).
PPR renders the static parts first and “fills in” the dynamic parts as the data becomes available. This approach makes your site faster by delivering some content immediately, rather than waiting for everything to load.
How Does fetch() Work in Next.js?
The fetch()
function is used to retrieve data from APIs or other servers. In Next.js, it was initially set up to cache responses by default, which could conflict with dynamic needs. For example:
- If you fetch user-specific data but the cache returns old data, the user sees outdated information.
What's changed in Next.js 15 Caching?
In Next.js 15:
- Uncached by Default:
- By default, the server no longer caches GET Route Handlers or Client Router Cache. This change ensures that the app always fetches the most recent data.
- It helps dynamic content load correctly without showing old data.
- Opting Back into Caching:
- If needed, you can still opt back into caching by adding configurations like
force-cache
orrevalidate
to control how long data should be cached.
- If needed, you can still opt back into caching by adding configurations like
Understand with a flowchart
Before Next.js 15
- The page would cache blog posts automatically, even when they were updated.
- Users might see old posts because the cache hasn’t refreshed.
In Next.js 15
- You must explicitly set caching rules. If you don’t set them, the page will always fetch fresh data, ensuring users see the latest blog posts.
This approach makes it easier to manage data freshness and reduces conflicts with dynamic rendering. Let me know if this clarifies things further!
Why Was Caching Behavior Changed in Next.js 15?
Earlier versions of Next.js had “opinionated caching defaults,” meaning that caching was enabled automatically to boost performance. However, this led to issues like:
- Stale Data in Dynamic Content: PPR needed fresh data, but the old default caching made it difficult to update the dynamic parts.
- Conflicts with
fetch()
API: Third-party libraries fetching real-time data struggled with caching settings.
How to Configure Caching in Next.js 15
To customize caching behavior, you need to update the caching strategy in your app’s configuration:
Example
Before, caching was the default behavior:
export const runtime = 'edge';
export async function GET(request) {
return new Response('Hello, world!');
}
In Next.js 15, to enable caching explicitly:
export const runtime = 'edge';
export const revalidate = 60; // Cache for 60 seconds
export async function GET(request) {
return new Response('Hello, world!');
}
revalidate
sets the cache duration in seconds, specifying how long the response should be cached before it is considered stale.- This allows developers to have granular control over caching based on endpoint requirements.
FAQs
Q1: I noticed my app is suddenly slower after upgrading. Could it be due to the caching changes?
Yes, it’s possible. In Next.js 15, the default caching behavior for GET Route Handlers and the Client Router Cache has shifted to uncached by default. This means that all your API calls, especially those fetching large datasets, will now request fresh data every time. You may want to opt into caching for specific routes using the revalidate
property to improve performance where real-time data isn't critical.
Q2: How can I selectively enable caching only for certain routes in Next.js 15?
If you need to reintroduce caching for specific API routes, you can set the revalidate
property in the route handler. For example, if your blog posts update infrequently, you could use:
export const revalidate = 600; // Cache for 10 minutes
Similarly, for client-side caching, use libraries like useSWR()
to control cache duration, reducing redundant network requests for static data.
Q3: Will changing to uncached defaults affect my app's behavior with Partial Prerendering (PPR)?
Yes, it will. With PPR, the goal is to prerender static parts while dynamically fetching fresh content. Previously, cached defaults could interfere with dynamic data. In Next.js 15, uncached defaults align better with PPR, ensuring real-time updates without stale data. You still have the option to cache static components that don't require frequent updates.
Q4: What if my users start complaining about slower page loads after upgrading?
This can happen because cached responses from previous versions are no longer available by default. To resolve this, review which routes need real-time data and which ones can benefit from caching. Use the revalidate
or no-store
option to control how data is fetched and cached based on the frequency of changes.
Q5: How do I know if I need to opt back into caching?
A good rule of thumb is to ask, “Is this data dynamic or static?”
- Dynamic Data: Real-time data (e.g., user notifications, comments) should not be cached.
- Static Data: Data that changes infrequently (e.g., blog posts, product catalogs) can be cached to reduce server load and improve speed.
Q6: What if I forget to adjust the caching settings?
If you leave caching settings unchanged, your app will behave as if all requests are uncached by default. This means more server load and potential slower response times. Regularly check your network logs to identify high-traffic routes that might benefit from caching.
Q7: What should I do if third-party libraries using fetch()
start behaving unexpectedly?
Libraries that rely on fetch()
might fetch fresh data by default due to the new uncached behavior. To control this, add caching options directly to the fetch()
request:
fetch('/api/data', { cache: 'force-cache' });
This will force the response to be cached, aligning with previous behavior.
Q8: Can I still use static site generation (SSG) with the new caching changes?
Yes, you can! Static Site Generation (SSG) remains compatible. The new caching behavior only impacts routes and data fetching during runtime. You can still generate static pages at build time using getStaticProps()
and enable revalidation with the revalidate
property.
These questions and answers should help make the caching changes in Next.js 15 clearer and more practical for developers upgrading their projects. Let me know if you need further adjustments!
Summary
Next.js 15 introduces more flexible caching options by setting uncached defaults for GET Route Handlers and the Client Router Cache. By opting into caching manually, developers can tailor the caching behavior to meet their application’s needs.