You are correct: in the App Router, there is no getStaticProps. Instead, data fetching and caching are controlled at the fetch/request level, and static generation with revalidation (ISR) is typically achieved using the revalidate option—most commonly with fetch requests. For example:
export const revalidate = 60;
export default async function Page() {
const data = await fetch('<https://...',> { next: { revalidate: 60 } });
}
How to implement Incremental Static Regeneration (ISR)
What about local data (DB/files)?
You are not limited to fetch for ISR. Next.js provides the unstable_cache utility, which allows you to cache the result of any async function—including database queries or file reads—and set a revalidation interval. Here’s how you can use it:
import { unstable_cache } from 'next/cache';
const getCachedData = unstable_cache(
async () => {
return getDataFromDBorFile();
},
['cache-key'],
{ revalidate: 60 }
);
export default async function Page() {
const data = await getCachedData();
}
Caching and Revalidating
This approach allows you to generate a static page, cache it, and have it revalidate every 60 seconds, even if your data source is not a fetch request.
You do not need to use force-dynamic for this use case. force-dynamic is only necessary if you want the page to be rendered on every request (i.e., no caching at all), which is not what you want.