### Create Server Component Page with Data Fetching in Next.js App Directory
Source: https://github.com/vercel/next.js/blob/canary/docs/01-app/02-guides/migrating/app-router-migration.mdx
Shows how to create a new page.tsx file in the app directory that acts as a Server Component by default. This component imports the Client Component and handles data fetching using the new data fetching APIs. The fetched data is then passed as props to the Client Component.
```typescript
// Import your Client Component
import HomePage from './home-page'
async function getPosts() {
const res = await fetch('https://...')
const posts = await res.json()
return posts
}
export default async function Page() {
// Fetch data directly in a Server Component
const recentPosts = await getPosts()
// Forward fetched data to your Client Component
return <HomePage recentPosts={recentPosts} />
}
```
```javascript
// Import your Client Component
import HomePage from './home-page'
async function getPosts() {
const res = await fetch('https://...')
const posts = await res.json()
return posts
}
export default async function Page() {
// Fetch data directly in a Server Component
const recentPosts = await getPosts()
// Forward fetched data to your Client Component
return <HomePage recentPosts={recentPosts} />
}
```
--------------------------------
### Migrate getServerSideProps to App Router Server Component
Source: https://github.com/vercel/next.js/blob/canary/docs/01-app/02-guides/migrating/app-router-migration.mdx
Shows how to replace getServerSideProps from pages directory with an async Server Component in the app directory. Data fetching is colocated within the component using fetch with cache: 'no-store' to ensure fresh data on every request, reducing client-side JavaScript.
```javascript
// `pages` directory
export async function getServerSideProps() {
const res = await fetch(`https://...`)
const projects = await res.json()
return { props: { projects } }
}
export default function Dashboard({ projects }) {
return (
<ul>
{projects.map((project) => (
<li key={project.id}>{project.name}</li>
))}
</ul>
)
}
```
```javascript
// `app` directory
// This function can be named anything
async function getProjects() {
const res = await fetch(`https://...`, { cache: 'no-store' })
const projects = await res.json()
return projects
}
export default async function Dashboard() {
const projects = await getProjects()
return (
<ul>
{projects.map((project) => (
<li key={project.id}>{project.name}</li>
))}
</ul>
)
}
```
--------------------------------
### Fetch Data with Cache Options in App Router
Source: https://github.com/vercel/next.js/blob/canary/docs/01-app/02-guides/migrating/app-router-migration.mdx
Demonstrates three caching strategies for data fetching in async React Server Components: force-cache for static data (equivalent to getStaticProps), no-store for dynamic data (equivalent to getServerSideProps), and revalidate for time-based cache invalidation. Uses the fetch API with cache and next options.
```typescript
export default async function Page() {
// This request should be cached until manually invalidated.
// Similar to `getStaticProps`.
// `force-cache` is the default and can be omitted.
const staticData = await fetch(`https://...`, { cache: 'force-cache' })
// This request should be refetched on every request.
// Similar to `getServerSideProps`.
const dynamicData = await fetch(`https://...`, { cache: 'no-store' })
// This request should be cached with a lifetime of 10 seconds.
// Similar to `getStaticProps` with the `revalidate` option.
const revalidatedData = await fetch(`https://...`, {
next: { revalidate: 10 },
})
return <div>...</div>
}
```
```javascript
export default async function Page() {
// This request should be cached until manually invalidated.
// Similar to `getStaticProps`.
// `force-cache` is the default and can be omitted.
const staticData = await fetch(`https://...`, { cache: 'force-cache' })
// This request should be refetched on every request.
// Similar to `getServerSideProps`.
const dynamicData = await fetch(`https://...`, { cache: 'no-store' })
// This request should be cached with a lifetime of 10 seconds.
// Similar to `getStaticProps` with the `revalidate` option.
const revalidatedData = await fetch(`https://...`, {
next: { revalidate: 10 },
})
return <div>...</div>
}
```
--------------------------------
### Server-Side Rendering with App Router
Source: https://github.com/vercel/next.js/blob/canary/docs/01-app/02-guides/migrating/app-router-migration.mdx
Demonstrates implementing server-side rendering in the app directory using async Server Components with fetch and cache: 'no-store'. This replaces getServerSideProps functionality while allowing data fetching to be colocated within components.
```typescript
// `app` directory
// This function can be named anything
async function getProjects() {
const res = await fetch(`https://...`, { cache: 'no-store' })
const projects = await res.json()
return projects
}
export default async function Dashboard() {
const projects = await getProjects()
return (
<ul>
{projects.map((project) => (
<li key={project.id}>{project.name}</li>
))}
</ul>
)
}
```
```javascript
// `app` directory
// This function can be named anything
async function getProjects() {
const res = await fetch(`https://...`, { cache: 'no-store' })
const projects = await res.json()
return projects
}
export default async function Dashboard() {
const projects = await getProjects()
return (
<ul>
{projects.map((project) => (
<li key={project.id}>{project.name}</li>
))}
</ul>
)
}
```
--------------------------------
### Incremental Static Regeneration with fetch in App Directory
Source: https://github.com/vercel/next.js/blob/canary/docs/01-app/02-guides/migrating/app-router-migration.mdx
Shows how to implement ISR in the app directory using the fetch API with the next.revalidate option. This approach replaces getStaticProps and allows caching of fetch requests for a specified duration. The component is async and directly fetches data within the component function.
```jsx
async function getPosts() {
const res = await fetch(`https://.../posts`, { next: { revalidate: 60 } })
const data = await res.json()
return data.posts
}
export default async function PostList() {
const posts = await getPosts()
return posts.map((post) => <div>{post.name}</div>)
}
```