From a64971c09a3bc464729b0950065729f5ca8e65c0 Mon Sep 17 00:00:00 2001 From: Delba de Oliveira Date: Thu, 9 May 2024 16:35:39 +0100 Subject: [PATCH 01/64] Add PPR page --- .../03-rendering/01-partial-prerendering.mdx | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 docs/02-app/01-building-your-application/03-rendering/01-partial-prerendering.mdx diff --git a/docs/02-app/01-building-your-application/03-rendering/01-partial-prerendering.mdx b/docs/02-app/01-building-your-application/03-rendering/01-partial-prerendering.mdx new file mode 100644 index 0000000000000..44d2e29e6486a --- /dev/null +++ b/docs/02-app/01-building-your-application/03-rendering/01-partial-prerendering.mdx @@ -0,0 +1,90 @@ +--- +title: Partial Prerendering (Experimental) +description: Learn how to combine the benefits of static and dynamic rendering with Partial Prerendering. +--- + +> Partial Prerendering is an **experimental** feature and subject to change. + +Partial Prerendering (PPR) is a rendering strategy that combines the benefits of static and dynamic rendering on the same route. + +Next.js currently defaults to static rendering unless you use [dynamic functions](/docs/app/building-your-application/rendering/server-components#dynamic-functions). These APIs opt a whole route into dynamic rendering. + +With PPR, you can wrap any dynamic UI in a [Suspense](https://react.dev/reference/react/Suspense) boundary. When a new request comes in, Next.js will immediately serve a static HTML shell from the cache, then render and [stream](/docs/app/building-your-application/rendering/server-components#streaming) the dynamic parts in the same HTTP request. + +Partially Prerendered Product Page showing static nav and product information, and dynamic cart and recommended products + +## Incremental Adoption (Version 15) + +In Next.js 15, you can incrementally adopt Partial Prerendering in [layouts](/docs/app/building-your-application/routing/layouts-and-templates) and [pages](/docs/app/building-your-application/routing/pages) by setting the [`ppr`](/docs/app/api-reference/next-config-js/partial-prerendering) `next.config.js` option to `incremental`, and adding the `experimental_ppr` [route config option](/docs/app/api-reference/file-conventions/route-segment-config) at the top of the file: + +```js filename="next.config.js" +const nextConfig = { + experimental: { + ppr: 'incremental', + }, +} + +module.exports = nextConfig +``` + +```tsx filename="app/page.tsx" switcher +import { Suspense } from "react" +import { StaticComponent, DynamicComponent, Fallback } from "@/app/ui" + +export const experimental_ppr = true + +export default function Page() { + return { + <> + + }> + + + + }; +} +``` + +```jsx filename="app/page.js" switcher +import { Suspense } from "react" +import { StaticComponent, DynamicComponent, Fallback } from "@/app/ui" + +export const experimental_ppr = true + +export default function Page() { + return { + <> + + }> + + + + }; +} +``` + +> **Good to know**: +> +> - Routes that don't have `experimental_ppr` will default to `false` and will not be prerendered using PPR. You need to explicitly opt-in to PPR for each route. +> - `experimental_ppr` will apply to all children of the route segment, including nested layouts and pages. You don't have to add it to every file, only the top segment of a route. +> - To disable PPR for children segments, you can set `experimental_ppr` to `false` in the child segment. + +## Enabling PPR (Version 14) + +For version 14, you can enable it by adding the [`ppr`](/docs/app/api-reference/next-config-js/partial-prerendering) option to your `next.config.js` file. This will apply to all routes in your application: + +```js filename="next.config.js" +const nextConfig = { + experimental: { + ppr: true, + }, +} + +module.exports = nextConfig +``` From a03ba9b4f910ac535e11e28ff318ec3e985157c3 Mon Sep 17 00:00:00 2001 From: Delba de Oliveira Date: Thu, 9 May 2024 16:37:36 +0100 Subject: [PATCH 02/64] Reorder rendering section --- ...01-server-components.mdx => 02-server-components.mdx} | 9 ++++++--- ...02-client-components.mdx => 03-client-components.mdx} | 0 ...position-patterns.mdx => 04-composition-patterns.mdx} | 0 ...dejs-runtimes.mdx => 05-edge-and-nodejs-runtimes.mdx} | 0 4 files changed, 6 insertions(+), 3 deletions(-) rename docs/02-app/01-building-your-application/03-rendering/{01-server-components.mdx => 02-server-components.mdx} (94%) rename docs/02-app/01-building-your-application/03-rendering/{02-client-components.mdx => 03-client-components.mdx} (100%) rename docs/02-app/01-building-your-application/03-rendering/{03-composition-patterns.mdx => 04-composition-patterns.mdx} (100%) rename docs/02-app/01-building-your-application/03-rendering/{04-edge-and-nodejs-runtimes.mdx => 05-edge-and-nodejs-runtimes.mdx} (100%) diff --git a/docs/02-app/01-building-your-application/03-rendering/01-server-components.mdx b/docs/02-app/01-building-your-application/03-rendering/02-server-components.mdx similarity index 94% rename from docs/02-app/01-building-your-application/03-rendering/01-server-components.mdx rename to docs/02-app/01-building-your-application/03-rendering/02-server-components.mdx index 369e8db646ab4..d509e06bebd43 100644 --- a/docs/02-app/01-building-your-application/03-rendering/01-server-components.mdx +++ b/docs/02-app/01-building-your-application/03-rendering/02-server-components.mdx @@ -101,10 +101,13 @@ As a developer, you do not need to choose between static and dynamic rendering a #### 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 functions are: +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: -- **[`cookies()`](/docs/app/api-reference/functions/cookies) and [`headers()`](/docs/app/api-reference/functions/headers)**: Using these in a Server Component will opt the whole route into dynamic rendering at request time. -- **[`searchParams`](/docs/app/api-reference/file-conventions/page#searchparams-optional)**: Using the `searchParams` prop on a [Page](/docs/app/api-reference/file-conventions/page) will opt the page into dynamic rendering at request time. +- [`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) Using any of these functions will opt the whole route into dynamic rendering at request time. diff --git a/docs/02-app/01-building-your-application/03-rendering/02-client-components.mdx b/docs/02-app/01-building-your-application/03-rendering/03-client-components.mdx similarity index 100% rename from docs/02-app/01-building-your-application/03-rendering/02-client-components.mdx rename to docs/02-app/01-building-your-application/03-rendering/03-client-components.mdx diff --git a/docs/02-app/01-building-your-application/03-rendering/03-composition-patterns.mdx b/docs/02-app/01-building-your-application/03-rendering/04-composition-patterns.mdx similarity index 100% rename from docs/02-app/01-building-your-application/03-rendering/03-composition-patterns.mdx rename to docs/02-app/01-building-your-application/03-rendering/04-composition-patterns.mdx diff --git a/docs/02-app/01-building-your-application/03-rendering/04-edge-and-nodejs-runtimes.mdx b/docs/02-app/01-building-your-application/03-rendering/05-edge-and-nodejs-runtimes.mdx similarity index 100% rename from docs/02-app/01-building-your-application/03-rendering/04-edge-and-nodejs-runtimes.mdx rename to docs/02-app/01-building-your-application/03-rendering/05-edge-and-nodejs-runtimes.mdx From f02dbf9567cb0e23db453cd25f78b3a580b32b74 Mon Sep 17 00:00:00 2001 From: Delba de Oliveira Date: Thu, 9 May 2024 16:38:22 +0100 Subject: [PATCH 03/64] Clean up, use consistent `experimental` titles --- .../06-optimizing/12-third-party-libraries.mdx | 14 ++++---------- .../04-functions/generate-metadata.mdx | 3 +-- .../04-functions/permanentRedirect.mdx | 2 +- .../02-api-reference/04-functions/redirect.mdx | 2 +- .../04-functions/revalidatePath.mdx | 2 +- .../04-functions/revalidateTag.mdx | 2 +- .../04-functions/unstable_cache.mdx | 2 +- .../04-functions/unstable_noStore.mdx | 2 +- .../05-next-config-js/staleTimes.mdx | 2 +- 9 files changed, 12 insertions(+), 19 deletions(-) diff --git a/docs/02-app/01-building-your-application/06-optimizing/12-third-party-libraries.mdx b/docs/02-app/01-building-your-application/06-optimizing/12-third-party-libraries.mdx index ab7f5b9ef589e..dbf25dd1a79b8 100644 --- a/docs/02-app/01-building-your-application/06-optimizing/12-third-party-libraries.mdx +++ b/docs/02-app/01-building-your-application/06-optimizing/12-third-party-libraries.mdx @@ -5,12 +5,9 @@ description: Optimize the performance of third-party libraries in your applicati {/* The content of this doc is shared between the app and pages router. You can use the `Content` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */} -**`@next/third-parties`** is a library that provides a collection of components and utilities that -improve the performance and developer experience of loading popular third-party libraries in your -Next.js application. +**`@next/third-parties`** is a library that provides a collection of components and utilities that improve the performance and developer experience of loading popular third-party libraries in your Next.js application. -All third-party integrations provided by `@next/third-parties` have been optimized for performance -and ease of use. +All third-party integrations provided by `@next/third-parties` have been optimized for performance and ease of use. ## Getting Started @@ -30,14 +27,11 @@ All supported third-party libraries from Google can be imported from `@next/thir ### Google Tag Manager -The `GoogleTagManager` component can be used to instantiate a [Google Tag -Manager](https://developers.google.com/tag-platform/tag-manager) container to your -page. By default, it fetches the original inline script after hydration occurs on the page. +The `GoogleTagManager` component can be used to instantiate a [Google Tag Manager](https://developers.google.com/tag-platform/tag-manager) container to your page. By default, it fetches the original inline script after hydration occurs on the page. -To load Google Tag Manager for all routes, include the component directly in your root layout and -pass in your GTM container ID: +To load Google Tag Manager for all routes, include the component directly in your root layout and pass in your GTM container ID: ```tsx filename="app/layout.tsx" switcher import { GoogleTagManager } from '@next/third-parties/google' diff --git a/docs/02-app/02-api-reference/04-functions/generate-metadata.mdx b/docs/02-app/02-api-reference/04-functions/generate-metadata.mdx index ea36795965ead..eb744fb92a8c1 100644 --- a/docs/02-app/02-api-reference/04-functions/generate-metadata.mdx +++ b/docs/02-app/02-api-reference/04-functions/generate-metadata.mdx @@ -1,6 +1,5 @@ --- -title: Metadata Object and generateMetadata Options -nav_title: generateMetadata +title: generateMetadata description: Learn how to add Metadata to your Next.js application for improved search engine optimization (SEO) and web shareability. related: title: Next Steps diff --git a/docs/02-app/02-api-reference/04-functions/permanentRedirect.mdx b/docs/02-app/02-api-reference/04-functions/permanentRedirect.mdx index b156326376f37..b1f1166525490 100644 --- a/docs/02-app/02-api-reference/04-functions/permanentRedirect.mdx +++ b/docs/02-app/02-api-reference/04-functions/permanentRedirect.mdx @@ -33,7 +33,7 @@ The `type` parameter has no effect when used in Server Components. ## Returns -`permanentRedirect` does not return any value. +`permanentRedirect` does not return a value. ## Example diff --git a/docs/02-app/02-api-reference/04-functions/redirect.mdx b/docs/02-app/02-api-reference/04-functions/redirect.mdx index 286ae00ccd994..330a7aed1b215 100644 --- a/docs/02-app/02-api-reference/04-functions/redirect.mdx +++ b/docs/02-app/02-api-reference/04-functions/redirect.mdx @@ -36,7 +36,7 @@ The `type` parameter has no effect when used in Server Components. ## Returns -`redirect` does not return any value. +`redirect` does not return a value. ## Example diff --git a/docs/02-app/02-api-reference/04-functions/revalidatePath.mdx b/docs/02-app/02-api-reference/04-functions/revalidatePath.mdx index 7d23b8d8e3d13..a5db8b3020c8b 100644 --- a/docs/02-app/02-api-reference/04-functions/revalidatePath.mdx +++ b/docs/02-app/02-api-reference/04-functions/revalidatePath.mdx @@ -23,7 +23,7 @@ revalidatePath(path: string, type?: 'page' | 'layout'): void; ## Returns -`revalidatePath` does not return any value. +`revalidatePath` does not return a value. ## Examples diff --git a/docs/02-app/02-api-reference/04-functions/revalidateTag.mdx b/docs/02-app/02-api-reference/04-functions/revalidateTag.mdx index 402392b83ebb2..d04015bd591a7 100644 --- a/docs/02-app/02-api-reference/04-functions/revalidateTag.mdx +++ b/docs/02-app/02-api-reference/04-functions/revalidateTag.mdx @@ -26,7 +26,7 @@ fetch(url, { next: { tags: [...] } }); ## Returns -`revalidateTag` does not return any value. +`revalidateTag` does not return a value. ## Examples diff --git a/docs/02-app/02-api-reference/04-functions/unstable_cache.mdx b/docs/02-app/02-api-reference/04-functions/unstable_cache.mdx index 98bc6a5834360..6db13aed46702 100644 --- a/docs/02-app/02-api-reference/04-functions/unstable_cache.mdx +++ b/docs/02-app/02-api-reference/04-functions/unstable_cache.mdx @@ -1,5 +1,5 @@ --- -title: unstable_cache +title: unstable_cache (Experimental) description: API Reference for the unstable_cache function. --- diff --git a/docs/02-app/02-api-reference/04-functions/unstable_noStore.mdx b/docs/02-app/02-api-reference/04-functions/unstable_noStore.mdx index 3c484a43088a0..33ce7439686ab 100644 --- a/docs/02-app/02-api-reference/04-functions/unstable_noStore.mdx +++ b/docs/02-app/02-api-reference/04-functions/unstable_noStore.mdx @@ -1,5 +1,5 @@ --- -title: unstable_noStore +title: unstable_noStore (Experimental) description: API Reference for the unstable_noStore function. --- diff --git a/docs/02-app/02-api-reference/05-next-config-js/staleTimes.mdx b/docs/02-app/02-api-reference/05-next-config-js/staleTimes.mdx index b9136c8cac126..9f1a68d594501 100644 --- a/docs/02-app/02-api-reference/05-next-config-js/staleTimes.mdx +++ b/docs/02-app/02-api-reference/05-next-config-js/staleTimes.mdx @@ -1,5 +1,5 @@ --- -title: StaleTimes (experimental) +title: staleTimes (Experimental) description: Learn how to override the invalidation time of the Client Router Cache. --- From 8f09765c124057510f59f5c31652b141baff8f1d Mon Sep 17 00:00:00 2001 From: Delba de Oliveira Date: Thu, 9 May 2024 16:38:48 +0100 Subject: [PATCH 04/64] Document experimental_ppr --- .../02-file-conventions/route-segment-config.mdx | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/02-app/02-api-reference/02-file-conventions/route-segment-config.mdx b/docs/02-app/02-api-reference/02-file-conventions/route-segment-config.mdx index 281d6394b7bc8..f29c881e5d575 100644 --- a/docs/02-app/02-api-reference/02-file-conventions/route-segment-config.mdx +++ b/docs/02-app/02-api-reference/02-file-conventions/route-segment-config.mdx @@ -7,6 +7,7 @@ The Route Segment options allows you to configure the behavior of a [Page](/docs | Option | Type | Default | | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | -------------------------- | +| [`experimental_ppr`](#dynamic) | `'true' \| 'false'` | | [`dynamic`](#dynamic) | `'auto' \| 'force-dynamic' \| 'error' \| 'force-static'` | `'auto'` | | [`dynamicParams`](#dynamicparams) | `boolean` | `true` | | [`revalidate`](#revalidate) | `false \| 0 \| number` | `false` | @@ -17,6 +18,20 @@ The Route Segment options allows you to configure the behavior of a [Page](/docs ## Options +### `experimental_ppr` + +Enable [Partial Prerendering (PPR)](/docs/app/building-your-application/rendering/partial-prerendering) for a layout or page. + +```tsx filename="layout.tsx | page.tsx " switcher +export const experimental_ppr = 'true' +// 'true' | 'false' +``` + +```jsx filename="layout.js | page.js " switcher +export const experimental_ppr = 'true' +// 'true' | 'false' +``` + ### `dynamic` Change the dynamic behavior of a layout or page to fully static or fully dynamic. From f8d7b3b6e1f63bc1ddead20cace27f50e5c1cacb Mon Sep 17 00:00:00 2001 From: Delba de Oliveira Date: Thu, 9 May 2024 16:39:43 +0100 Subject: [PATCH 05/64] Update ppr next.config.js page - Rename partial-prerendering to ppr for consistent option names - Will add redirect in next-site --- .../partial-prerendering.mdx | 34 ---------------- .../05-next-config-js/ppr.mdx | 39 +++++++++++++++++++ 2 files changed, 39 insertions(+), 34 deletions(-) delete mode 100644 docs/02-app/02-api-reference/05-next-config-js/partial-prerendering.mdx create mode 100644 docs/02-app/02-api-reference/05-next-config-js/ppr.mdx diff --git a/docs/02-app/02-api-reference/05-next-config-js/partial-prerendering.mdx b/docs/02-app/02-api-reference/05-next-config-js/partial-prerendering.mdx deleted file mode 100644 index 6bd339a78dd59..0000000000000 --- a/docs/02-app/02-api-reference/05-next-config-js/partial-prerendering.mdx +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Partial Prerendering (experimental) -description: Learn how to enable Partial Prerendering (experimental) in Next.js 14. ---- - -> **Warning**: Partial Prerendering is an experimental feature and is currently **not suitable for production environments**. - -Partial Prerendering is an experimental feature that allows static portions of a route to be prerendered and served from the cache with dynamic holes streamed in, all in a single HTTP request. - -Partial Prerendering is available in `next@canary`: - -```bash filename="Terminal" -npm install next@canary -``` - -You can enable Partial Prerendering by setting the experimental `ppr` flag: - -```js filename="next.config.js" -/** @type {import('next').NextConfig} */ -const nextConfig = { - experimental: { - ppr: true, - }, -} - -module.exports = nextConfig -``` - -> **Good to know:** -> -> - Partial Prerendering does not yet apply to client-side navigations. We are actively working on this. -> - Partial Prerendering is designed for the [Node.js runtime](/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes) only. Using the subset of the Node.js runtime is not needed when you can instantly serve the static shell. - -Learn more about Partial Prerendering in the [Next.js Learn course](/learn/dashboard-app/partial-prerendering). diff --git a/docs/02-app/02-api-reference/05-next-config-js/ppr.mdx b/docs/02-app/02-api-reference/05-next-config-js/ppr.mdx new file mode 100644 index 0000000000000..6425b79054c54 --- /dev/null +++ b/docs/02-app/02-api-reference/05-next-config-js/ppr.mdx @@ -0,0 +1,39 @@ +--- +title: Partial Prerendering (Experimental) +nav_title: ppr (Experimental) +description: Learn how to enable Partial Prerendering (experimental) in Next.js 14. +--- + +> **Warning**: Partial Prerendering is an experimental feature and is currently **not suitable for production environments**. + +Partial Prerendering is an experimental feature that allows static portions of a route to be prerendered and served from the cache with dynamic holes streamed in, all in a single HTTP request. + +Incremental support is available in Next.js 15, allowing you to opt-in to Partial Prerendering for specific routes and layouts. + +To enable Partial Prerendering, set the experimental `ppr` flag `incremental`: + +```js filename="next.config.js" +/** @type {import('next').NextConfig} */ +const nextConfig = { + experimental: { + ppr: 'incremental', + }, +} + +module.exports = nextConfig +``` + +## Options + +- `incremental`: Allowing you to incrementally opt-in layouts and pages, should be used with the [`experimental_ppr`](/docs/app/api-reference/file-conventions/route-segment-config#experimental_ppr) route config option. +- `true`: Enables Partial Prerendering for all routes in your application. + +We recommend using `incremental` first. Once all the routes in your application have PPR enabled, it’ll be considered safe for you to set the `ppr` value to `true`, and enable it for the entire app and all future routes. + +> **Good to know:** +> +> - When using `incremental`, routes that don't have `experimental_ppr` will default to `false` and will not be prerendered using Partial Prerendering. You need to explicitly opt-in to Partial Prerendering for each route. +> - Partial Prerendering does not yet apply to client-side navigations. We are actively working on this. +> - Partial Prerendering is designed for the [Node.js runtime](/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes) only. Using the subset of the Node.js runtime is not needed when you can instantly serve the static shell. + +Learn more about Partial Prerendering in the [Next.js Learn course](/learn/dashboard-app/partial-prerendering). From 79b8b2b9eac06df555fc3ce5154c4abc505fe927 Mon Sep 17 00:00:00 2001 From: Delba de Oliveira Date: Thu, 9 May 2024 16:39:57 +0100 Subject: [PATCH 06/64] Document unstable_after --- .../04-functions/unstable_after.mdx | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 docs/02-app/02-api-reference/04-functions/unstable_after.mdx diff --git a/docs/02-app/02-api-reference/04-functions/unstable_after.mdx b/docs/02-app/02-api-reference/04-functions/unstable_after.mdx new file mode 100644 index 0000000000000..5d6905578292b --- /dev/null +++ b/docs/02-app/02-api-reference/04-functions/unstable_after.mdx @@ -0,0 +1,62 @@ +--- +title: unstable_after (Experimental) +description: API Reference for the unstable_after function. +--- + +> This API is **experimental** and subject to change. + +`unstable_after()` allows you to schedule work to be executed after a response is finished. This is useful for background tasks and other side effects that should not block the response, such as logging and analytics. + +It can be used in [Server Components](/docs/app/building-your-application/rendering/server-components) (including [`generateMetadata`](https://nextjs.org/docs/app/api-reference/functions/generate-metadata)), [Server Actions](/docs/app/building-your-application/data-fetching/server-actions-and-mutations), [Route Handlers](/docs/app/building-your-application/routing/route-handlers), and [Middleware](/docs/app/building-your-application/routing/middleware). + +To use `unstable_after()`, you need to enable it using `experimental.after` config in the `next.config.js` file: + +```js filename="next.config.js" +const nextConfig = { + experimental: { + after: true, + }, +} +module.exports = nextConfig +``` + +```tsx filename="app/layout.tsx switcher +import { unstable_after as after } from 'next/after' +import { log } from '@/app/utils' + +export default function Layout({ children }: { children: React.ReactNode }) { + after(() => { + // Execute after the layout is rendered and sent to the user + log() + }) + return <>{children} +} +``` + +```jsx filename="app/layout.js switcher +import { unstable_after as after } from 'next/after' +import { log } from '@/app/utils' + +export default function Layout({ children }) { + after(() => { + // Execute after the layout is rendered and sent to the user + log() + }) + return <>{children} +} +``` + +> **Good to know**: +> +> - `unstable_after()` will be executed even if the response didn't complete successfully. Including when an error is thrown or when `notFound()` or `redirect()` is called. +> - `unstable_after()` is a [dynamic function](/docs/app/building-your-application/rendering/server-components#dynamic-functions) that will opt a route into dynamic rendering. This behavior can be overridden with the [`export dynamic = "force-static"`](/docs/app/api-reference/file-conventions/route-segment-config#dynamic) segment config. +> - You can use React `cache` to deduplicate functions called inside `unstable_after()`. +> - [`cookies()`](/docs/app/api-reference/functions/cookies) cannot be set inside `unstable_after()` since the response has already been sent. + +### Parameters + +- A function that will be executed after the response is finished. + +### Returns + +- `unstable_after()` does not return a value. From 513c61085b3d4500575b9b855bbf9229b32f1f30 Mon Sep 17 00:00:00 2001 From: Delba de Oliveira Date: Fri, 10 May 2024 10:28:43 +0100 Subject: [PATCH 07/64] Add package bundling page --- .../06-optimizing/06-bundle-analyzer.mdx | 48 ------- .../06-optimizing/06-package-bundling.mdx | 135 ++++++++++++++++++ .../05-next-config-js/transpilePackages.mdx | 2 +- ...e-analyzer.mdx => 06-package-bundling.mdx} | 7 +- 4 files changed, 140 insertions(+), 52 deletions(-) delete mode 100644 docs/02-app/01-building-your-application/06-optimizing/06-bundle-analyzer.mdx create mode 100644 docs/02-app/01-building-your-application/06-optimizing/06-package-bundling.mdx rename docs/03-pages/01-building-your-application/05-optimizing/{06-bundle-analyzer.mdx => 06-package-bundling.mdx} (72%) diff --git a/docs/02-app/01-building-your-application/06-optimizing/06-bundle-analyzer.mdx b/docs/02-app/01-building-your-application/06-optimizing/06-bundle-analyzer.mdx deleted file mode 100644 index cb46ac5470fbe..0000000000000 --- a/docs/02-app/01-building-your-application/06-optimizing/06-bundle-analyzer.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Bundle Analyzer -description: Analyze the size of your JavaScript bundles using the @next/bundle-analyzer plugin. -related: - description: Learn more about optimizing your application for production. - links: - - app/building-your-application/deploying/production-checklist ---- - -[`@next/bundle-analyzer`](https://www.npmjs.com/package/@next/bundle-analyzer) is a plugin for Next.js that helps you manage the size of your JavaScript modules. It generates a visual report of the size of each module and their dependencies. You can use the information to remove large dependencies, split your code, or only load some parts when needed, reducing the amount of data transferred to the client. - -## Installation - -Install the plugin by running the following command: - -```bash -npm i @next/bundle-analyzer -# or -yarn add @next/bundle-analyzer -# or -pnpm add @next/bundle-analyzer -``` - -Then, add the bundle analyzer's settings to your `next.config.js`. - -```js filename="next.config.js" -/** @type {import('next').NextConfig} */ -const nextConfig = {} - -const withBundleAnalyzer = require('@next/bundle-analyzer')() - -module.exports = - process.env.ANALYZE === 'true' ? withBundleAnalyzer(nextConfig) : nextConfig -``` - -## Analyzing your bundles - -Run the following command to analyze your bundles: - -```bash -ANALYZE=true npm run build -# or -ANALYZE=true yarn build -# or -ANALYZE=true pnpm build -``` - -The report will open three new tabs in your browser, which you can inspect. Doing this regularly while you develop and before deploying your site can help you identify large bundles earlier, and architect your application to be more performant. diff --git a/docs/02-app/01-building-your-application/06-optimizing/06-package-bundling.mdx b/docs/02-app/01-building-your-application/06-optimizing/06-package-bundling.mdx new file mode 100644 index 0000000000000..1b44d9105a109 --- /dev/null +++ b/docs/02-app/01-building-your-application/06-optimizing/06-package-bundling.mdx @@ -0,0 +1,135 @@ +--- +title: Optimizing Package Bundling +nav_title: Package Bundling +description: Learn how to optimize your application's server and client bundles. +related: + description: Learn more about optimizing your application for production. + links: + - app/building-your-application/deploying/production-checklist +--- + +Bundling external packages can significantly improve the performance of your application. By default, packages imported inside Server Components and Route Handlers are automatically bundled by Next.js. This page will guide you through how to analyze and further optimize package bundling. By default, packages imported into your application are not bundled. This can impact performance or might not work if external packages are not pre-bundled, for example, if imported from a monorepo or `node_modules`. This page will guide you through how to analyze and configure package bundling. + +## Analyzing JavaScript bundles + +[`@next/bundle-analyzer`](https://www.npmjs.com/package/@next/bundle-analyzer) is a plugin for Next.js that helps you manage the size of your application bundles. It generates a visual report of the size of each package and their dependencies. You can use the information to remove large dependencies, split, or [lazy-load](/docs/app/building-your-application/optimizing/lazy-loading) your code. + +### Installation + +Install the plugin by running the following command: + +```bash +npm i @next/bundle-analyzer +# or +yarn add @next/bundle-analyzer +# or +pnpm add @next/bundle-analyzer +``` + +Then, add the bundle analyzer's settings to your `next.config.js`. + +```js filename="next.config.js" +/** @type {import('next').NextConfig} */ +const nextConfig = {} + +const withBundleAnalyzer = require('@next/bundle-analyzer')() + +module.exports = + process.env.ANALYZE === 'true' ? withBundleAnalyzer(nextConfig) : nextConfig +``` + +### Generating a report + +Run the following command to analyze your bundles: + +```bash +ANALYZE=true npm run build +# or +ANALYZE=true yarn build +# or +ANALYZE=true pnpm build +``` + +The report will open three new tabs in your browser, which you can inspect. Periodically evaluating your application's bundles can help you maintain application performance over time. + +## Optimizing package imports + +Some packages, such as icon libraries, can export hundreds of modules, which can cause performance issues in development and production. + +You can optimize how these packages are imported by adding the [`optimizePackageImports`](/docs/app/api-reference/next-config-js/optimizePackageImports) option to your `next.config.js`. This option will only load the modules you _actually_ use, while still giving you the convenience of writing import statements with many named exports. + +```js filename="next.config.js" +/** @type {import('next').NextConfig} */ +const nextConfig = { + experimental: { + optimizePackageImports: ['icon-library'], + }, +} + +module.exports = nextConfig +``` + +Next.js also optimizes some libraries automatically. See the [full list](https://nextjs.org/docs/app/api-reference/next-config-js/optimizePackageImports) + + + +## Bundling specific packages + +To bundle specific packages, you can use the [`transpilePackages`](/docs/app/api-reference/next-config-js/transpilePackages) option in your `next.config.js`. This option is useful for bundling external packages that are not pre-bundled, for example, in a monorepo or imported from `node_modules`. + +```js filename="next.config.js" +/** @type {import('next').NextConfig} */ +const nextConfig = { + transpilePackages: ['package-name'], +} + +module.exports = nextConfig +``` + +## Bundling all packages + +To automatically bundle all packages (default behavior in the App Router), you can use the [`bundlePagesRouterDependencies`](/docs/app/api-reference/next-config-js/bundlePagesRouterDependencies) option in your `next.config.js`. + +```js filename="next.config.js" +/** @type {import('next').NextConfig} */ +const nextConfig = { + bundlePagesRouterDependencies: true, +} + +module.exports = nextConfig +``` + +## Opting specific packages out of bundling + +If you have the [`bundlePagesRouterDependencies`](/docs/pages/api-reference/next-config-js/bundlePagesRouterDependencies) option enabled, you can opt specific packages out of automatic bundling using the [`serverExternalPackages`](/docs/pages/api-reference/next-config-js/serverExternalPackages) option in your `next.config.js`: + +```js filename="next.config.js" +/** @type {import('next').NextConfig} */ +const nextConfig = { + // Automatically bundle external packages in the Pages Router: + bundlePagesRouterDependencies: true, + // Opt specific packages out of bundling for both App and Pages Router: + serverExternalPackages: ['package-name'], +} + +module.exports = nextConfig +``` + + + + + +## Opting specific packages out of bundling + +Since packages imported inside Server Components and Route Handlers are automatically bundled by Next.js, you can opt specific packages out of bundling using the [`serverExternalPackages`](/docs/app/api-reference/next-config-js/serverExternalPackages) option in your `next.config.js`. + +```js filename="next.config.js" +/** @type {import('next').NextConfig} */ +const nextConfig = { + serverExternalPackages: ['package-name'], +} + +module.exports = nextConfig +``` + + diff --git a/docs/02-app/02-api-reference/05-next-config-js/transpilePackages.mdx b/docs/02-app/02-api-reference/05-next-config-js/transpilePackages.mdx index 185d834627400..a6aecbb18bbe5 100644 --- a/docs/02-app/02-api-reference/05-next-config-js/transpilePackages.mdx +++ b/docs/02-app/02-api-reference/05-next-config-js/transpilePackages.mdx @@ -10,7 +10,7 @@ Next.js can automatically transpile and bundle dependencies from local packages ```js filename="next.config.js" /** @type {import('next').NextConfig} */ const nextConfig = { - transpilePackages: ['@acme/ui', 'lodash-es'], + transpilePackages: ['package-name'], } module.exports = nextConfig diff --git a/docs/03-pages/01-building-your-application/05-optimizing/06-bundle-analyzer.mdx b/docs/03-pages/01-building-your-application/05-optimizing/06-package-bundling.mdx similarity index 72% rename from docs/03-pages/01-building-your-application/05-optimizing/06-bundle-analyzer.mdx rename to docs/03-pages/01-building-your-application/05-optimizing/06-package-bundling.mdx index 8136294167014..56f931965b79c 100644 --- a/docs/03-pages/01-building-your-application/05-optimizing/06-bundle-analyzer.mdx +++ b/docs/03-pages/01-building-your-application/05-optimizing/06-package-bundling.mdx @@ -1,7 +1,8 @@ --- -title: Bundle Analyzer -description: Analyze the size of your JavaScript bundles using the @next/bundle-analyzer plugin. -source: app/building-your-application/optimizing/bundle-analyzer +title: Optimizing Bundling +nav_title: Bundling +description: Learn how to optimize your application's server and client bundles. +source: app/building-your-application/optimizing/bundles related: description: Learn more about optimizing your application for production. links: From 66db9a24fcfefe1ad097ea88ab2e6d529ad38ceb Mon Sep 17 00:00:00 2001 From: Delba de Oliveira Date: Fri, 10 May 2024 10:34:01 +0100 Subject: [PATCH 08/64] Clean up, fix broken links --- .../03-rendering/01-partial-prerendering.mdx | 4 ++-- .../06-optimizing/06-package-bundling.mdx | 2 +- .../06-optimizing/13-memory-usage.mdx | 2 +- .../10-deploying/01-production-checklist.mdx | 2 +- docs/02-app/02-api-reference/05-next-config-js/ppr.mdx | 2 +- .../05-optimizing/06-package-bundling.mdx | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/02-app/01-building-your-application/03-rendering/01-partial-prerendering.mdx b/docs/02-app/01-building-your-application/03-rendering/01-partial-prerendering.mdx index 44d2e29e6486a..67bf0bea86734 100644 --- a/docs/02-app/01-building-your-application/03-rendering/01-partial-prerendering.mdx +++ b/docs/02-app/01-building-your-application/03-rendering/01-partial-prerendering.mdx @@ -21,7 +21,7 @@ With PPR, you can wrap any dynamic UI in a [Suspense](https://react.dev/referenc ## Incremental Adoption (Version 15) -In Next.js 15, you can incrementally adopt Partial Prerendering in [layouts](/docs/app/building-your-application/routing/layouts-and-templates) and [pages](/docs/app/building-your-application/routing/pages) by setting the [`ppr`](/docs/app/api-reference/next-config-js/partial-prerendering) `next.config.js` option to `incremental`, and adding the `experimental_ppr` [route config option](/docs/app/api-reference/file-conventions/route-segment-config) at the top of the file: +In Next.js 15, you can incrementally adopt Partial Prerendering in [layouts](/docs/app/building-your-application/routing/layouts-and-templates) and [pages](/docs/app/building-your-application/routing/pages) by setting the [`ppr`](/docs/app/api-reference/next-config-js/ppr) `next.config.js` option to `incremental`, and adding the `experimental_ppr` [route config option](/docs/app/api-reference/file-conventions/route-segment-config) at the top of the file: ```js filename="next.config.js" const nextConfig = { @@ -77,7 +77,7 @@ export default function Page() { ## Enabling PPR (Version 14) -For version 14, you can enable it by adding the [`ppr`](/docs/app/api-reference/next-config-js/partial-prerendering) option to your `next.config.js` file. This will apply to all routes in your application: +For version 14, you can enable it by adding the [`ppr`](/docs/app/api-reference/next-config-js/ppr) option to your `next.config.js` file. This will apply to all routes in your application: ```js filename="next.config.js" const nextConfig = { diff --git a/docs/02-app/01-building-your-application/06-optimizing/06-package-bundling.mdx b/docs/02-app/01-building-your-application/06-optimizing/06-package-bundling.mdx index 1b44d9105a109..5ad69f15306d3 100644 --- a/docs/02-app/01-building-your-application/06-optimizing/06-package-bundling.mdx +++ b/docs/02-app/01-building-your-application/06-optimizing/06-package-bundling.mdx @@ -88,7 +88,7 @@ module.exports = nextConfig ## Bundling all packages -To automatically bundle all packages (default behavior in the App Router), you can use the [`bundlePagesRouterDependencies`](/docs/app/api-reference/next-config-js/bundlePagesRouterDependencies) option in your `next.config.js`. +To automatically bundle all packages (default behavior in the App Router), you can use the [`bundlePagesRouterDependencies`](/docs/pages/api-reference/next-config-js/bundlePagesRouterDependencies) option in your `next.config.js`. ```js filename="next.config.js" /** @type {import('next').NextConfig} */ diff --git a/docs/02-app/01-building-your-application/06-optimizing/13-memory-usage.mdx b/docs/02-app/01-building-your-application/06-optimizing/13-memory-usage.mdx index 263d99531f6d5..737d9975b1b69 100644 --- a/docs/02-app/01-building-your-application/06-optimizing/13-memory-usage.mdx +++ b/docs/02-app/01-building-your-application/06-optimizing/13-memory-usage.mdx @@ -11,7 +11,7 @@ Let's explore some strategies and techniques to optimize memory and address comm Applications with a large amount of dependencies will use more memory. -The [Bundle Analyzer](/docs/app/building-your-application/optimizing/bundle-analyzer) can help you investigate large dependencies in your application that may be able to be removed to improve performance and memory usage. +The [Bundle Analyzer](/docs/app/building-your-application/optimizing/bundling-ackages#analyzing-javascript-bundles) can help you investigate large dependencies in your application that may be able to be removed to improve performance and memory usage. ## Run `next build` with `--experimental-debug-memory-usage` diff --git a/docs/02-app/01-building-your-application/10-deploying/01-production-checklist.mdx b/docs/02-app/01-building-your-application/10-deploying/01-production-checklist.mdx index 568c3e6e25d87..52d21a899cde5 100644 --- a/docs/02-app/01-building-your-application/10-deploying/01-production-checklist.mdx +++ b/docs/02-app/01-building-your-application/10-deploying/01-production-checklist.mdx @@ -139,7 +139,7 @@ Before going to production, you can run `next build` to build your application l ### Analyzing bundles -Use the [`@next/bundle-analyzer` plugin](/docs/app/building-your-application/optimizing/bundle-analyzer) to analyze the size of your JavaScript bundles and identify large modules and dependencies that might be impacting your application's performance. +Use the [`@next/bundle-analyzer` plugin](/docs/app/building-your-application/optimizing/bundling-ackages#analyzing-javascript-bundles) to analyze the size of your JavaScript bundles and identify large modules and dependencies that might be impacting your application's performance. Additionally, the following tools can you understand the impact of adding new dependencies to your application: diff --git a/docs/02-app/02-api-reference/05-next-config-js/ppr.mdx b/docs/02-app/02-api-reference/05-next-config-js/ppr.mdx index 6425b79054c54..313a9f6660cb1 100644 --- a/docs/02-app/02-api-reference/05-next-config-js/ppr.mdx +++ b/docs/02-app/02-api-reference/05-next-config-js/ppr.mdx @@ -4,7 +4,7 @@ nav_title: ppr (Experimental) description: Learn how to enable Partial Prerendering (experimental) in Next.js 14. --- -> **Warning**: Partial Prerendering is an experimental feature and is currently **not suitable for production environments**. +> Partial Prerendering is an **experimental** feature and subject to change. Partial Prerendering is an experimental feature that allows static portions of a route to be prerendered and served from the cache with dynamic holes streamed in, all in a single HTTP request. diff --git a/docs/03-pages/01-building-your-application/05-optimizing/06-package-bundling.mdx b/docs/03-pages/01-building-your-application/05-optimizing/06-package-bundling.mdx index 56f931965b79c..8fc8d76e18045 100644 --- a/docs/03-pages/01-building-your-application/05-optimizing/06-package-bundling.mdx +++ b/docs/03-pages/01-building-your-application/05-optimizing/06-package-bundling.mdx @@ -2,7 +2,7 @@ title: Optimizing Bundling nav_title: Bundling description: Learn how to optimize your application's server and client bundles. -source: app/building-your-application/optimizing/bundles +source: /docs/app/building-your-application/optimizing/bundling-ackages related: description: Learn more about optimizing your application for production. links: From c8da54f95cdd26ff6afa95e6908b16dafe2f7515 Mon Sep 17 00:00:00 2001 From: Delba de Oliveira Date: Fri, 10 May 2024 10:35:51 +0100 Subject: [PATCH 09/64] Broken links --- .../06-optimizing/13-memory-usage.mdx | 2 +- .../10-deploying/01-production-checklist.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/02-app/01-building-your-application/06-optimizing/13-memory-usage.mdx b/docs/02-app/01-building-your-application/06-optimizing/13-memory-usage.mdx index 737d9975b1b69..cda91e7e851b0 100644 --- a/docs/02-app/01-building-your-application/06-optimizing/13-memory-usage.mdx +++ b/docs/02-app/01-building-your-application/06-optimizing/13-memory-usage.mdx @@ -11,7 +11,7 @@ Let's explore some strategies and techniques to optimize memory and address comm Applications with a large amount of dependencies will use more memory. -The [Bundle Analyzer](/docs/app/building-your-application/optimizing/bundling-ackages#analyzing-javascript-bundles) can help you investigate large dependencies in your application that may be able to be removed to improve performance and memory usage. +The [Bundle Analyzer](/docs/app/building-your-application/optimizing/bundling-ackages) can help you investigate large dependencies in your application that may be able to be removed to improve performance and memory usage. ## Run `next build` with `--experimental-debug-memory-usage` diff --git a/docs/02-app/01-building-your-application/10-deploying/01-production-checklist.mdx b/docs/02-app/01-building-your-application/10-deploying/01-production-checklist.mdx index 52d21a899cde5..7dd8c4177a7eb 100644 --- a/docs/02-app/01-building-your-application/10-deploying/01-production-checklist.mdx +++ b/docs/02-app/01-building-your-application/10-deploying/01-production-checklist.mdx @@ -139,7 +139,7 @@ Before going to production, you can run `next build` to build your application l ### Analyzing bundles -Use the [`@next/bundle-analyzer` plugin](/docs/app/building-your-application/optimizing/bundling-ackages#analyzing-javascript-bundles) to analyze the size of your JavaScript bundles and identify large modules and dependencies that might be impacting your application's performance. +Use the [`@next/bundle-analyzer` plugin](/docs/app/building-your-application/optimizing/bundling-ackages) to analyze the size of your JavaScript bundles and identify large modules and dependencies that might be impacting your application's performance. Additionally, the following tools can you understand the impact of adding new dependencies to your application: From 20a8384d25a3405df770f0471f59939f4b684cc2 Mon Sep 17 00:00:00 2001 From: Delba de Oliveira Date: Fri, 10 May 2024 10:49:29 +0100 Subject: [PATCH 10/64] Missing p --- .../06-optimizing/13-memory-usage.mdx | 2 +- .../10-deploying/01-production-checklist.mdx | 2 +- .../05-optimizing/06-package-bundling.mdx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/02-app/01-building-your-application/06-optimizing/13-memory-usage.mdx b/docs/02-app/01-building-your-application/06-optimizing/13-memory-usage.mdx index cda91e7e851b0..bdc0e48e9a0e3 100644 --- a/docs/02-app/01-building-your-application/06-optimizing/13-memory-usage.mdx +++ b/docs/02-app/01-building-your-application/06-optimizing/13-memory-usage.mdx @@ -11,7 +11,7 @@ Let's explore some strategies and techniques to optimize memory and address comm Applications with a large amount of dependencies will use more memory. -The [Bundle Analyzer](/docs/app/building-your-application/optimizing/bundling-ackages) can help you investigate large dependencies in your application that may be able to be removed to improve performance and memory usage. +The [Bundle Analyzer](/docs/app/building-your-application/optimizing/bundling-packages#analyzing-javascript-bundles) can help you investigate large dependencies in your application that may be able to be removed to improve performance and memory usage. ## Run `next build` with `--experimental-debug-memory-usage` diff --git a/docs/02-app/01-building-your-application/10-deploying/01-production-checklist.mdx b/docs/02-app/01-building-your-application/10-deploying/01-production-checklist.mdx index 7dd8c4177a7eb..47ced77b42afb 100644 --- a/docs/02-app/01-building-your-application/10-deploying/01-production-checklist.mdx +++ b/docs/02-app/01-building-your-application/10-deploying/01-production-checklist.mdx @@ -139,7 +139,7 @@ Before going to production, you can run `next build` to build your application l ### Analyzing bundles -Use the [`@next/bundle-analyzer` plugin](/docs/app/building-your-application/optimizing/bundling-ackages) to analyze the size of your JavaScript bundles and identify large modules and dependencies that might be impacting your application's performance. +Use the [`@next/bundle-analyzer` plugin](/docs/app/building-your-application/optimizing/bundling-packages#analyzing-javascript-bundles) to analyze the size of your JavaScript bundles and identify large modules and dependencies that might be impacting your application's performance. Additionally, the following tools can you understand the impact of adding new dependencies to your application: diff --git a/docs/03-pages/01-building-your-application/05-optimizing/06-package-bundling.mdx b/docs/03-pages/01-building-your-application/05-optimizing/06-package-bundling.mdx index 8fc8d76e18045..0c3dd129f48f9 100644 --- a/docs/03-pages/01-building-your-application/05-optimizing/06-package-bundling.mdx +++ b/docs/03-pages/01-building-your-application/05-optimizing/06-package-bundling.mdx @@ -2,7 +2,7 @@ title: Optimizing Bundling nav_title: Bundling description: Learn how to optimize your application's server and client bundles. -source: /docs/app/building-your-application/optimizing/bundling-ackages +source: /docs/app/building-your-application/optimizing/bundling-packages related: description: Learn more about optimizing your application for production. links: From 1748791607935f953e3fddd00ff19cc5ea462847 Mon Sep 17 00:00:00 2001 From: Delba de Oliveira Date: Fri, 10 May 2024 10:52:37 +0100 Subject: [PATCH 11/64] Fix links - Time for a break, I think --- .../06-optimizing/13-memory-usage.mdx | 2 +- .../10-deploying/01-production-checklist.mdx | 2 +- .../05-optimizing/06-package-bundling.mdx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/02-app/01-building-your-application/06-optimizing/13-memory-usage.mdx b/docs/02-app/01-building-your-application/06-optimizing/13-memory-usage.mdx index bdc0e48e9a0e3..2be24f847dc16 100644 --- a/docs/02-app/01-building-your-application/06-optimizing/13-memory-usage.mdx +++ b/docs/02-app/01-building-your-application/06-optimizing/13-memory-usage.mdx @@ -11,7 +11,7 @@ Let's explore some strategies and techniques to optimize memory and address comm Applications with a large amount of dependencies will use more memory. -The [Bundle Analyzer](/docs/app/building-your-application/optimizing/bundling-packages#analyzing-javascript-bundles) can help you investigate large dependencies in your application that may be able to be removed to improve performance and memory usage. +The [Bundle Analyzer](/docs/app/building-your-application/optimizing/package-bundling#analyzing-javascript-bundles) can help you investigate large dependencies in your application that may be able to be removed to improve performance and memory usage. ## Run `next build` with `--experimental-debug-memory-usage` diff --git a/docs/02-app/01-building-your-application/10-deploying/01-production-checklist.mdx b/docs/02-app/01-building-your-application/10-deploying/01-production-checklist.mdx index 47ced77b42afb..a9f325128ad60 100644 --- a/docs/02-app/01-building-your-application/10-deploying/01-production-checklist.mdx +++ b/docs/02-app/01-building-your-application/10-deploying/01-production-checklist.mdx @@ -139,7 +139,7 @@ Before going to production, you can run `next build` to build your application l ### Analyzing bundles -Use the [`@next/bundle-analyzer` plugin](/docs/app/building-your-application/optimizing/bundling-packages#analyzing-javascript-bundles) to analyze the size of your JavaScript bundles and identify large modules and dependencies that might be impacting your application's performance. +Use the [`@next/bundle-analyzer` plugin](/docs/app/building-your-application/optimizing/package-bundling#analyzing-javascript-bundles) to analyze the size of your JavaScript bundles and identify large modules and dependencies that might be impacting your application's performance. Additionally, the following tools can you understand the impact of adding new dependencies to your application: diff --git a/docs/03-pages/01-building-your-application/05-optimizing/06-package-bundling.mdx b/docs/03-pages/01-building-your-application/05-optimizing/06-package-bundling.mdx index 0c3dd129f48f9..af0fa7c911e6e 100644 --- a/docs/03-pages/01-building-your-application/05-optimizing/06-package-bundling.mdx +++ b/docs/03-pages/01-building-your-application/05-optimizing/06-package-bundling.mdx @@ -2,7 +2,7 @@ title: Optimizing Bundling nav_title: Bundling description: Learn how to optimize your application's server and client bundles. -source: /docs/app/building-your-application/optimizing/bundling-packages +source: /docs/app/building-your-application/optimizing/package-bundling related: description: Learn more about optimizing your application for production. links: From afb0d5d53890313b2e1ccb83b3d3de67baf16aed Mon Sep 17 00:00:00 2001 From: Delba de Oliveira Date: Fri, 10 May 2024 12:29:49 +0100 Subject: [PATCH 12/64] Fix server actions example --- .../02-server-actions-and-mutations.mdx | 42 ++++++++----------- .../05-optimizing/06-package-bundling.mdx | 2 +- 2 files changed, 18 insertions(+), 26 deletions(-) diff --git a/docs/02-app/01-building-your-application/02-data-fetching/02-server-actions-and-mutations.mdx b/docs/02-app/01-building-your-application/02-data-fetching/02-server-actions-and-mutations.mdx index 65105fcc1e919..2e1d9a87dc4fc 100644 --- a/docs/02-app/01-building-your-application/02-data-fetching/02-server-actions-and-mutations.mdx +++ b/docs/02-app/01-building-your-application/02-data-fetching/02-server-actions-and-mutations.mdx @@ -8,7 +8,7 @@ related: - app/api-reference/next-config-js/serverActions --- -Server Actions are **asynchronous functions** that are executed on the server. They can be used in Server and Client Components to handle form submissions and data mutations in Next.js applications. +[Server Actions]() are **asynchronous functions** that are executed on the server. They can be called in Server and Client Components to handle form submissions and data mutations in Next.js applications. > **🎥 Watch:** Learn more about forms and mutations with Server Actions → [YouTube (10 minutes)](https://youtu.be/dDpZfOQBMaU?si=cJZHlUu_jFhCzHUg). @@ -22,78 +22,70 @@ Server Components can use the inline function level or module level `"use server ```tsx filename="app/page.tsx" switcher // Server Component + export default function Page() { // Server Action async function create() { 'use server' - - // ... + // Mutate data } - return ( - // ... - ) + return <> } ``` ```jsx filename="app/page.jsx" switcher // Server Component + export default function Page() { // Server Action async function create() { 'use server' - - // ... + // Mutate data } - return ( - // ... - ) + return <> } ``` ### Client Components -Client Components can only import actions that use the module-level `"use server"` directive. - To call a Server Action in a Client Component, create a new file and add the `"use server"` directive at the top of it. All functions within the file will be marked as Server Actions that can be reused in both Client and Server Components: ```tsx filename="app/actions.ts" switcher 'use server' -export async function create() { - // ... -} +export async function create() {} ``` ```js filename="app/actions.js" switcher 'use server' -export async function create() { - // ... -} +export async function create() {} ``` ```tsx filename="app/ui/button.tsx" switcher +'use client' + import { create } from '@/app/actions' export function Button() { - return ( - // ... - ) + return - ) -} -``` - -```jsx filename="app/submit-button.jsx" switcher -'use client' - -import { useFormStatus } from 'react-dom' - -export function SubmitButton() { - const { pending } = useFormStatus() - - return ( - - ) -} -``` - -`` can then be nested in any form: - -```tsx filename="app/page.tsx" switcher -import { SubmitButton } from '@/app/submit-button' -import { createItem } from '@/app/actions' - -// Server Component -export default async function Home() { - return ( - - - - - ) -} -``` - -```jsx filename="app/page.jsx" switcher -import { SubmitButton } from '@/app/submit-button' -import { createItem } from '@/app/actions' - -// Server Component -export default async function Home() { - return ( -
- - - - ) -} -``` - #### Server-side validation and error handling We recommend using HTML validation like `required` and `type="email"` for basic client-side form validation. @@ -379,7 +306,7 @@ export async function createUser(prevState, formData) { Then, you can pass your action to the `useActionState` hook and use the returned `state` to display an error message. -```tsx filename="app/ui/signup.tsx" switcher +```tsx filename="app/ui/signup.tsx" highlight={11,18-20} switcher 'use client' import { useActionState } from 'react' @@ -406,7 +333,7 @@ export function Signup() { } ``` -```jsx filename="app/ui/signup.js" switcher +```jsx filename="app/ui/signup.js" highlight={11,18-20} switcher 'use client' import { useActionState } from 'react' @@ -433,9 +360,69 @@ export function Signup() { } ``` -> **Good to know:** -> -> - Before mutating data, you should always ensure a user is also authorized to perform the action. See [Authentication and Authorization](#authentication-and-authorization). +#### Pending states + +The [`useActionState`](https://react.dev/reference/react/useActionState) hook exposes a `pending` state that can be used to show a loading indicator while the action is being executed. + +```tsx filename="app/submit-button.tsx" highlight={11,21-23} switcher +'use client' + +import { useActionState } from 'react' +import { createUser } from '@/app/actions' + +const initialState = { + message: '', +} + +export function Signup() { + const [state, formAction, pending] = useActionState(createUser, initialState) + + return ( +
+ + + {/* ... */} +

+ {state?.message} +

+ +
+ ) +} +``` + +```jsx filename="app/submit-button.jsx" highlight={11,21-23} switcher +'use client' + +import { useActionState } from 'react' +import { createUser } from '@/app/actions' + +const initialState = { + message: '', +} + +export function Signup() { + const [state, formAction, pending] = useActionState(createUser, initialState) + + return ( +
+ + + {/* ... */} +

+ {state?.message} +

+ +
+ ) +} +``` + +> **Good to know:** Alternatively, you can also use the [`useFormStatus`](https://react.dev/reference/react-dom/hooks/useFormStatus) hook to show a pending state for a specific form. #### Optimistic updates @@ -991,6 +978,7 @@ Learn more about [Security and Server Actions](https://nextjs.org/blog/security- For more information on Server Actions, check out the following React docs: +- [Server Actions](https://react.dev/reference/rsc/server-actions) - [`"use server"`](https://react.dev/reference/react/use-server) - [`
`](https://react.dev/reference/react-dom/components/form) - [`useFormStatus`](https://react.dev/reference/react-dom/hooks/useFormStatus) diff --git a/docs/02-app/01-building-your-application/09-authentication/index.mdx b/docs/02-app/01-building-your-application/09-authentication/index.mdx index 14289f4bcf91a..4aa0f31aa7711 100644 --- a/docs/02-app/01-building-your-application/09-authentication/index.mdx +++ b/docs/02-app/01-building-your-application/09-authentication/index.mdx @@ -29,7 +29,7 @@ The examples on this page walk through basic username and password auth for educ ### Sign-up and login functionality -You can use the [``](https://react.dev/reference/react-dom/components/form) element with React's [Server Actions](/docs/app/building-your-application/rendering/server-components), [`useFormStatus()`](https://react.dev/reference/react-dom/hooks/useFormStatus), and [`useActionState()`](https://react.dev/reference/react/useActionState) to capture user credentials, validate form fields, and call your Authentication Provider's API or database. +You can use the [``](https://react.dev/reference/react-dom/components/form) element with React's [Server Actions](/docs/app/building-your-application/rendering/server-components) and [`useActionState()`](https://react.dev/reference/react/useActionState) to capture user credentials, validate form fields, and call your Authentication Provider's API or database. Since Server Actions always execute on the server, they provide a secure environment for handling authentication logic. @@ -200,9 +200,9 @@ export async function signup(state, formData) { } ``` -Back in your ``, you can use React's `useActionState()` hook to display validation errors to the user: +Back in your ``, you can use React's `useActionState()` hook to display validation errors and a pending state while the form is submitting: -```tsx filename="app/ui/signup-form.tsx" switcher highlight={7,15,21,27-36} +```tsx filename="app/ui/signup-form.tsx" switcher highlight={7,15,21,27-39} 'use client' import { useActionState } from 'react' @@ -239,13 +239,15 @@ export function SignupForm() { )} - + ) } ``` -```jsx filename="app/ui/signup-form.js" switcher highlight={7,15,21,27-36} +```jsx filename="app/ui/signup-form.js" switcher highlight={7,15,21,27-39} 'use client' import { useActionState } from 'react' @@ -282,49 +284,15 @@ export function SignupForm() { )} - + ) } ``` -You can also use the `useFormStatus()` hook to handle the pending state on form submission: - -```tsx filename="app/ui/signup-form.tsx" highlight={6} switcher -'use client' - -import { useActionState } from 'react' -import { useFormStatus } from 'react-dom' - -export function SignupButton() { - const { pending } = useFormStatus() - - return ( - - ) -} -``` - -```jsx filename="app/ui/signup-form.js" highlight={6} switcher -'use client' - -import { useActionState } from 'react' -import { useFormStatus } from 'react-dom' - -export function SignupButton() { - const { pending } = useFormStatus() - - return ( - - ) -} -``` - -> **Good to know:** `useFormStatus()` must be called from a component that is rendered inside a `
`. See the [React Docs](https://react.dev/reference/react-dom/hooks/useFormStatus#usage) for more information. +> **Good to know:** Alternatively, you can use the [`useFormStatus`](https://react.dev/reference/react-dom/hooks/useFormStatus) hook to display the pending state. #### 3. Create a user or check user credentials From 827bce7e13b4fac7f31ce05b3bbbf7fd7d43c98b Mon Sep 17 00:00:00 2001 From: Delba de Oliveira Date: Fri, 10 May 2024 13:38:35 +0100 Subject: [PATCH 14/64] Review useOptimistic example --- .../02-server-actions-and-mutations.mdx | 40 +++++++++---------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/docs/02-app/01-building-your-application/02-data-fetching/02-server-actions-and-mutations.mdx b/docs/02-app/01-building-your-application/02-data-fetching/02-server-actions-and-mutations.mdx index 0c1743ca63762..6ae0a1eaf9e49 100644 --- a/docs/02-app/01-building-your-application/02-data-fetching/02-server-actions-and-mutations.mdx +++ b/docs/02-app/01-building-your-application/02-data-fetching/02-server-actions-and-mutations.mdx @@ -8,7 +8,7 @@ related: - app/api-reference/next-config-js/serverActions --- -[Server Actions]() are **asynchronous functions** that are executed on the server. They can be called in Server and Client Components to handle form submissions and data mutations in Next.js applications. +[Server Actions](https://react.dev/reference/rsc/server-actions) are **asynchronous functions** that are executed on the server. They can be called in Server and Client Components to handle form submissions and data mutations in Next.js applications. > **🎥 Watch:** Learn more about mutations with Server Actions → [YouTube (10 minutes)](https://youtu.be/dDpZfOQBMaU?si=cJZHlUu_jFhCzHUg). @@ -21,8 +21,6 @@ A Server Action can be defined with the React [`"use server"`](https://react.dev Server Components can use the inline function level or module level `"use server"` directive. To inline a Server Action, add `"use server"` to the top of the function body: ```tsx filename="app/page.tsx" switcher -// Server Component - export default function Page() { // Server Action async function create() { @@ -35,8 +33,6 @@ export default function Page() { ``` ```jsx filename="app/page.jsx" switcher -// Server Component - export default function Page() { // Server Action async function create() { @@ -426,7 +422,7 @@ export function Signup() { #### Optimistic updates -You can use the React [`useOptimistic`](https://react.dev/reference/react/useOptimistic) hook to optimistically update the UI before the Server Action finishes, rather than waiting for the response: +You can use the React [`useOptimistic`](https://react.dev/reference/react/useOptimistic) hook to optimistically update the UI before the Server Action finishes executing, rather than waiting for the response: ```tsx filename="app/page.tsx" switcher 'use client' @@ -444,18 +440,18 @@ export function Thread({ messages }: { messages: Message[] }) { string >(messages, (state, newMessage) => [...state, { message: newMessage }]) + const formAction = async (formData) => { + const message = formData.get('message') + addOptimisticMessage(message) + await send(message) + } + return (
- {optimisticMessages.map((m, k) => ( -
{m.message}
+ {optimisticMessages.map((m, i) => ( +
{m.message}
))} - { - const message = formData.get('message') - addOptimisticMessage(message) - await send(message) - }} - > + @@ -476,18 +472,18 @@ export function Thread({ messages }) { (state, newMessage) => [...state, { message: newMessage }] ) + const formAction = async (formData) => { + const message = formData.get('message') + addOptimisticMessage(message) + await send(message) + } + return (
{optimisticMessages.map((m) => (
{m.message}
))} -
{ - const message = formData.get('message') - addOptimisticMessage(message) - await send(message) - }} - > +
From 13e75429a547c4125941a9ec7ab834b12a94538b Mon Sep 17 00:00:00 2001 From: Delba de Oliveira Date: Fri, 10 May 2024 13:51:49 +0100 Subject: [PATCH 15/64] Review server actions page --- .../02-server-actions-and-mutations.mdx | 132 +++++++++--------- 1 file changed, 63 insertions(+), 69 deletions(-) diff --git a/docs/02-app/01-building-your-application/02-data-fetching/02-server-actions-and-mutations.mdx b/docs/02-app/01-building-your-application/02-data-fetching/02-server-actions-and-mutations.mdx index 6ae0a1eaf9e49..142018aed0f76 100644 --- a/docs/02-app/01-building-your-application/02-data-fetching/02-server-actions-and-mutations.mdx +++ b/docs/02-app/01-building-your-application/02-data-fetching/02-server-actions-and-mutations.mdx @@ -162,7 +162,7 @@ export default function Page() { > - When working with forms that have many fields, you may want to consider using the [`entries()`](https://developer.mozilla.org/en-US/docs/Web/API/FormData/entries) method with JavaScript's [`Object.fromEntries()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries). For example: `const rawFormData = Object.fromEntries(formData)`. One thing to note is that the `formData` will include additional `$ACTION_` properties. > - See [React `
` documentation](https://react.dev/reference/react-dom/components/form#handle-form-submission-with-a-server-action) to learn more. -#### Passing Additional Arguments +### Passing Additional Arguments You can pass additional arguments to a Server Action using the JavaScript `bind` method. @@ -213,7 +213,63 @@ export async function updateUser(userId, formData) {} > - An alternative is to pass arguments as hidden input fields in the form (e.g. ``). However, the value will be part of the rendered HTML and will not be encoded. > - `.bind` works in both Server and Client Components. It also supports progressive enhancement. -#### Server-side validation and error handling +### Nested form elements + +You can also invoke a Server Action in elements nested inside `` such as `