You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/01-app/02-guides/static-exports.mdx
+48-13Lines changed: 48 additions & 13 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -165,19 +165,20 @@ module.exports = nextConfig
165
165
During `next build`, Next.js uses [vary params](/docs/app/api-reference/functions/generate-static-params) to determine which parts of each route depend on which dynamic params. It then renders a fallback shell per dynamic route:
166
166
167
167
-**Param-independent layouts and components** (those that don't read the dynamic param) render fully as Server Components at build time.
168
-
-**Param-dependent components** (those that `await params`) suspend at the nearest [Suspense boundary](/docs/app/guides/streaming#granular-streaming-with-suspense), showing your `loading.tsx` or `<Suspense fallback>` UI.
168
+
-**Param-dependent boundaries** suspend at the nearest [Suspense boundary](/docs/app/guides/streaming#granular-streaming-with-suspense), showing your `loading.tsx` or `<Suspense fallback>` UI.
169
169
170
-
Wrap param-dependent content in a Suspense boundary so the fallback shell can show meaningful loading UI:
170
+
For `output: 'export'`, the most ergonomic shape is a shared Server Component shell with a Client Component leaf for paths you did not prerender with `generateStaticParams`. Wrap that client leaf in a Suspense boundary so the fallback shell can show meaningful loading UI:
> **Good to know**: A Suspense boundary lets Next.js emit the fallback shell at build time, but it does not create a runtime server request later. For unknown params in `output: 'export'`, request-specific data must still cross into a Client Component.
229
+
202
230
#### Combining with `generateStaticParams`
203
231
204
-
If you export `generateStaticParams`, the returned params are fully prerendered at build time. Any other param values fall back to the shared shell. This lets you prerender your most popular pages while still supporting the long tail:
232
+
If you export `generateStaticParams`, the returned params are fully prerendered at build time, which lets you keep using Server Components at build time for those known paths. Any other param values fall back to the shared shell. In other words, the same route can use both fully prerendered params and fallback-rendered unknown params:
205
233
206
234
```tsx filename="app/blog/[slug]/page.tsx"
207
235
// These slugs get full static HTML at build time
@@ -222,12 +250,12 @@ For example, `/docs/[section]/[page]` is matched before `/docs/[...slug]`, so `/
222
250
223
251
To serve unenumerated params on a static host, configure the host's 404 or error document to serve `_fallback.html` from the export output for document navigations:
| GitHub Pages |Copy`_fallback.html` to `404.html`|
231
259
232
260
When a user visits an unenumerated route, the host serves `_fallback.html`. The Next.js client router then discovers the correct fallback shell and renders the page with param-dependent content loading on the client.
233
261
@@ -272,6 +300,12 @@ server {
272
300
273
301
With `trailingSlash: true`, the same config works because prerendered routes are emitted as `/route/index.html` and unknown paths still fall back to `/_fallback.html`. With `trailingSlash: false`, keep the `try_files $uri $uri.html $uri/ /_fallback.html;` order so prerendered flat files are served before the fallback bootstrap.
274
302
303
+
#### Deployment tips
304
+
305
+
-**S3 + CloudFront**: If your S3 origin returns `403` for missing files, configure CloudFront custom error responses for both `403` and `404` to serve `/_fallback.html`. Use a `200` response code if you want SPA-style hard navigations for unknown params.
306
+
-**GitHub Pages**: Keep `_fallback.html` as the canonical export artifact, then copy it to `404.html` as part of your deploy step. GitHub Pages uses `404.html` as its static fallback entrypoint.
307
+
-**First paint**: `/_fallback.html` is a bootstrap document, not the final page. The first meaningful UI should come from the resolved fallback route shell, so prefer neutral loading states over route-specific content in that phase.
308
+
275
309
#### Server and client boundaries
276
310
277
311
Fallback routes in `output: 'export'` do not have a runtime server request. For unenumerated paths, request-specific APIs and unresolved fallback params are only available on the client.
@@ -301,6 +335,7 @@ export default async function Page() {
301
335
> **Good to know**:
302
336
>
303
337
> - Param-dependent content for fallback routes renders on the client, so use client-side fetching patterns like `fetch`, SWR, or React Query in those parts of the tree.
338
+
> - Prefer `generateStaticParams` for SEO-critical or frequently visited routes, then let other paths use the export fallback shell.
304
339
> - Direct requests for unenumerated params may initially return a 404 status from the static host before the fallback shell loads. SEO-sensitive pages should be listed in `generateStaticParams`.
305
340
> - This mode does not provide ISR. Rebuilding is still required to promote a fallback path to a fully prerendered page.
306
341
> - Route names starting with `__fallback` are reserved and cannot be used with this feature.
Copy file name to clipboardExpand all lines: docs/01-app/03-api-reference/03-file-conventions/dynamic-routes.mdx
+11-1Lines changed: 11 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -160,6 +160,8 @@ All params are runtime data. Param access must be wrapped by Suspense fallback U
160
160
161
161
> **Good to know**: You can also use [`loading.tsx`](/docs/app/api-reference/file-conventions/loading) for page-level fallback UI.
162
162
163
+
> **Good to know**: When using [`output: 'export'`](/docs/app/guides/static-exports), the component that consumes unknown params should typically be a Client Component. That keeps the shared shell static while the long-tail route resolves on the client.
When using [`output: 'export'`](/docs/app/guides/static-exports) for App Router dynamic routes with `cacheComponents: true`, `generateStaticParams` is optional. Next.js emits a shared fallback shell for the dynamic route, prerenders any param-independent layouts or Server Components at build time, and resolves param-dependent content on the client. If you still export `generateStaticParams`, those params are fully prerendered and the rest use the fallback shell.
296
+
When using [`output: 'export'`](/docs/app/guides/static-exports) for App Router dynamic routes with `cacheComponents: true`, `generateStaticParams` is optional. Next.js emits a shared fallback shell for the dynamic route, prerenders any param-independent layouts or Server Components at build time, and resolves param-dependent content on the client. If you still export `generateStaticParams`, those params are fully prerendered so you can keep using Server Components at build time for the paths you know ahead of time, and the rest use the fallback shell. The same route can do both at once: prerender the params you return and fall back for the params you do not return.
297
+
298
+
For the best ergonomics in `output: 'export'`:
299
+
300
+
- Keep shared layout and shell content in Server Components.
301
+
- Move param reads and request-specific data for paths you did not prerender into Client Components.
302
+
- Use Suspense to show loading UI while the client resolves those paths.
303
+
304
+
> **Good to know**: In `output: 'export'`, a Suspense boundary makes the shell prerenderable, but it does not create a runtime server request. Unknown params still need a Client Component boundary if they depend on request-time data.
Copy file name to clipboardExpand all lines: docs/01-app/03-api-reference/04-functions/generate-static-params.mdx
+7-1Lines changed: 7 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -311,10 +311,16 @@ When using [Cache Components](/docs/app/getting-started/caching) with dynamic ro
311
311
312
312
For server deployments, `generateStaticParams` must return **at least one param**. Empty arrays cause a [build error](/docs/messages/empty-generate-static-params). This allows Cache Components to validate your route doesn't incorrectly access `cookies()`, `headers()`, or `searchParams` at runtime.
313
313
314
-
When using [`output: 'export'`](/docs/app/guides/static-exports) with App Router dynamic routes, `generateStaticParams` becomes optional when `cacheComponents: true` is enabled. If you omit it, Next.js emits a fallback shell for the route and resolves param-dependent content on the client. If you provide it, the returned params are prerendered and all other params use the fallback shell.
314
+
When using [`output: 'export'`](/docs/app/guides/static-exports) with App Router dynamic routes, `generateStaticParams` becomes optional when `cacheComponents: true` is enabled. If you omit it, Next.js emits a fallback shell for the route and resolves param-dependent content on the client. If you provide it, the returned params are prerendered so you can keep using Server Components at build time for the paths you know ahead of time, and all other params use the fallback shell. The same route can mix both behaviors: prerendered params from `generateStaticParams` and fallback rendering for params you did not return.
315
315
316
316
When multiple dynamic route patterns share the same static prefix in `output: 'export'`, the fallback shell still follows normal App Router route specificity. For example, if both `/docs/[section]/[page]` and `/docs/[...slug]` exist, params returned by `generateStaticParams` for the specific route are prerendered as usual, while unknown params still fall back and match the most specific route first.
317
317
318
+
For the best authoring ergonomics in `output: 'export'`:
319
+
320
+
- Return the params you care about most for SEO or fast first loads.
321
+
- Let other paths use the export fallback shell.
322
+
- Keep param-dependent request data in Client Components for paths you did not prerender.
323
+
318
324
> **Good to know**: If you don't know the actual param values at build time, you can return a placeholder param (e.g., `[{ slug: '__placeholder__' }]`) for validation, then handle it in your page with `notFound()`. However, this prevents build time validation from working effectively and may cause runtime errors.
319
325
320
326
See the [dynamic routes section](/docs/app/api-reference/file-conventions/dynamic-routes#with-cache-components) for detailed walkthroughs.
0 commit comments