Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs: RC Updates #70031

Merged
merged 75 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from 55 commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
704e720
Mark unstable_after as stable, rename function mentions
delbaoliveira Sep 12, 2024
1672a6e
Mark intrumentation as stable, remove instrumentationHook
delbaoliveira Sep 12, 2024
a0791b3
Remove instrumentation experimental notes
delbaoliveira Sep 12, 2024
b810600
Improve turbo docs, add missing options
delbaoliveira Sep 12, 2024
3b6457e
Document `connection()`
delbaoliveira Sep 13, 2024
69ce0b1
Tweak
delbaoliveira Sep 13, 2024
8118eb8
Add note to unstable_noStore about deprecation
delbaoliveira Sep 13, 2024
ef577a8
Update cookies API reference
delbaoliveira Sep 13, 2024
ba46bd8
Correction
delbaoliveira Sep 13, 2024
b1e21a7
Update headers API reference
delbaoliveira Sep 13, 2024
4122da1
Remove IP address example
delbaoliveira Sep 13, 2024
8de187b
Fix broken links
delbaoliveira Sep 13, 2024
220178e
More corrections
delbaoliveira Sep 13, 2024
b551afe
Add synchronous example for headers
delbaoliveira Sep 13, 2024
98feccb
Simplify headers example
delbaoliveira Sep 13, 2024
f49685a
Update draftMode API reference page
delbaoliveira Sep 13, 2024
8b3f8c3
Update page.js API reference, add basic examples
delbaoliveira Sep 13, 2024
84ea124
Update layout.js to follow template, add examples
delbaoliveira Sep 16, 2024
b85275e
Polish
delbaoliveira Sep 16, 2024
86369ea
Merge branch 'canary' into docs-rc-updates
delbaoliveira Sep 16, 2024
9f2ad43
Update async API examples
delbaoliveira Sep 16, 2024
170266f
Merge branch 'docs-rc-updates' of https://github.com/vercel/next.js i…
delbaoliveira Sep 16, 2024
8cf00d7
Update noStore example to use connection
delbaoliveira Sep 16, 2024
66fbc14
Merge branch 'canary' into docs-rc-updates
delbaoliveira Sep 16, 2024
9f62cf5
Update router handler params to async
delbaoliveira Sep 17, 2024
0bafb70
Promote `turbo` option to stable
delbaoliveira Sep 17, 2024
371f3df
Clarify `use` usage
delbaoliveira Sep 17, 2024
6eb58f9
Update upgrade guide (wip)
delbaoliveira Sep 17, 2024
18b98f2
Merge branch 'canary' into docs-rc-updates
delbaoliveira Sep 17, 2024
aebbf70
Add note about secure server actions
delbaoliveira Sep 18, 2024
9b86e0e
Update upgrade guide
delbaoliveira Sep 18, 2024
1a13e50
Update default.js reference
delbaoliveira Sep 18, 2024
5869c98
Merge branch 'canary' into docs-rc-updates
delbaoliveira Sep 18, 2024
5de2e75
Remove unecessary Dynamic Functions heading
delbaoliveira Sep 18, 2024
f97c573
Merge branch 'docs-rc-updates' of https://github.com/vercel/next.js i…
delbaoliveira Sep 18, 2024
29e5b24
Update dynamic APIs section
delbaoliveira Sep 18, 2024
e2d78f4
Fix broken links
delbaoliveira Sep 18, 2024
66398dc
Replace dynamic functions w/ dynamic APIs
delbaoliveira Sep 18, 2024
ad64dbc
Fix broken links
delbaoliveira Sep 18, 2024
4170ae9
Update docs/02-app/02-api-reference/05-next-config-js/turbo.mdx
delbaoliveira Sep 18, 2024
ee14a30
Update docs/02-app/02-api-reference/05-next-config-js/turbo.mdx
delbaoliveira Sep 18, 2024
5fd7864
Update after.mdx
delbaoliveira Sep 18, 2024
fa770b9
Merge branch 'docs-rc-updates' of https://github.com/vercel/next.js i…
delbaoliveira Sep 18, 2024
d31144f
Expand on nested `after` functions
delbaoliveira Sep 18, 2024
87f5f29
Add codemod heading to fix broken link
delbaoliveira Sep 18, 2024
ec35d65
Merge branch 'canary' into docs-rc-updates
delbaoliveira Sep 18, 2024
3c20c87
Merge branch 'canary' into docs-rc-updates
delbaoliveira Sep 26, 2024
6738b0c
Merge branch 'canary' into docs-rc-updates
delbaoliveira Sep 30, 2024
61465ea
Mark after as unstable
delbaoliveira Oct 1, 2024
d34d148
Apply suggestions from code review
delbaoliveira Oct 1, 2024
39422ba
Apply feedback
delbaoliveira Oct 1, 2024
b047ad6
Merge branch 'docs-rc-updates' of https://github.com/vercel/next.js i…
delbaoliveira Oct 1, 2024
eaac453
Merge branch 'canary' into docs-rc-updates
delbaoliveira Oct 1, 2024
a0f1e5f
Merge branch 'docs-rc-updates' of https://github.com/vercel/next.js i…
delbaoliveira Oct 8, 2024
f2af85f
Merge branch 'canary' into docs-rc-updates
delbaoliveira Oct 8, 2024
d26d76d
Apply suggestions from code review
delbaoliveira Oct 14, 2024
c2f14cd
Update docs/02-app/01-building-your-application/09-authentication/ind…
delbaoliveira Oct 14, 2024
7db3f1b
Update docs/02-app/01-building-your-application/07-configuring/03-env…
delbaoliveira Oct 14, 2024
76fb8c8
Update docs/02-app/01-building-your-application/09-authentication/ind…
delbaoliveira Oct 14, 2024
3877eb2
Update docs/02-app/01-building-your-application/10-deploying/index.mdx
delbaoliveira Oct 14, 2024
5c61517
Update docs/02-app/01-building-your-application/07-configuring/03-env…
delbaoliveira Oct 14, 2024
67d153c
Merge branch 'canary' into docs-rc-updates
delbaoliveira Oct 14, 2024
194d15c
Fix broken link
delbaoliveira Oct 14, 2024
ff4c7df
Fix borked await
delbaoliveira Oct 14, 2024
fed09f3
More fixes
delbaoliveira Oct 14, 2024
a7148d9
Update secure server actions section
delbaoliveira Oct 14, 2024
8f8de82
Clean up
delbaoliveira Oct 14, 2024
6f1472d
Add new prefetch prop to next/form
delbaoliveira Oct 14, 2024
fbd8f73
Add note about experimental_edge deprecation
delbaoliveira Oct 14, 2024
5f28cfb
Update canary tags
delbaoliveira Oct 14, 2024
5558489
Share next/form between app and pages docs
delbaoliveira Oct 14, 2024
db7885d
Fix broken link
delbaoliveira Oct 14, 2024
d34acba
Merge branch 'canary' into docs-rc-updates
delbaoliveira Oct 14, 2024
69cf992
Merge branch 'docs-rc-updates' of https://github.com/vercel/next.js i…
delbaoliveira Oct 14, 2024
4000ebb
Document staticGeneration* config options
delbaoliveira Oct 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export async function GET() {

### Special Route Handlers

Special Route Handlers like [`sitemap.ts`](/docs/app/api-reference/file-conventions/metadata/sitemap), [`opengraph-image.tsx`](/docs/app/api-reference/file-conventions/metadata/opengraph-image), and [`icon.tsx`](/docs/app/api-reference/file-conventions/metadata/app-icons), and other [metadata files](/docs/app/api-reference/file-conventions/metadata) remain static by default unless they use dynamic functions or dynamic config options.
Special Route Handlers like [`sitemap.ts`](/docs/app/api-reference/file-conventions/metadata/sitemap), [`opengraph-image.tsx`](/docs/app/api-reference/file-conventions/metadata/opengraph-image), and [`icon.tsx`](/docs/app/api-reference/file-conventions/metadata/app-icons), and other [metadata files](/docs/app/api-reference/file-conventions/metadata) remain static by default unless they use Dynamic APIs or dynamic config options.

### Route Resolution

Expand Down Expand Up @@ -139,11 +139,7 @@ export async function GET() {
}
```

### Dynamic Functions

Route Handlers can be used with dynamic functions from Next.js, like [`cookies`](/docs/app/api-reference/functions/cookies) and [`headers`](/docs/app/api-reference/functions/headers).

#### Cookies
### Cookies

You can read or set cookies with [`cookies`](/docs/app/api-reference/functions/cookies) from `next/headers`. This server function can be called directly in a Route Handler, or nested inside of another function.

Expand All @@ -153,7 +149,7 @@ Alternatively, you can return a new `Response` using the [`Set-Cookie`](https://
import { cookies } from 'next/headers'

export async function GET(request: Request) {
const cookieStore = cookies()
const cookieStore = await cookies()
const token = cookieStore.get('token')

return new Response('Hello, Next.js!', {
Expand All @@ -167,7 +163,7 @@ export async function GET(request: Request) {
import { cookies } from 'next/headers'

export async function GET(request) {
const cookieStore = cookies()
const cookieStore = await cookies()
const token = cookieStore.get('token')

return new Response('Hello, Next.js!', {
Expand All @@ -193,7 +189,7 @@ export async function GET(request) {
}
```

#### Headers
### Headers

You can read headers with [`headers`](/docs/app/api-reference/functions/headers) from `next/headers`. This server function can be called directly in a Route Handler, or nested inside of another function.

Expand All @@ -203,7 +199,7 @@ This `headers` instance is read-only. To set headers, you need to return a new `
import { headers } from 'next/headers'

export async function GET(request: Request) {
const headersList = headers()
const headersList = await headers()
const referer = headersList.get('referer')

return new Response('Hello, Next.js!', {
Expand All @@ -217,7 +213,7 @@ export async function GET(request: Request) {
import { headers } from 'next/headers'

export async function GET(request) {
const headersList = headers()
const headersList = await headers()
const referer = headersList.get('referer')

return new Response('Hello, Next.js!', {
Expand Down Expand Up @@ -270,23 +266,23 @@ Route Handlers can use [Dynamic Segments](/docs/app/building-your-application/ro
```ts filename="app/items/[slug]/route.ts" switcher
export async function GET(
request: Request,
{ params }: { params: { slug: string } }
{ params }: { params: Promise<{ slug: string }> }
) {
const slug = params.slug // 'a', 'b', or 'c'
const slug = (await params).slug // 'a', 'b', or 'c'
}
```

```js filename="app/items/[slug]/route.js" switcher
export async function GET(request, { params }) {
const slug = params.slug // 'a', 'b', or 'c'
const slug = (await params).slug // 'a', 'b', or 'c'
}
```

| Route | Example URL | `params` |
| --------------------------- | ----------- | --------------- |
| `app/items/[slug]/route.js` | `/items/a` | `{ slug: 'a' }` |
| `app/items/[slug]/route.js` | `/items/b` | `{ slug: 'b' }` |
| `app/items/[slug]/route.js` | `/items/c` | `{ slug: 'c' }` |
| Route | Example URL | `params` |
| --------------------------- | ----------- | ------------------------ |
| `app/items/[slug]/route.js` | `/items/a` | `Promise<{ slug: 'a' }>` |
| `app/items/[slug]/route.js` | `/items/b` | `Promise<{ slug: 'b' }>` |
| `app/items/[slug]/route.js` | `/items/c` | `Promise<{ slug: 'c' }>` |

### URL Query Parameters

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export default async function Page() {
}
```

If you are not using any [dynamic functions](/docs/app/building-your-application/rendering/server-components#dynamic-rendering) anywhere else in this route, it will be prerendered during `next build` to a static page. The data can then be updated using [Incremental Static Regeneration](/docs/app/building-your-application/data-fetching/incremental-static-regeneration).
If you are not using any [Dynamic APIs](/docs/app/building-your-application/rendering/server-components#dynamic-rendering) anywhere else in this route, it will be prerendered during `next build` to a static page. The data can then be updated using [Incremental Static Regeneration](/docs/app/building-your-application/data-fetching/incremental-static-regeneration).

If you do _not_ want to cache the response from `fetch`, you can do the following:

Expand Down Expand Up @@ -129,15 +129,15 @@ export default async function Page() {
}
```

If you are not using any [dynamic functions](/docs/app/building-your-application/rendering/server-components#dynamic-rendering) anywhere else in this route, it will be prerendered during `next build` to a static page. The data can then be updated using [Incremental Static Regeneration](/docs/app/building-your-application/data-fetching/incremental-static-regeneration).
If you are not using any [Dynamic APIs](/docs/app/building-your-application/rendering/server-components#dynamic-rendering) anywhere else in this route, it will be prerendered during `next build` to a static page. The data can then be updated using [Incremental Static Regeneration](/docs/app/building-your-application/data-fetching/incremental-static-regeneration).

To prevent the page from prerendering, you can add the following to your file:

```js
export const dynamic = 'force-dynamic'
```

However, you will commonly use functions like `cookies()`, `headers()`, or reading the incoming `searchParams` from the page props, which will automatically make the page render dynamically. In this case, you do _not_ need to explicitly use `force-dynamic`.
However, you will commonly use functions like `cookies`, `headers`, or reading the incoming `searchParams` from the page props, which will automatically make the page render dynamically. In this case, you do _not_ need to explicitly use `force-dynamic`.

### Fetching data on the client

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -839,13 +839,13 @@ import { cookies } from 'next/headers'

export async function exampleAction() {
// Get cookie
const value = cookies().get('name')?.value
(await cookies()).get('name')?.value

// Set cookie
cookies().set('name', 'Delba')
(await cookies()).set('name', 'Delba')

// Delete cookie
cookies().delete('name')
(await cookies()).delete('name')
}
```

Expand All @@ -856,23 +856,27 @@ import { cookies } from 'next/headers'

export async function exampleAction() {
// Get cookie
const value = cookies().get('name')?.value
(await cookies()).get('name')?.value

// Set cookie
cookies().set('name', 'Delba')
(await cookies()).set('name', 'Delba')

// Delete cookie
cookies().delete('name')
(await cookies()).delete('name')
}
```

See [additional examples](/docs/app/api-reference/functions/cookies#deleting-cookies) for deleting cookies from Server Actions.

## Security

When you add the `"use server"` directive to the top of a file, it marks all the exports in that file as API endpoints. By default, exported but unused functions are tree-shaken. That is, Next.js evaluates your codebase and removes references to unused Server Actions from the client-side JavaScript bundle.

In addition, the IDs that link the client-side reference to the server-side code is re-encrypted on each new deployment. This means Server Actions can only be invoked internally by the application.

### Authentication and authorization

You should treat Server Actions as you would public-facing API endpoints, and ensure that the user is authorized to perform the action. For example:
You should treat Server Actions as public-facing API endpoints, and ensure that the user is authorized to perform the action. For example:

```tsx filename="app/actions.ts"
'use server'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,12 @@ There are three subsets of server rendering: Static, Dynamic, and Streaming.

### Static Rendering (Default)

{/* Static Rendering Diagram */}

With Static Rendering, routes are rendered at **build time**, or in the background after [data revalidation](/docs/app/building-your-application/data-fetching/incremental-static-regeneration). The result is cached and can be pushed to a [Content Delivery Network (CDN)](https://developer.mozilla.org/docs/Glossary/CDN). This optimization allows you to share the result of the rendering work between users and server requests.

Static rendering is useful when a route has data that is not personalized to the user and can be known at build time, such as a static blog post or a product page.

### Dynamic Rendering

{/* Dynamic Rendering Diagram */}

With Dynamic Rendering, routes are rendered for each user at **request time**.

Dynamic rendering is useful when a route has data that is personalized to the user or has information that can only be known at request time, such as cookies or the URL's search params.
Expand All @@ -86,30 +82,30 @@ Dynamic rendering is useful when a route has data that is personalized to the us

#### Switching to Dynamic Rendering

During rendering, if a [dynamic function](#dynamic-functions) or uncached data request is discovered, Next.js will switch to dynamically rendering the whole route. This table summarizes how dynamic functions and data caching affect whether a route is statically or dynamically rendered:
During rendering, if a [Dynamic API](#dynamic-apis) or uncached data request is discovered, Next.js will switch to dynamically rendering the whole route. This table summarizes how Dynamic APIs and data caching affect whether a route is statically or dynamically rendered:

| Dynamic Functions | Data | Route |
| ----------------- | ---------- | -------------------- |
| No | Cached | Statically Rendered |
| Yes | Cached | Dynamically Rendered |
| No | Not Cached | Dynamically Rendered |
| Yes | Not Cached | Dynamically Rendered |
| Dynamic APIs | Data | Route |
| ------------ | ---------- | -------------------- |
| No | Cached | Statically Rendered |
| Yes | Cached | Dynamically Rendered |
| No | Not Cached | Dynamically Rendered |
| Yes | Not Cached | Dynamically Rendered |

In the table above, for a route to be fully static, all data must be cached. However, you can have a dynamically rendered route that uses both cached and uncached data fetches.

As a developer, you do not need to choose between static and dynamic rendering as Next.js will automatically choose the best rendering strategy for each route based on the features and APIs used. Instead, you choose when to [cache](/docs/app/building-your-application/data-fetching/fetching) or [revalidate specific data](/docs/app/building-your-application/data-fetching/incremental-static-regeneration), and you may choose to [stream](#streaming) parts of your UI.

#### Dynamic Functions

Dynamic functions rely on information that can only be known at request time such as a user's cookies, current requests headers, or the URL's search params. In Next.js, these dynamic APIs are:
### Dynamic APIs

- [`cookies()`](/docs/app/api-reference/functions/cookies)
- [`headers()`](/docs/app/api-reference/functions/headers)
- [`unstable_noStore()`](/docs/app/api-reference/functions/unstable_noStore)
- [`unstable_after()`](/docs/app/api-reference/functions/unstable_after):
- [`searchParams` prop](/docs/app/api-reference/file-conventions/page#searchparams-optional)
Dynamic APIs rely on information that can only be known at request time (and not ahead of time during prerendering). Using any of these APIs signals the developer's intention and will opt the whole route into dynamic rendering at the request time. These APIs include:

Using any of these functions will opt the whole route into dynamic rendering at request time.
- [`cookies`](https://www.notion.so/docs/app/api-reference/functions/cookies)
- [`headers`](https://www.notion.so/docs/app/api-reference/functions/headers)
- [`unstable_noStore`](https://www.notion.so/docs/app/api-reference/functions/unstable_noStore)
- [`unstable_after`](https://www.notion.so/docs/app/api-reference/functions/unstable_after)
- [`connection`](https://www.notion.so/docs/app/api-reference/functions/connection)
- [`draftMode`](https://www.notion.so/docs/app/api-reference/functions/draft-mode)
- [`searchParams` prop](https://www.notion.so/docs/app/api-reference/file-conventions/page#searchparams-optional)

### Streaming

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,24 +127,24 @@ module.exports = nextConfig

## Dynamic Components

When creating the prerender for your route during `next build`, Next.js requires that dynamic functions are wrapped with React Suspense. The `fallback` is then included in the prerender.
When creating the prerender for your route during `next build`, Next.js requires that Dynamic APIs are wrapped with React Suspense. The `fallback` is then included in the prerender.

For example, using functions like `cookies()` or `headers()`:
For example, using functions like `cookies` or `headers`:

```jsx filename="app/user.js" switcher
import { cookies } from 'next/headers'

export function User() {
const session = cookies().get('session')?.value
export async function User() {
const session = (await cookies()).get('session')?.value
return '...'
}
```

```tsx filename="app/user.tsx" switcher
import { cookies } from 'next/headers'

export function User() {
const session = cookies().get('session')?.value
export async function User() {
const session = (await cookies()).get('session')?.value
return '...'
}
```
Expand Down Expand Up @@ -224,17 +224,21 @@ export default function Page({ searchParams }) {
Inside of the table component, accessing the value from `searchParams` will make the component run dynamically:

```tsx filename="app/table.tsx" switcher
export function Table({ searchParams }: { searchParams: { sort: string } }) {
const sort = searchParams.sort === 'true'
export async function Table({
searchParams,
}: {
searchParams: Promise<{ sort: string }>
}) {
const sort = (await searchParams).sort === 'true'
return '...'
}
```

```jsx filename="app/table.js" switcher
export function Table({ searchParams }: {
searchParams: { sort: string }
export async function Table({ searchParams }: {
searchParams: Promise<{ sort: string }>
}) {
const sort = searchParams.sort === 'true';
const sort = (await searchParams).sort === 'true';
return '...'
}
```
Loading
Loading