-
Notifications
You must be signed in to change notification settings - Fork 30.8k
docs: add Building guide #92507
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
Draft
aurorascharff
wants to merge
46
commits into
canary
Choose a base branch
from
docs/getting-started-building
base: canary
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+245
−1
Draft
docs: add Building guide #92507
Changes from all commits
Commits
Show all changes
46 commits
Select commit
Hold shift + click to select a range
fd7612a
docs: add Getting Started > Building guide
aurorascharff 831b82f
docs: fix build output symbols and improve error explanation
aurorascharff 5647664
docs: add partialFallbacks section for high-cardinality routes
aurorascharff 78b6afb
docs: link to blocking-route error reference instead of inline list
aurorascharff 6f68674
docs: clarify params error requires missing generateStaticParams
aurorascharff 671c577
docs: tighten Step 3 prerender error section
aurorascharff 5009157
docs: link Suspense references to streaming guide
aurorascharff 0eeecff
docs: clarify generateStaticParams doesn't guarantee fully static
aurorascharff f0d6085
docs: fix generateStaticParams output, routes stay PPR
aurorascharff 200846f
docs: clarify prerender behavior depends on route content
aurorascharff c4e4164
docs: clarify PPR symbol persists even when fully cached
aurorascharff 9efedb1
docs: simplify generateStaticParams result explanation
aurorascharff a8094bf
docs: fix unknown params have no shell without partialFallbacks
aurorascharff 809bcc1
docs: clean up generateStaticParams result paragraphs
aurorascharff 82fe8c1
docs: params are resolved ahead of time, not fully prerendered
aurorascharff 1f4b084
docs: unlisted params resolve without a fallback
aurorascharff a3a5b83
docs: move building guide from getting-started to guides
aurorascharff 0de0823
docs: link first Suspense mention to React docs, second to streaming …
aurorascharff 07b22be
docs: mention loading.js alongside Suspense as fix
aurorascharff 48e8e66
docs: add --debug-build-paths section for building specific routes
aurorascharff 1ab0a5a
docs: add 'What next build does' overview section
aurorascharff 5fe50e6
docs: replace inline fix list with link to blocking-route reference
aurorascharff b63af2d
docs: add starter code snippet to Example section
aurorascharff 3dba9f1
docs: add related frontmatter and match guide format
aurorascharff f9f21e8
docs: remove starter snippet that would fail at build time
aurorascharff 7eccc7b
docs: restructure guide to start with the problem
aurorascharff ae2672d
docs: move Cache Components explanation before the example
aurorascharff b462a91
docs: remove forward reference to partialFallbacks
aurorascharff 8f14e1d
docs: add cross-references to building guide
aurorascharff 928d1f4
docs: link to building guide from deploying page
aurorascharff e843778
docs: restore original build output link in caching page
aurorascharff ad51e62
docs: add build and deploy mention to installation page
aurorascharff 706a4d1
docs: move building guide link after the example block
aurorascharff 22776ad
Update
aurorascharff 9e49f38
Update for new build output
aurorascharff fe14199
Update
aurorascharff abb7a32
Update
aurorascharff 707e936
Update
aurorascharff 2498a25
Update writing style
aurorascharff a241b7a
Restructure guide
aurorascharff 0a76393
Update
aurorascharff 155c741
Update
aurorascharff cc34f9c
Update docs/01-app/02-guides/building.mdx
aurorascharff 8e3e965
docs: align Building guide route tree with actual next build output
aurorascharff 4047972
docs: refine Building guide (style, switchers, default-first flow)
aurorascharff e42357a
docs: clarify Building guide route tree explanation
aurorascharff File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,240 @@ | ||
| --- | ||
| title: Building your application | ||
| description: Learn what happens when you run next build, how to read the build output, and how to fix common prerender errors. | ||
| nav_title: Building | ||
| related: | ||
| description: Related API references and guides. | ||
| links: | ||
| - app/api-reference/cli/next | ||
| - app/getting-started/caching | ||
| - app/api-reference/functions/generate-static-params | ||
| - app/api-reference/config/next-config-js/cacheComponents | ||
| - app/guides/streaming | ||
| - app/guides/ci-build-caching | ||
| --- | ||
|
|
||
| Run `next build` to compile your app for production: optimized bundles, prerendered pages, and a route table that shows how each URL is served (fully static, partial prerender with streaming, or on demand). | ||
|
|
||
| ## What `next build` does | ||
|
|
||
| `next build` runs in these phases: | ||
|
|
||
| 1. **Setup.** Loads [environment variables](/docs/app/guides/environment-variables) (`.env` files), validates your [`next.config`](/docs/app/api-reference/config/next-config-js), and generates a [build ID](/docs/app/api-reference/config/next-config-js/generateBuildId). | ||
| 2. **Route discovery.** Scans `app/` and `pages/` for routes, proxy, and [instrumentation](/docs/app/api-reference/file-conventions/instrumentation) hooks. Generates TypeScript route definitions. | ||
| 3. **Compilation.** Bundles client, server, and edge code with [Turbopack](/docs/app/api-reference/turbopack) (or webpack). Transpiles TypeScript and JSX, tree-shakes unused code, and optimizes CSS and fonts. Type checking runs in parallel. | ||
| 4. **Static analysis.** Classifies each route for prerendering versus on-demand rendering. Collects [`generateStaticParams`](/docs/app/api-reference/functions/generate-static-params) output. Checks for [prerender-blocking errors](/docs/messages/blocking-route). | ||
| 5. **Prerendering.** Prerenders static pages and PPR shells to HTML. Generates [RSC payloads](/docs/app/getting-started/server-and-client-components#on-the-server) for client-side navigation. | ||
| 6. **Output.** Writes the build to `.next/`. For [`output: 'standalone'`](/docs/app/guides/self-hosting), bundles only the files needed at runtime. For [`output: 'export'`](/docs/app/guides/static-exports), generates a full static site. Prints the route table. | ||
|
|
||
| ## Reading the build output | ||
|
|
||
| With [Cache Components](/docs/app/api-reference/config/next-config-js/cacheComponents), Next.js prerenders as much of each route as it can at build time. Request-time data (`params`, `searchParams`, `cookies()`, `headers()`, and similar) is not available during that pass. Wrap that work in [`<Suspense>`](/docs/app/guides/streaming) or [`'use cache'`](/docs/app/api-reference/directives/use-cache), or the build fails with a [prerender-blocking error](/docs/messages/blocking-route). | ||
|
|
||
| After a successful build, the route table puts a **symbol on each main route row**. When you use [`generateStaticParams`](/docs/app/api-reference/functions/generate-static-params), the dynamic segment gets one labeled row, and each prerendered URL appears indented underneath that row. The legend at the bottom lists only symbols that appeared in the tree. | ||
|
|
||
| | Symbol | Name | Behavior | | ||
| | ------ | ----------------- | -------------------------------------------------------------------------- | | ||
| | `○` | Static | Fully prerendered at build time. Served from CDN with no server work. | | ||
| | `◐` | Partial Prerender | Static shell served from CDN. Dynamic content streams in at request time. | | ||
| | `●` | SSG | Prerendered static HTML (from `generateStaticParams` or `getStaticProps`). | | ||
| | `ƒ` | Dynamic | Server-rendered on demand for every request. | | ||
|
|
||
| With Cache Components, App Router `page` routes show `○` or `◐`. You still see `ƒ` for API routes, [Proxy](/docs/app/api-reference/file-conventions/proxy) routes, dynamic [metadata](/docs/app/api-reference/functions/generate-metadata) (such as `icon` or `opengraph-image`), and other handlers that render on every request. Without Cache Components, or on the Pages Router, prerendered pages can show `●` (SSG) and on-demand pages can show `ƒ` (Dynamic). | ||
|
|
||
| [Partial Prerendering](/docs/app/getting-started/caching#how-rendering-works) is the default rendering model with Cache Components. The example below walks through a dynamic segment and shows how its prerendered URLs appear in the route table. | ||
|
|
||
| ## Example | ||
|
|
||
| This example uses a dynamic product page at `/products/[id]` that loads data by id: | ||
|
|
||
| ```tsx filename="app/products/[id]/page.tsx" switcher | ||
| export default async function Page({ params }) { | ||
| const { id } = await params | ||
| const product = await db.product.find(id) | ||
| return <div>{product.name}</div> | ||
| } | ||
| ``` | ||
|
|
||
| ```jsx filename="app/products/[id]/page.js" switcher | ||
| export default async function Page({ params }) { | ||
| const { id } = await params | ||
| const product = await db.product.find(id) | ||
| return <div>{product.name}</div> | ||
| } | ||
| ``` | ||
|
|
||
| `next build` fails with: | ||
|
|
||
| ```txt filename="Terminal" | ||
| Uncached data, `params`, `searchParams`, or `connection()` was accessed outside of `<Suspense>`. | ||
| This delays the entire page from rendering, resulting in a slow user experience. | ||
| ``` | ||
|
|
||
| Next.js does not know param values at build time, so it cannot prerender this page. Decide how to supply or defer that data. See the [blocking-route error reference](/docs/messages/blocking-route) for triggers and fixes. | ||
|
|
||
| ### Resolve params with `generateStaticParams` | ||
|
|
||
| Export [`generateStaticParams`](/docs/app/api-reference/functions/generate-static-params) so Next.js knows which param values exist at build time: | ||
|
|
||
| ```tsx filename="app/products/[id]/page.tsx" switcher | ||
| export async function generateStaticParams() { | ||
| const products = await db.product.findMany() | ||
| return products.map((product) => ({ id: product.id })) | ||
| } | ||
|
|
||
| export default async function Page({ params }) { | ||
| const { id } = await params | ||
| const product = await db.product.find(id) | ||
| return <div>{product.name}</div> | ||
| } | ||
| ``` | ||
|
|
||
| ```jsx filename="app/products/[id]/page.js" switcher | ||
| export async function generateStaticParams() { | ||
| const products = await db.product.findMany() | ||
| return products.map((product) => ({ id: product.id })) | ||
| } | ||
|
|
||
| export default async function Page({ params }) { | ||
| const { id } = await params | ||
| const product = await db.product.find(id) | ||
| return <div>{product.name}</div> | ||
| } | ||
| ``` | ||
|
|
||
| `next build` succeeds: | ||
|
|
||
| ```bash filename="Terminal" | ||
| Route (app) | ||
| ┌ ○ / | ||
| ├ ○ /_not-found | ||
| ├ ○ /products/[id] | ||
| │ ├ /products/1 | ||
| │ ├ /products/2 | ||
| │ └ /products/3 | ||
|
|
||
| ○ (Static) prerendered as static content | ||
| ``` | ||
|
|
||
| The `○` on `├ ○ /products/[id]` means that whole route is **static prerender** (see the legend). The indented lines name each concrete URL Next.js built for the ids you returned from `generateStaticParams`, such as `/products/1`, `/products/2`, and `/products/3`. | ||
|
|
||
| When there are more paths than fit in the preview, Next.js prints a short list and ends with `[+N more paths]`. | ||
|
|
||
| > **Good to know**: `generateStaticParams` must return at least one param. An empty array causes a [build error](/docs/messages/empty-generate-static-params). | ||
|
|
||
| Routes that use [`cacheLife`](/docs/app/api-reference/functions/cacheLife) also show `Revalidate` and `Expire` columns: | ||
|
|
||
| ```bash filename="Terminal" | ||
| Route (app) Revalidate Expire | ||
| ┌ ○ / 15m 1y | ||
| ├ ○ /_not-found | ||
| ├ ○ /products/[id] 15m 1y | ||
| │ ├ /products/1 15m 1y | ||
| │ ├ /products/2 15m 1y | ||
| │ └ /products/3 15m 1y | ||
| ``` | ||
|
|
||
| ### Stream dynamic content with Suspense | ||
|
|
||
| When you cannot list every param ahead of time, or part of the page needs cookies or headers, [stream](/docs/app/guides/streaming) that work inside [`<Suspense>`](https://react.dev/reference/react/Suspense), or add [`loading.js`](/docs/app/api-reference/file-conventions/loading): | ||
|
|
||
| ```tsx filename="app/products/[id]/page.tsx" switcher | ||
| import { Suspense } from 'react' | ||
|
|
||
| export default function Page({ params }) { | ||
| return ( | ||
| <Suspense fallback={<ProductSkeleton />}> | ||
| <ProductContent params={params} /> | ||
| </Suspense> | ||
| ) | ||
| } | ||
|
|
||
| async function ProductContent({ params }) { | ||
| const { id } = await params | ||
| const product = await db.product.find(id) | ||
| return <div>{product.name}</div> | ||
| } | ||
| ``` | ||
|
|
||
| ```jsx filename="app/products/[id]/page.js" switcher | ||
| import { Suspense } from 'react' | ||
|
|
||
| export default function Page({ params }) { | ||
| return ( | ||
| <Suspense fallback={<ProductSkeleton />}> | ||
| <ProductContent params={params} /> | ||
| </Suspense> | ||
| ) | ||
| } | ||
|
|
||
| async function ProductContent({ params }) { | ||
| const { id } = await params | ||
| const product = await db.product.find(id) | ||
| return <div>{product.name}</div> | ||
| } | ||
| ``` | ||
|
|
||
| The fallback becomes part of the static shell. The rest streams in on each request: | ||
|
|
||
| ```bash filename="Terminal" | ||
| Route (app) | ||
| ┌ ○ / | ||
| ├ ○ /_not-found | ||
| └ ◐ /products/[id] | ||
|
|
||
| ○ (Static) prerendered as static content | ||
| ◐ (Partial Prerender) prerendered as static HTML with dynamic server-streamed content | ||
| ``` | ||
|
|
||
| You can combine `generateStaticParams` for known params with `<Suspense>` for request-specific content on the same page. | ||
|
|
||
| ### High-cardinality routes | ||
|
|
||
| Large or unbounded slug sets (for example, millions of product pages) are not practical to prerender fully at build time. | ||
|
|
||
| The experimental [`partialFallbacks`](/docs/app/api-reference/config/next-config-js/partialFallbacks) flag serves a `<Suspense>` shell from the CDN for unknown slugs while data streams in. After the first visit, the page can be cached and treated as static. | ||
|
|
||
| ```ts filename="next.config.ts" | ||
| import type { NextConfig } from 'next' | ||
|
|
||
| const nextConfig: NextConfig = { | ||
| cacheComponents: true, | ||
| experimental: { | ||
| partialFallbacks: true, | ||
| }, | ||
| } | ||
|
|
||
| export default nextConfig | ||
aurorascharff marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ``` | ||
|
|
||
| Without `partialFallbacks`, unlisted params wait on the server for a full render before the response is sent. With `partialFallbacks`, keep `generateStaticParams` small and let traffic decide which extra pages warm into cache. | ||
|
|
||
| ## Debugging prerender errors | ||
|
|
||
| When the error does not include a clear file and line, run: | ||
|
|
||
| ```bash filename="Terminal" | ||
| next build --debug-prerender | ||
| ``` | ||
|
|
||
| That disables minification, turns on source maps for server bundles, and prints stack traces that point at the triggering code. The build also continues after the first failure so you can see every issue in one run. | ||
|
|
||
| > **Warning**: Do not deploy builds produced with `--debug-prerender`. They skip optimizations you need in production. | ||
|
|
||
| ### Building specific routes | ||
|
|
||
| To iterate faster in a large app, scope the build with `--debug-build-paths`: | ||
|
|
||
| ```bash filename="Terminal" | ||
| next build --debug-build-paths="app/products/[id]/page.tsx" | ||
| ``` | ||
|
|
||
| Use comma-separated paths or globs. See [`--debug-build-paths`](/docs/app/api-reference/cli/next#building-specific-routes) for syntax. | ||
|
|
||
| ## Next steps | ||
|
|
||
| Next, learn how to: | ||
|
|
||
| - [Deploy your application](/docs/app/getting-started/deploying) | ||
| - [Cache data and UI](/docs/app/getting-started/caching) | ||
| - [Configure CI build caching](/docs/app/guides/ci-build-caching) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.