In the App Router, data is fetched directly in Server Components using `async/await` with automatic caching. The Pages Router uses special functions like `getStaticProps` (build time) and `getServerSideProps` (request time).
App Router Data Fetching:
Server Components can be async and fetch data directly:
async function Page() {
const data = await fetch('...');
}
Caching Behavior:
fetch() is cached by default (SSG){ cache: 'no-store' } - No caching (SSR){ next: { revalidate: 60 } } - ISR (revalidate after 60s)Pages Router Data Fetching:
getStaticProps - Build time (SSG)getStaticPaths - Dynamic routes for SSGgetServerSideProps - Request time (SSR)Client-Side Fetching:
useEffect + useState (manual approach)Parallel vs Sequential:
Promise.all for parallel fetches// app/posts/page.tsx - Server Component
// Cached by default (SSG behavior)
async function getPosts() {
const res = await fetch('https://api.example.com/posts');
if (!res.ok) throw new Error('Failed to fetch posts');
return res.json();
}
export default async function PostsPage() {
const posts = await getPosts();
return (
<ul>
{posts.map((post: any) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}
// With revalidation (ISR)
async function getPostsISR() {
const res = await fetch('https://api.example.com/posts', {
next: { revalidate: 3600 }, // Revalidate every hour
});
return res.json();
}
// Force dynamic (SSR)
async function getPostsSSR() {
const res = await fetch('https://api.example.com/posts', {
cache: 'no-store', // Always fetch fresh
});
return res.json();
}