Auto-commit 2026-04-29 16:31
This commit is contained in:
8
node_modules/next/dist/docs/02-pages/01-getting-started/01-installation.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/01-getting-started/01-installation.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: Create a new Next.js application
|
||||
nav_title: Installation
|
||||
description: How to create a new Next.js application with `create-next-app`. Set up TypeScript, ESLint,and configure your `next.config.js` file.
|
||||
source: app/getting-started/installation
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
8
node_modules/next/dist/docs/02-pages/01-getting-started/02-project-structure.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/01-getting-started/02-project-structure.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: Project Structure and Organization
|
||||
nav_title: Project Structure
|
||||
description: Learn about the folder and file conventions in a Next.js project, and how to organize your project.
|
||||
source: app/getting-started/project-structure
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
13
node_modules/next/dist/docs/02-pages/01-getting-started/04-images.md
generated
vendored
Normal file
13
node_modules/next/dist/docs/02-pages/01-getting-started/04-images.md
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
title: Image Optimization
|
||||
nav_title: Images
|
||||
description: Optimize your images with the built-in `next/image` component.
|
||||
related:
|
||||
title: API Reference
|
||||
description: See the API Reference for the full feature set of Next.js Image
|
||||
links:
|
||||
- pages/api-reference/components/image
|
||||
source: app/getting-started/images
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
13
node_modules/next/dist/docs/02-pages/01-getting-started/05-fonts.md
generated
vendored
Normal file
13
node_modules/next/dist/docs/02-pages/01-getting-started/05-fonts.md
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
title: How to use fonts
|
||||
nav_title: Fonts
|
||||
description: Learn how to use fonts in Next.js
|
||||
related:
|
||||
title: API Reference
|
||||
description: See the API Reference for the full feature set of Next.js Font
|
||||
links:
|
||||
- pages/api-reference/components/font
|
||||
source: app/getting-started/fonts
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
15
node_modules/next/dist/docs/02-pages/01-getting-started/06-css.md
generated
vendored
Normal file
15
node_modules/next/dist/docs/02-pages/01-getting-started/06-css.md
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
title: How to use CSS in your application
|
||||
nav_title: CSS
|
||||
description: Learn about the different ways to add CSS to your application, including CSS Modules, Global CSS, Tailwind CSS, and more.
|
||||
related:
|
||||
title: Next Steps
|
||||
description: Learn more about the features mentioned in this page.
|
||||
links:
|
||||
- pages/guides/tailwind-v3-css
|
||||
- pages/guides/sass
|
||||
- pages/guides/css-in-js
|
||||
source: app/getting-started/css
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
6
node_modules/next/dist/docs/02-pages/01-getting-started/11-deploying.md
generated
vendored
Normal file
6
node_modules/next/dist/docs/02-pages/01-getting-started/11-deploying.md
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
title: How to deploy your Next.js application
|
||||
nav_title: Deploying
|
||||
description: Learn how to deploy your Next.js application.
|
||||
source: app/getting-started/deploying
|
||||
---
|
||||
5
node_modules/next/dist/docs/02-pages/01-getting-started/index.md
generated
vendored
Normal file
5
node_modules/next/dist/docs/02-pages/01-getting-started/index.md
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: Getting Started - Pages Router
|
||||
nav_title: Getting Started
|
||||
description: Learn how to create full-stack web applications with Next.js with the Pages Router.
|
||||
---
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/analytics.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/analytics.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to set up analytics
|
||||
nav_title: Analytics
|
||||
description: Measure and track page performance using Next.js
|
||||
source: app/guides/analytics
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/authentication.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/authentication.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to implement authentication in Next.js
|
||||
nav_title: Authentication
|
||||
description: Learn how to implement authentication in Next.js, covering best practices, securing routes, authorization techniques, and session management.
|
||||
source: app/guides/authentication
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
66
node_modules/next/dist/docs/02-pages/02-guides/babel.md
generated
vendored
Normal file
66
node_modules/next/dist/docs/02-pages/02-guides/babel.md
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
---
|
||||
title: How to configure Babel in Next.js
|
||||
nav_title: Babel
|
||||
description: Extend the babel preset added by Next.js with your own configs.
|
||||
---
|
||||
|
||||
<details>
|
||||
<summary>Examples</summary>
|
||||
|
||||
- [Customizing babel configuration](https://github.com/vercel/next.js/tree/canary/examples/with-custom-babel-config)
|
||||
|
||||
</details>
|
||||
|
||||
Next.js includes the `next/babel` preset to your app, which includes everything needed to compile React applications and server-side code. But if you want to extend the default Babel configs, it's also possible.
|
||||
|
||||
## Adding Presets and Plugins
|
||||
|
||||
To start, you only need to define a `.babelrc` file (or `babel.config.js`) in the root directory of your project. If such a file is found, it will be considered as the _source of truth_, and therefore it needs to define what Next.js needs as well, which is the `next/babel` preset.
|
||||
|
||||
Here's an example `.babelrc` file:
|
||||
|
||||
```json filename=".babelrc"
|
||||
{
|
||||
"presets": ["next/babel"],
|
||||
"plugins": []
|
||||
}
|
||||
```
|
||||
|
||||
You can [take a look at this file](https://github.com/vercel/next.js/blob/canary/packages/next/src/build/babel/preset.ts) to learn about the presets included by `next/babel`.
|
||||
|
||||
To add presets/plugins **without configuring them**, you can do it this way:
|
||||
|
||||
```json filename=".babelrc"
|
||||
{
|
||||
"presets": ["next/babel"],
|
||||
"plugins": ["@babel/plugin-proposal-do-expressions"]
|
||||
}
|
||||
```
|
||||
|
||||
## Customizing Presets and Plugins
|
||||
|
||||
To add presets/plugins **with custom configuration**, do it on the `next/babel` preset like so:
|
||||
|
||||
```json filename=".babelrc"
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"next/babel",
|
||||
{
|
||||
"preset-env": {},
|
||||
"transform-runtime": {},
|
||||
"styled-jsx": {},
|
||||
"class-properties": {}
|
||||
}
|
||||
]
|
||||
],
|
||||
"plugins": []
|
||||
}
|
||||
```
|
||||
|
||||
To learn more about the available options for each config, visit babel's [documentation](https://babeljs.io/docs/) site.
|
||||
|
||||
> **Good to know**:
|
||||
>
|
||||
> - Next.js uses the [**current** Node.js version](https://github.com/nodejs/release#release-schedule) for server-side compilations.
|
||||
> - The `modules` option on `"preset-env"` should be kept to `false`, otherwise webpack code splitting is turned off.
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/ci-build-caching.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/ci-build-caching.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to configure Continuous Integration (CI) build caching
|
||||
nav_title: CI Build Caching
|
||||
description: Learn how to configure CI to cache Next.js builds
|
||||
source: app/guides/ci-build-caching
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/content-security-policy.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/content-security-policy.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to set a Content Security Policy (CSP) for your Next.js application
|
||||
nav_title: Content Security Policy
|
||||
description: Learn how to set a Content Security Policy (CSP) for your Next.js application.
|
||||
source: app/guides/content-security-policy
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/css-in-js.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/css-in-js.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to use CSS-in-JS libraries
|
||||
nav_title: CSS-in-JS
|
||||
description: Use CSS-in-JS libraries with Next.js
|
||||
source: app/guides/css-in-js
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/custom-server.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/custom-server.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to set up a custom server in Next.js
|
||||
nav_title: Custom Server
|
||||
description: Start a Next.js app programmatically using a custom server.
|
||||
source: app/guides/custom-server
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/debugging.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/debugging.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to use debugging tools with Next.js
|
||||
nav_title: Debugging
|
||||
description: Learn how to debug your Next.js application with VS Code or Chrome DevTools.
|
||||
source: app/guides/debugging
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
182
node_modules/next/dist/docs/02-pages/02-guides/draft-mode.md
generated
vendored
Normal file
182
node_modules/next/dist/docs/02-pages/02-guides/draft-mode.md
generated
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
---
|
||||
title: How to preview content with Draft Mode in Next.js
|
||||
nav_title: Draft Mode
|
||||
description: Next.js has draft mode to toggle between static and dynamic pages. You can learn how it works with Pages Router.
|
||||
---
|
||||
|
||||
In the [Pages documentation](/docs/pages/building-your-application/routing/pages-and-layouts) and the [Data Fetching documentation](/docs/pages/building-your-application/data-fetching), we talked about how to prerender a page at build time (**Static Generation**) using `getStaticProps` and `getStaticPaths`.
|
||||
|
||||
Static Generation is useful when your pages fetch data from a headless CMS. However, it’s not ideal when you’re writing a draft on your headless CMS and want to view the draft immediately on your page. You’d want Next.js to render these pages at **request time** instead of build time and fetch the draft content instead of the published content. You’d want Next.js to bypass Static Generation only for this specific case.
|
||||
|
||||
Next.js has a feature called **Draft Mode** which solves this problem. Here are instructions on how to use it.
|
||||
|
||||
## Step 1: Create and access the API route
|
||||
|
||||
> Take a look at the [API Routes documentation](/docs/pages/building-your-application/routing/api-routes) first if you’re not familiar with Next.js API Routes.
|
||||
|
||||
First, create the **API route**. It can have any name - e.g. `pages/api/draft.ts`
|
||||
|
||||
In this API route, you need to call `setDraftMode` on the response object.
|
||||
|
||||
```js
|
||||
export default function handler(req, res) {
|
||||
// ...
|
||||
res.setDraftMode({ enable: true })
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
This will set a **cookie** to enable draft mode. Subsequent requests containing this cookie will trigger **Draft Mode** changing the behavior for statically generated pages (more on this later).
|
||||
|
||||
You can test this manually by creating an API route like below and accessing it from your browser manually:
|
||||
|
||||
```ts filename="pages/api/draft.ts"
|
||||
// simple example for testing it manually from your browser.
|
||||
export default function handler(req, res) {
|
||||
res.setDraftMode({ enable: true })
|
||||
res.end('Draft mode is enabled')
|
||||
}
|
||||
```
|
||||
|
||||
If you open your browser’s developer tools and visit `/api/draft`, you’ll notice a `Set-Cookie` response header with a cookie named `__prerender_bypass`.
|
||||
|
||||
### Securely accessing it from your Headless CMS
|
||||
|
||||
In practice, you’d want to call this API route _securely_ from your headless CMS. The specific steps will vary depending on which headless CMS you’re using, but here are some common steps you could take.
|
||||
|
||||
These steps assume that the headless CMS you’re using supports setting **custom draft URLs**. If it doesn’t, you can still use this method to secure your draft URLs, but you’ll need to construct and access the draft URL manually.
|
||||
|
||||
**First**, you should create a **secret token string** using a token generator of your choice. This secret will only be known by your Next.js app and your headless CMS. This secret prevents people who don’t have access to your CMS from accessing draft URLs.
|
||||
|
||||
**Second**, if your headless CMS supports setting custom draft URLs, specify the following as the draft URL. This assumes that your draft API route is located at `pages/api/draft.ts`.
|
||||
|
||||
```bash filename="Terminal"
|
||||
https://<your-site>/api/draft?secret=<token>&slug=<path>
|
||||
```
|
||||
|
||||
- `<your-site>` should be your deployment domain.
|
||||
- `<token>` should be replaced with the secret token you generated.
|
||||
- `<path>` should be the path for the page that you want to view. If you want to view `/posts/foo`, then you should use `&slug=/posts/foo`.
|
||||
|
||||
Your headless CMS might allow you to include a variable in the draft URL so that `<path>` can be set dynamically based on the CMS’s data like so: `&slug=/posts/{entry.fields.slug}`
|
||||
|
||||
**Finally**, in the draft API route:
|
||||
|
||||
- Check that the secret matches and that the `slug` parameter exists (if not, the request should fail).
|
||||
-
|
||||
- Call `res.setDraftMode`.
|
||||
- Then redirect the browser to the path specified by `slug`. (The following example uses a [307 redirect](https://developer.mozilla.org/docs/Web/HTTP/Status/307)).
|
||||
|
||||
```js
|
||||
export default async (req, res) => {
|
||||
// Check the secret and next parameters
|
||||
// This secret should only be known to this API route and the CMS
|
||||
if (req.query.secret !== 'MY_SECRET_TOKEN' || !req.query.slug) {
|
||||
return res.status(401).json({ message: 'Invalid token' })
|
||||
}
|
||||
|
||||
// Fetch the headless CMS to check if the provided `slug` exists
|
||||
// getPostBySlug would implement the required fetching logic to the headless CMS
|
||||
const post = await getPostBySlug(req.query.slug)
|
||||
|
||||
// If the slug doesn't exist prevent draft mode from being enabled
|
||||
if (!post) {
|
||||
return res.status(401).json({ message: 'Invalid slug' })
|
||||
}
|
||||
|
||||
// Enable Draft Mode by setting the cookie
|
||||
res.setDraftMode({ enable: true })
|
||||
|
||||
// Redirect to the path from the fetched post
|
||||
// We don't redirect to req.query.slug as that might lead to open redirect vulnerabilities
|
||||
res.redirect(post.slug)
|
||||
}
|
||||
```
|
||||
|
||||
If it succeeds, then the browser will be redirected to the path you want to view with the draft mode cookie.
|
||||
|
||||
## Step 2: Update `getStaticProps`
|
||||
|
||||
The next step is to update `getStaticProps` to support draft mode.
|
||||
|
||||
If you request a page which has `getStaticProps` with the cookie set (via `res.setDraftMode`), then `getStaticProps` will be called at **request time** (instead of at build time).
|
||||
|
||||
Furthermore, it will be called with a `context` object where `context.draftMode` will be `true`.
|
||||
|
||||
```js
|
||||
export async function getStaticProps(context) {
|
||||
if (context.draftMode) {
|
||||
// dynamic data
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
We used `res.setDraftMode` in the draft API route, so `context.draftMode` will be `true`.
|
||||
|
||||
If you’re also using `getStaticPaths`, then `context.params` will also be available.
|
||||
|
||||
### Fetch draft data
|
||||
|
||||
You can update `getStaticProps` to fetch different data based on `context.draftMode`.
|
||||
|
||||
For example, your headless CMS might have a different API endpoint for draft posts. If so, you can modify the API endpoint URL like below:
|
||||
|
||||
```js
|
||||
export async function getStaticProps(context) {
|
||||
const url = context.draftMode
|
||||
? 'https://draft.example.com'
|
||||
: 'https://production.example.com'
|
||||
const res = await fetch(url)
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
That’s it! If you access the draft API route (with `secret` and `slug`) from your headless CMS or manually, you should now be able to see the draft content. And if you update your draft without publishing, you should be able to view the draft.
|
||||
|
||||
Set this as the draft URL on your headless CMS or access manually, and you should be able to see the draft.
|
||||
|
||||
```bash filename="Terminal"
|
||||
https://<your-site>/api/draft?secret=<token>&slug=<path>
|
||||
```
|
||||
|
||||
## More Details
|
||||
|
||||
### Clear the Draft Mode cookie
|
||||
|
||||
By default, the Draft Mode session ends when the browser is closed.
|
||||
|
||||
To clear the Draft Mode cookie manually, create an API route that calls `setDraftMode({ enable: false })`:
|
||||
|
||||
```ts filename="pages/api/disable-draft.ts"
|
||||
export default function handler(req, res) {
|
||||
res.setDraftMode({ enable: false })
|
||||
}
|
||||
```
|
||||
|
||||
Then, send a request to `/api/disable-draft` to invoke the API Route. If calling this route using [`next/link`](/docs/pages/api-reference/components/link), you must pass `prefetch={false}` to prevent accidentally deleting the cookie on prefetch.
|
||||
|
||||
### Works with `getServerSideProps`
|
||||
|
||||
Draft Mode works with `getServerSideProps`, and is available as a `draftMode` key in the [`context`](/docs/pages/api-reference/functions/get-server-side-props#context-parameter) object.
|
||||
|
||||
> **Good to know**: You shouldn't set the `Cache-Control` header when using Draft Mode because it cannot be bypassed. Instead, we recommend using [ISR](/docs/pages/guides/incremental-static-regeneration).
|
||||
|
||||
### Works with API Routes
|
||||
|
||||
API Routes will have access to `draftMode` on the request object. For example:
|
||||
|
||||
```js
|
||||
export default function myApiRoute(req, res) {
|
||||
if (req.draftMode) {
|
||||
// get draft data
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Unique per `next build`
|
||||
|
||||
A new bypass cookie value will be generated each time you run `next build`.
|
||||
|
||||
This ensures that the bypass cookie can’t be guessed.
|
||||
|
||||
> **Good to know**: To test Draft Mode locally over HTTP, your browser will need to allow third-party cookies and local storage access.
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/environment-variables.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/environment-variables.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to use environment variables in Next.js
|
||||
nav_title: Environment Variables
|
||||
description: Learn to add and access environment variables in your Next.js application.
|
||||
source: app/guides/environment-variables
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
336
node_modules/next/dist/docs/02-pages/02-guides/forms.md
generated
vendored
Normal file
336
node_modules/next/dist/docs/02-pages/02-guides/forms.md
generated
vendored
Normal file
@@ -0,0 +1,336 @@
|
||||
---
|
||||
title: How to create forms with API Routes
|
||||
nav_title: Forms
|
||||
description: Learn how to handle form submissions and data mutations with Next.js.
|
||||
---
|
||||
|
||||
Forms enable you to create and update data in web applications. Next.js provides a powerful way to handle data mutations using **API Routes**. This guide will walk you through how to handle form submission on the server.
|
||||
|
||||
## Server Forms
|
||||
|
||||
To handle form submissions on the server, create an API endpoint that securely mutates data.
|
||||
|
||||
```ts filename="pages/api/submit.ts" switcher
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
) {
|
||||
const data = req.body
|
||||
const id = await createItem(data)
|
||||
res.status(200).json({ id })
|
||||
}
|
||||
```
|
||||
|
||||
```js filename="pages/api/submit.js" switcher
|
||||
export default function handler(req, res) {
|
||||
const data = req.body
|
||||
// call your database, etc.
|
||||
// const id = await createItem(data)
|
||||
// ...
|
||||
res.status(200).json({ data })
|
||||
}
|
||||
```
|
||||
|
||||
Then, call the API Route from the client with an event handler:
|
||||
|
||||
```tsx filename="pages/index.tsx" switcher
|
||||
import { FormEvent } from 'react'
|
||||
|
||||
export default function Page() {
|
||||
async function onSubmit(event: FormEvent<HTMLFormElement>) {
|
||||
event.preventDefault()
|
||||
|
||||
const formData = new FormData(event.currentTarget)
|
||||
const response = await fetch('/api/submit', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
})
|
||||
|
||||
// Handle response if necessary
|
||||
const data = await response.json()
|
||||
// ...
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={onSubmit}>
|
||||
<input type="text" name="name" />
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/index.jsx" switcher
|
||||
export default function Page() {
|
||||
async function onSubmit(event) {
|
||||
event.preventDefault()
|
||||
|
||||
const formData = new FormData(event.currentTarget)
|
||||
const response = await fetch('/api/submit', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
})
|
||||
|
||||
// Handle response if necessary
|
||||
const data = await response.json()
|
||||
// ...
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={onSubmit}>
|
||||
<input type="text" name="name" />
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
> **Good to know:**
|
||||
>
|
||||
> - API Routes [do not specify CORS headers](https://developer.mozilla.org/docs/Web/HTTP/CORS), meaning they are same-origin only by default.
|
||||
> - Since API Routes run on the server, we're able to use sensitive values (like API keys) through [Environment Variables](/docs/pages/guides/environment-variables) without exposing them to the client. This is critical for the security of your application.
|
||||
|
||||
## Form validation
|
||||
|
||||
We recommend using HTML validation like `required` and `type="email"` for basic client-side form validation.
|
||||
|
||||
For more advanced server-side validation, you can use a schema validation library like [zod](https://zod.dev/) to validate the form fields before mutating the data:
|
||||
|
||||
```ts filename="pages/api/submit.ts" switcher
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
import { z } from 'zod'
|
||||
|
||||
const schema = z.object({
|
||||
// ...
|
||||
})
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
) {
|
||||
const parsed = schema.parse(req.body)
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
```js filename="pages/api/submit.js" switcher
|
||||
import { z } from 'zod'
|
||||
|
||||
const schema = z.object({
|
||||
// ...
|
||||
})
|
||||
|
||||
export default async function handler(req, res) {
|
||||
const parsed = schema.parse(req.body)
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Error handling
|
||||
|
||||
You can use React state to show an error message when a form submission fails:
|
||||
|
||||
```tsx filename="pages/index.tsx" switcher
|
||||
import React, { useState, FormEvent } from 'react'
|
||||
|
||||
export default function Page() {
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
|
||||
async function onSubmit(event: FormEvent<HTMLFormElement>) {
|
||||
event.preventDefault()
|
||||
setIsLoading(true)
|
||||
setError(null) // Clear previous errors when a new request starts
|
||||
|
||||
try {
|
||||
const formData = new FormData(event.currentTarget)
|
||||
const response = await fetch('/api/submit', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to submit the data. Please try again.')
|
||||
}
|
||||
|
||||
// Handle response if necessary
|
||||
const data = await response.json()
|
||||
// ...
|
||||
} catch (error) {
|
||||
// Capture the error message to display to the user
|
||||
setError(error.message)
|
||||
console.error(error)
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{error && <div style={{ color: 'red' }}>{error}</div>}
|
||||
<form onSubmit={onSubmit}>
|
||||
<input type="text" name="name" required />
|
||||
<button type="submit" disabled={isLoading}>
|
||||
{isLoading ? 'Loading...' : 'Submit'}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/index.jsx" switcher
|
||||
import React, { useState } from 'react'
|
||||
|
||||
export default function Page() {
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [error, setError] = useState(null)
|
||||
|
||||
async function onSubmit(event) {
|
||||
event.preventDefault()
|
||||
setIsLoading(true)
|
||||
setError(null) // Clear previous errors when a new request starts
|
||||
|
||||
try {
|
||||
const formData = new FormData(event.currentTarget)
|
||||
const response = await fetch('/api/submit', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to submit the data. Please try again.')
|
||||
}
|
||||
|
||||
// Handle response if necessary
|
||||
const data = await response.json()
|
||||
// ...
|
||||
} catch (error) {
|
||||
// Capture the error message to display to the user
|
||||
setError(error.message)
|
||||
console.error(error)
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{error && <div style={{ color: 'red' }}>{error}</div>}
|
||||
<form onSubmit={onSubmit}>
|
||||
<input type="text" name="name" required />
|
||||
<button type="submit" disabled={isLoading}>
|
||||
{isLoading ? 'Loading...' : 'Submit'}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Displaying loading state
|
||||
|
||||
You can use React state to show a loading state when a form is submitting on the server:
|
||||
|
||||
```tsx filename="pages/index.tsx" switcher
|
||||
import React, { useState, FormEvent } from 'react'
|
||||
|
||||
export default function Page() {
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false)
|
||||
|
||||
async function onSubmit(event: FormEvent<HTMLFormElement>) {
|
||||
event.preventDefault()
|
||||
setIsLoading(true) // Set loading to true when the request starts
|
||||
|
||||
try {
|
||||
const formData = new FormData(event.currentTarget)
|
||||
const response = await fetch('/api/submit', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
})
|
||||
|
||||
// Handle response if necessary
|
||||
const data = await response.json()
|
||||
// ...
|
||||
} catch (error) {
|
||||
// Handle error if necessary
|
||||
console.error(error)
|
||||
} finally {
|
||||
setIsLoading(false) // Set loading to false when the request completes
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={onSubmit}>
|
||||
<input type="text" name="name" />
|
||||
<button type="submit" disabled={isLoading}>
|
||||
{isLoading ? 'Loading...' : 'Submit'}
|
||||
</button>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/index.jsx" switcher
|
||||
import React, { useState } from 'react'
|
||||
|
||||
export default function Page() {
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
|
||||
async function onSubmit(event) {
|
||||
event.preventDefault()
|
||||
setIsLoading(true) // Set loading to true when the request starts
|
||||
|
||||
try {
|
||||
const formData = new FormData(event.currentTarget)
|
||||
const response = await fetch('/api/submit', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
})
|
||||
|
||||
// Handle response if necessary
|
||||
const data = await response.json()
|
||||
// ...
|
||||
} catch (error) {
|
||||
// Handle error if necessary
|
||||
console.error(error)
|
||||
} finally {
|
||||
setIsLoading(false) // Set loading to false when the request completes
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={onSubmit}>
|
||||
<input type="text" name="name" />
|
||||
<button type="submit" disabled={isLoading}>
|
||||
{isLoading ? 'Loading...' : 'Submit'}
|
||||
</button>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Redirecting
|
||||
|
||||
If you would like to redirect the user to a different route after a mutation, you can [`redirect`](/docs/pages/building-your-application/routing/api-routes#response-helpers) to any absolute or relative URL:
|
||||
|
||||
```ts filename="pages/api/submit.ts" switcher
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
) {
|
||||
const id = await addPost()
|
||||
res.redirect(307, `/post/${id}`)
|
||||
}
|
||||
```
|
||||
|
||||
```js filename="pages/api/submit.js" switcher
|
||||
export default async function handler(req, res) {
|
||||
const id = await addPost()
|
||||
res.redirect(307, `/post/${id}`)
|
||||
}
|
||||
```
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/incremental-static-regeneration.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/incremental-static-regeneration.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to implement Incremental Static Regeneration (ISR)
|
||||
nav_title: ISR
|
||||
description: Learn how to create or update static pages at runtime with Incremental Static Regeneration.
|
||||
source: app/guides/incremental-static-regeneration
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
4
node_modules/next/dist/docs/02-pages/02-guides/index.md
generated
vendored
Normal file
4
node_modules/next/dist/docs/02-pages/02-guides/index.md
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: Guides
|
||||
description: Learn how to implement common UI patterns and use cases using Next.js
|
||||
---
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/instrumentation.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/instrumentation.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to set up instrumentation
|
||||
nav_title: Instrumentation
|
||||
description: Learn how to use instrumentation to run code at server startup in your Next.js app
|
||||
source: app/guides/instrumentation
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
355
node_modules/next/dist/docs/02-pages/02-guides/internationalization.md
generated
vendored
Normal file
355
node_modules/next/dist/docs/02-pages/02-guides/internationalization.md
generated
vendored
Normal file
@@ -0,0 +1,355 @@
|
||||
---
|
||||
title: How to implement internationalization in Next.js
|
||||
nav_title: Internationalization
|
||||
description: Next.js has built-in support for internationalized routing and language detection. Learn more here.
|
||||
---
|
||||
|
||||
<details>
|
||||
<summary>Examples</summary>
|
||||
|
||||
- [i18n routing](https://github.com/vercel/next.js/tree/canary/examples/i18n-routing-pages)
|
||||
|
||||
</details>
|
||||
|
||||
Next.js has built-in support for internationalized ([i18n](https://en.wikipedia.org/wiki/Internationalization_and_localization#Naming)) routing since `v10.0.0`. You can provide a list of locales, the default locale, and domain-specific locales and Next.js will automatically handle the routing.
|
||||
|
||||
The i18n routing support is currently meant to complement existing i18n library solutions like [`react-intl`](https://formatjs.io/docs/getting-started/installation), [`react-i18next`](https://react.i18next.com/), [`lingui`](https://lingui.dev/), [`rosetta`](https://github.com/lukeed/rosetta), [`next-intl`](https://github.com/amannn/next-intl), [`next-translate`](https://github.com/aralroca/next-translate), [`next-multilingual`](https://github.com/Avansai/next-multilingual), [`tolgee`](https://tolgee.io/integrations/next), [`paraglide-next`](https://inlang.com/m/osslbuzt/paraglide-next-i18n), [`next-intlayer`](https://intlayer.org/doc/environment/nextjs/next-with-page-router), [`gt-react`](https://generaltranslation.com/en/docs/react) and others by streamlining the routes and locale parsing.
|
||||
|
||||
## Getting started
|
||||
|
||||
To get started, add the `i18n` config to your `next.config.js` file.
|
||||
|
||||
Locales are [UTS Locale Identifiers](https://www.unicode.org/reports/tr35/tr35-59/tr35.html#Identifiers), a standardized format for defining locales.
|
||||
|
||||
Generally a Locale Identifier is made up of a language, region, and script separated by a dash: `language-region-script`. The region and script are optional. An example:
|
||||
|
||||
- `en-US` - English as spoken in the United States
|
||||
- `nl-NL` - Dutch as spoken in the Netherlands
|
||||
- `nl` - Dutch, no specific region
|
||||
|
||||
If user locale is `nl-BE` and it is not listed in your configuration, they will be redirected to `nl` if available, or to the default locale otherwise.
|
||||
If you don't plan to support all regions of a country, it is therefore a good practice to include country locales that will act as fallbacks.
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
i18n: {
|
||||
// These are all the locales you want to support in
|
||||
// your application
|
||||
locales: ['en-US', 'fr', 'nl-NL'],
|
||||
// This is the default locale you want to be used when visiting
|
||||
// a non-locale prefixed path e.g. `/hello`
|
||||
defaultLocale: 'en-US',
|
||||
// This is a list of locale domains and the default locale they
|
||||
// should handle (these are only required when setting up domain routing)
|
||||
// Note: subdomains must be included in the domain value to be matched e.g. "fr.example.com".
|
||||
domains: [
|
||||
{
|
||||
domain: 'example.com',
|
||||
defaultLocale: 'en-US',
|
||||
},
|
||||
{
|
||||
domain: 'example.nl',
|
||||
defaultLocale: 'nl-NL',
|
||||
},
|
||||
{
|
||||
domain: 'example.fr',
|
||||
defaultLocale: 'fr',
|
||||
// an optional http field can also be used to test
|
||||
// locale domains locally with http instead of https
|
||||
http: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Locale Strategies
|
||||
|
||||
There are two locale handling strategies: Sub-path Routing and Domain Routing.
|
||||
|
||||
### Sub-path Routing
|
||||
|
||||
Sub-path Routing puts the locale in the url path.
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
i18n: {
|
||||
locales: ['en-US', 'fr', 'nl-NL'],
|
||||
defaultLocale: 'en-US',
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
With the above configuration `en-US`, `fr`, and `nl-NL` will be available to be routed to, and `en-US` is the default locale. If you have a `pages/blog.js` the following urls would be available:
|
||||
|
||||
- `/blog`
|
||||
- `/fr/blog`
|
||||
- `/nl-nl/blog`
|
||||
|
||||
The default locale does not have a prefix.
|
||||
|
||||
### Domain Routing
|
||||
|
||||
By using domain routing you can configure locales to be served from different domains:
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
i18n: {
|
||||
locales: ['en-US', 'fr', 'nl-NL', 'nl-BE'],
|
||||
defaultLocale: 'en-US',
|
||||
|
||||
domains: [
|
||||
{
|
||||
// Note: subdomains must be included in the domain value to be matched
|
||||
// e.g. www.example.com should be used if that is the expected hostname
|
||||
domain: 'example.com',
|
||||
defaultLocale: 'en-US',
|
||||
},
|
||||
{
|
||||
domain: 'example.fr',
|
||||
defaultLocale: 'fr',
|
||||
},
|
||||
{
|
||||
domain: 'example.nl',
|
||||
defaultLocale: 'nl-NL',
|
||||
// specify other locales that should be redirected
|
||||
// to this domain
|
||||
locales: ['nl-BE'],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
For example if you have `pages/blog.js` the following urls will be available:
|
||||
|
||||
- `example.com/blog`
|
||||
- `www.example.com/blog`
|
||||
- `example.fr/blog`
|
||||
- `example.nl/blog`
|
||||
- `example.nl/nl-BE/blog`
|
||||
|
||||
## Automatic Locale Detection
|
||||
|
||||
When a user visits the application root (generally `/`), Next.js will try to automatically detect which locale the user prefers based on the [`Accept-Language`](https://developer.mozilla.org/docs/Web/HTTP/Headers/Accept-Language) header and the current domain.
|
||||
|
||||
If a locale other than the default locale is detected, the user will be redirected to either:
|
||||
|
||||
- **When using Sub-path Routing:** The locale prefixed path
|
||||
- **When using Domain Routing:** The domain with that locale specified as the default
|
||||
|
||||
When using Domain Routing, if a user with the `Accept-Language` header `fr;q=0.9` visits `example.com`, they will be redirected to `example.fr` since that domain handles the `fr` locale by default.
|
||||
|
||||
When using Sub-path Routing, the user would be redirected to `/fr`.
|
||||
|
||||
### Prefixing the Default Locale
|
||||
|
||||
With Next.js 12 and [Proxy](/docs/pages/api-reference/file-conventions/proxy), we can add a prefix to the default locale with a [workaround](https://github.com/vercel/next.js/discussions/18419).
|
||||
|
||||
For example, here's a `next.config.js` file with support for a few languages. Note the `"default"` locale has been added intentionally.
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
i18n: {
|
||||
locales: ['default', 'en', 'de', 'fr'],
|
||||
defaultLocale: 'default',
|
||||
localeDetection: false,
|
||||
},
|
||||
trailingSlash: true,
|
||||
}
|
||||
```
|
||||
|
||||
Next, we can use [Proxy](/docs/pages/api-reference/file-conventions/proxy) to add custom routing rules:
|
||||
|
||||
```ts filename="proxy.ts"
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
const PUBLIC_FILE = /\.(.*)$/
|
||||
|
||||
export async function proxy(req: NextRequest) {
|
||||
if (
|
||||
req.nextUrl.pathname.startsWith('/_next') ||
|
||||
req.nextUrl.pathname.includes('/api/') ||
|
||||
PUBLIC_FILE.test(req.nextUrl.pathname)
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
if (req.nextUrl.locale === 'default') {
|
||||
const locale = req.cookies.get('NEXT_LOCALE')?.value || 'en'
|
||||
|
||||
return NextResponse.redirect(
|
||||
new URL(`/${locale}${req.nextUrl.pathname}${req.nextUrl.search}`, req.url)
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This [Proxy](/docs/pages/api-reference/file-conventions/proxy) skips adding the default prefix to [API Routes](/docs/pages/building-your-application/routing/api-routes) and [public](/docs/pages/api-reference/file-conventions/public-folder) files like fonts or images. If a request is made to the default locale, we redirect to our prefix `/en`.
|
||||
|
||||
### Disabling Automatic Locale Detection
|
||||
|
||||
The automatic locale detection can be disabled with:
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
i18n: {
|
||||
localeDetection: false,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
When `localeDetection` is set to `false` Next.js will no longer automatically redirect based on the user's preferred locale and will only provide locale information detected from either the locale based domain or locale path as described above.
|
||||
|
||||
## Accessing the locale information
|
||||
|
||||
You can access the locale information via the Next.js router. For example, using the [`useRouter()`](/docs/pages/api-reference/functions/use-router) hook the following properties are available:
|
||||
|
||||
- `locale` contains the currently active locale.
|
||||
- `locales` contains all configured locales.
|
||||
- `defaultLocale` contains the configured default locale.
|
||||
|
||||
When [prerendering](/docs/pages/building-your-application/rendering/static-site-generation) pages with `getStaticProps` or `getServerSideProps`, the locale information is provided in [the context](/docs/pages/building-your-application/data-fetching/get-static-props) provided to the function.
|
||||
|
||||
When leveraging `getStaticPaths`, the configured locales are provided in the context parameter of the function under `locales` and the configured defaultLocale under `defaultLocale`.
|
||||
|
||||
## Transition between locales
|
||||
|
||||
You can use `next/link` or `next/router` to transition between locales.
|
||||
|
||||
For `next/link`, a `locale` prop can be provided to transition to a different locale from the currently active one. If no `locale` prop is provided, the currently active `locale` is used during client-transitions. For example:
|
||||
|
||||
```jsx
|
||||
import Link from 'next/link'
|
||||
|
||||
export default function IndexPage(props) {
|
||||
return (
|
||||
<Link href="/another" locale="fr">
|
||||
To /fr/another
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
When using the `next/router` methods directly, you can specify the `locale` that should be used via the transition options. For example:
|
||||
|
||||
```jsx
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
export default function IndexPage(props) {
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<div
|
||||
onClick={() => {
|
||||
router.push('/another', '/another', { locale: 'fr' })
|
||||
}}
|
||||
>
|
||||
to /fr/another
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
Note that to handle switching only the `locale` while preserving all routing information such as [dynamic route](/docs/pages/building-your-application/routing/dynamic-routes) query values or hidden href query values, you can provide the `href` parameter as an object:
|
||||
|
||||
```jsx
|
||||
import { useRouter } from 'next/router'
|
||||
const router = useRouter()
|
||||
const { pathname, asPath, query } = router
|
||||
// change just the locale and maintain all other route information including href's query
|
||||
router.push({ pathname, query }, asPath, { locale: nextLocale })
|
||||
```
|
||||
|
||||
See [here](/docs/pages/api-reference/functions/use-router#with-url-object) for more information on the object structure for `router.push`.
|
||||
|
||||
If you have a `href` that already includes the locale you can opt-out of automatically handling the locale prefixing:
|
||||
|
||||
```jsx
|
||||
import Link from 'next/link'
|
||||
|
||||
export default function IndexPage(props) {
|
||||
return (
|
||||
<Link href="/fr/another" locale={false}>
|
||||
To /fr/another
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Leveraging the `NEXT_LOCALE` cookie
|
||||
|
||||
Next.js allows setting a `NEXT_LOCALE=the-locale` cookie, which takes priority over the accept-language header. This cookie can be set using a language switcher and then when a user comes back to the site it will leverage the locale specified in the cookie when redirecting from `/` to the correct locale location.
|
||||
|
||||
For example, if a user prefers the locale `fr` in their accept-language header but a `NEXT_LOCALE=en` cookie is set the `en` locale when visiting `/` the user will be redirected to the `en` locale location until the cookie is removed or expired.
|
||||
|
||||
## Search Engine Optimization
|
||||
|
||||
Since Next.js knows what language the user is visiting it will automatically add the `lang` attribute to the `<html>` tag.
|
||||
|
||||
Next.js doesn't know about variants of a page so it's up to you to add the `hreflang` meta tags using [`next/head`](/docs/pages/api-reference/components/head). You can learn more about `hreflang` in the [Google Webmasters documentation](https://support.google.com/webmasters/answer/189077).
|
||||
|
||||
## How does this work with Static Generation?
|
||||
|
||||
> Note that Internationalized Routing does not integrate with [`output: 'export'`](/docs/pages/guides/static-exports) as it does not leverage the Next.js routing layer. Hybrid Next.js applications that do not use `output: 'export'` are fully supported.
|
||||
|
||||
### Dynamic Routes and `getStaticProps` Pages
|
||||
|
||||
For pages using `getStaticProps` with [Dynamic Routes](/docs/pages/building-your-application/routing/dynamic-routes), all locale variants of the page desired to be prerendered need to be returned from [`getStaticPaths`](/docs/pages/building-your-application/data-fetching/get-static-paths). Along with the `params` object returned for `paths`, you can also return a `locale` field specifying which locale you want to render. For example:
|
||||
|
||||
```jsx filename="pages/blog/[slug].js"
|
||||
export const getStaticPaths = ({ locales }) => {
|
||||
return {
|
||||
paths: [
|
||||
// if no `locale` is provided only the defaultLocale will be generated
|
||||
{ params: { slug: 'post-1' }, locale: 'en-US' },
|
||||
{ params: { slug: 'post-1' }, locale: 'fr' },
|
||||
],
|
||||
fallback: true,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For [Automatically Statically Optimized](/docs/pages/building-your-application/rendering/automatic-static-optimization) and non-dynamic `getStaticProps` pages, **a version of the page will be generated for each locale**. This is important to consider because it can increase build times depending on how many locales are configured inside `getStaticProps`.
|
||||
|
||||
For example, if you have 50 locales configured with 10 non-dynamic pages using `getStaticProps`, this means `getStaticProps` will be called 500 times. 50 versions of the 10 pages will be generated during each build.
|
||||
|
||||
To decrease the build time of dynamic pages with `getStaticProps`, use a [`fallback` mode](/docs/pages/api-reference/functions/get-static-paths#fallback-true). This allows you to return only the most popular paths and locales from `getStaticPaths` for prerendering during the build. Then, Next.js will build the remaining pages at runtime as they are requested.
|
||||
|
||||
### Automatically Statically Optimized Pages
|
||||
|
||||
For pages that are [automatically statically optimized](/docs/pages/building-your-application/rendering/automatic-static-optimization), a version of the page will be generated for each locale.
|
||||
|
||||
### Non-dynamic getStaticProps Pages
|
||||
|
||||
For non-dynamic `getStaticProps` pages, a version is generated for each locale like above. `getStaticProps` is called with each `locale` that is being rendered. If you would like to opt-out of a certain locale from being prerendered, you can return `notFound: true` from `getStaticProps` and this variant of the page will not be generated.
|
||||
|
||||
```js
|
||||
export async function getStaticProps({ locale }) {
|
||||
// Call an external API endpoint to get posts.
|
||||
// You can use any data fetching library
|
||||
const res = await fetch(`https://.../posts?locale=${locale}`)
|
||||
const posts = await res.json()
|
||||
|
||||
if (posts.length === 0) {
|
||||
return {
|
||||
notFound: true,
|
||||
}
|
||||
}
|
||||
|
||||
// By returning { props: posts }, the Blog component
|
||||
// will receive `posts` as a prop at build time
|
||||
return {
|
||||
props: {
|
||||
posts,
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Limits for the i18n config
|
||||
|
||||
- `locales`: 100 total locales
|
||||
- `domains`: 100 total locale domain items
|
||||
|
||||
> **Good to know**: These limits have been added initially to prevent potential [performance issues at build time](#dynamic-routes-and-getstaticprops-pages). You can workaround these limits with custom routing using [Proxy](/docs/pages/api-reference/file-conventions/proxy) in Next.js 12.
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/lazy-loading.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/lazy-loading.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to lazy load Client Components and libraries
|
||||
nav_title: Lazy Loading
|
||||
description: Lazy load imported libraries and React Components to improve your application's overall loading performance.
|
||||
source: app/guides/lazy-loading
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/mdx.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/mdx.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to use markdown and MDX in Next.js
|
||||
nav_title: MDX
|
||||
description: Learn how to configure MDX to write JSX in your markdown files.
|
||||
source: app/guides/mdx
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/migrating/app-router-migration.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/migrating/app-router-migration.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to migrate from Pages to the App Router
|
||||
nav_title: App Router
|
||||
description: Learn how to upgrade your existing Next.js application from the Pages Router to the App Router.
|
||||
source: app/guides/migrating/app-router-migration
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/migrating/from-create-react-app.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/migrating/from-create-react-app.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to migrate from Create React App to Next.js
|
||||
nav_title: Create React App
|
||||
description: Learn how to migrate your existing React application from Create React App to Next.js.
|
||||
source: app/guides/migrating/from-create-react-app
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/migrating/from-vite.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/migrating/from-vite.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to migrate from Vite to Next.js
|
||||
nav_title: Vite
|
||||
description: Learn how to migrate your existing React application from Vite to Next.js.
|
||||
source: app/guides/migrating/from-vite
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
4
node_modules/next/dist/docs/02-pages/02-guides/migrating/index.md
generated
vendored
Normal file
4
node_modules/next/dist/docs/02-pages/02-guides/migrating/index.md
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: Migrating
|
||||
description: Learn how to migrate from popular frameworks to Next.js
|
||||
---
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/multi-zones.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/multi-zones.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to build micro-frontends using multi-zones and Next.js
|
||||
nav_title: Multi-Zones
|
||||
description: Learn how to build micro-frontends using Next.js Multi-Zones to deploy multiple Next.js apps under a single domain.
|
||||
source: app/guides/multi-zones
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/open-telemetry.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/open-telemetry.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to instrument your Next.js app with OpenTelemetry
|
||||
nav_title: OpenTelemetry
|
||||
description: Learn how to instrument your Next.js app with OpenTelemetry.
|
||||
source: app/guides/open-telemetry
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
12
node_modules/next/dist/docs/02-pages/02-guides/package-bundling.md
generated
vendored
Normal file
12
node_modules/next/dist/docs/02-pages/02-guides/package-bundling.md
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
title: How to optimize package bundling
|
||||
nav_title: Package Bundling
|
||||
description: Learn how to optimize your application's server and client bundles.
|
||||
source: app/guides/package-bundling
|
||||
related:
|
||||
description: Learn more about optimizing your application for production.
|
||||
links:
|
||||
- pages/guides/production-checklist
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
163
node_modules/next/dist/docs/02-pages/02-guides/post-css.md
generated
vendored
Normal file
163
node_modules/next/dist/docs/02-pages/02-guides/post-css.md
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
---
|
||||
title: How to configure PostCSS in Next.js
|
||||
nav_title: PostCSS
|
||||
description: Extend the PostCSS config and plugins added by Next.js with your own.
|
||||
---
|
||||
|
||||
## Default Behavior
|
||||
|
||||
Next.js compiles CSS for its [built-in CSS support](/docs/app/getting-started/css) using PostCSS.
|
||||
|
||||
Out of the box, with no configuration, Next.js compiles CSS with the following transformations:
|
||||
|
||||
- [Autoprefixer](https://github.com/postcss/autoprefixer) automatically adds vendor prefixes to CSS rules (back to IE11).
|
||||
- [Cross-browser Flexbox bugs](https://github.com/philipwalton/flexbugs) are corrected to behave like [the spec](https://www.w3.org/TR/css-flexbox-1/).
|
||||
- New CSS features are automatically compiled for Internet Explorer 11 compatibility:
|
||||
- [`all` Property](https://developer.mozilla.org/docs/Web/CSS/all)
|
||||
- [Break Properties](https://developer.mozilla.org/docs/Web/CSS/break-after)
|
||||
- [`font-variant` Property](https://developer.mozilla.org/docs/Web/CSS/font-variant)
|
||||
- [Gap Properties](https://developer.mozilla.org/docs/Web/CSS/gap)
|
||||
- [Media Query Ranges](https://developer.mozilla.org/docs/Web/CSS/Media_Queries/Using_media_queries#Syntax_improvements_in_Level_4)
|
||||
|
||||
By default, [CSS Grid](https://www.w3.org/TR/css-grid-1/) and [Custom Properties](https://developer.mozilla.org/docs/Web/CSS/var) (CSS variables) are **not compiled** for IE11 support.
|
||||
|
||||
To compile [CSS Grid Layout](https://developer.mozilla.org/docs/Web/CSS/grid) for IE11, you can place the following comment at the top of your CSS file:
|
||||
|
||||
```css
|
||||
/* autoprefixer grid: autoplace */
|
||||
```
|
||||
|
||||
You can also enable IE11 support for [CSS Grid Layout](https://developer.mozilla.org/docs/Web/CSS/grid)
|
||||
in your entire project by configuring autoprefixer with the configuration shown below (collapsed).
|
||||
See ["Customizing Plugins"](#customizing-plugins) below for more information.
|
||||
|
||||
<details>
|
||||
<summary>Click to view the configuration to enable CSS Grid Layout</summary>
|
||||
|
||||
```json filename="postcss.config.json"
|
||||
{
|
||||
"plugins": [
|
||||
"postcss-flexbugs-fixes",
|
||||
[
|
||||
"postcss-preset-env",
|
||||
{
|
||||
"autoprefixer": {
|
||||
"flexbox": "no-2009",
|
||||
"grid": "autoplace"
|
||||
},
|
||||
"stage": 3,
|
||||
"features": {
|
||||
"custom-properties": false
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
CSS variables are not compiled because it is [not possible to safely do so](https://github.com/MadLittleMods/postcss-css-variables#caveats).
|
||||
If you must use variables, consider using something like [Sass variables](https://sass-lang.com/documentation/variables) which are compiled away by [Sass](https://sass-lang.com/).
|
||||
|
||||
## Customizing Target Browsers
|
||||
|
||||
Next.js allows you to configure the target browsers (for [Autoprefixer](https://github.com/postcss/autoprefixer) and compiled css features) through [Browserslist](https://github.com/browserslist/browserslist).
|
||||
|
||||
To customize browserslist, create a `browserslist` key in your `package.json` like so:
|
||||
|
||||
```json filename="package.json"
|
||||
{
|
||||
"browserslist": [">0.3%", "not dead", "not op_mini all"]
|
||||
}
|
||||
```
|
||||
|
||||
You can use the [browsersl.ist](https://browsersl.ist/?q=%3E0.3%25%2C+not+ie+11%2C+not+dead%2C+not+op_mini+all) tool to visualize what browsers you are targeting.
|
||||
|
||||
## CSS Modules
|
||||
|
||||
No configuration is needed to support CSS Modules. To enable CSS Modules for a file, rename the file to have the extension `.module.css`.
|
||||
|
||||
You can learn more about [Next.js' CSS Module support here](/docs/app/getting-started/css).
|
||||
|
||||
## Customizing Plugins
|
||||
|
||||
> **Warning**: When you define a custom PostCSS configuration file, Next.js **completely disables** the [default behavior](#default-behavior).
|
||||
> Be sure to manually configure all the features you need compiled, including [Autoprefixer](https://github.com/postcss/autoprefixer).
|
||||
> You also need to install any plugins included in your custom configuration manually, i.e. `npm install postcss-flexbugs-fixes postcss-preset-env`.
|
||||
|
||||
To customize the PostCSS configuration, create a `postcss.config.json` file in the root of your project.
|
||||
|
||||
This is the default configuration used by Next.js:
|
||||
|
||||
```json filename="postcss.config.json"
|
||||
{
|
||||
"plugins": [
|
||||
"postcss-flexbugs-fixes",
|
||||
[
|
||||
"postcss-preset-env",
|
||||
{
|
||||
"autoprefixer": {
|
||||
"flexbox": "no-2009"
|
||||
},
|
||||
"stage": 3,
|
||||
"features": {
|
||||
"custom-properties": false
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
> **Good to know**: Next.js also allows the file to be named `.postcssrc.json`, or, to be read from the `postcss` key in `package.json`.
|
||||
|
||||
It is also possible to configure PostCSS with a `postcss.config.js` file, which is useful when you want to conditionally include plugins based on environment:
|
||||
|
||||
```js filename="postcss.config.js"
|
||||
module.exports = {
|
||||
plugins:
|
||||
process.env.NODE_ENV === 'production'
|
||||
? [
|
||||
'postcss-flexbugs-fixes',
|
||||
[
|
||||
'postcss-preset-env',
|
||||
{
|
||||
autoprefixer: {
|
||||
flexbox: 'no-2009',
|
||||
},
|
||||
stage: 3,
|
||||
features: {
|
||||
'custom-properties': false,
|
||||
},
|
||||
},
|
||||
],
|
||||
]
|
||||
: [
|
||||
// No transformations in development
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
> **Good to know**: Next.js also allows the file to be named `.postcssrc.js`.
|
||||
|
||||
Do **not use `require()`** to import the PostCSS Plugins. Plugins must be provided as strings.
|
||||
|
||||
> **Good to know**: If your `postcss.config.js` needs to support other non-Next.js tools in the same project, you must use the interoperable object-based format instead:
|
||||
>
|
||||
> ```js
|
||||
> module.exports = {
|
||||
> plugins: {
|
||||
> 'postcss-flexbugs-fixes': {},
|
||||
> 'postcss-preset-env': {
|
||||
> autoprefixer: {
|
||||
> flexbox: 'no-2009',
|
||||
> },
|
||||
> stage: 3,
|
||||
> features: {
|
||||
> 'custom-properties': false,
|
||||
> },
|
||||
> },
|
||||
> },
|
||||
> }
|
||||
> ```
|
||||
252
node_modules/next/dist/docs/02-pages/02-guides/preview-mode.md
generated
vendored
Normal file
252
node_modules/next/dist/docs/02-pages/02-guides/preview-mode.md
generated
vendored
Normal file
@@ -0,0 +1,252 @@
|
||||
---
|
||||
title: How to preview content with Preview Mode in Next.js
|
||||
nav_title: Preview Mode
|
||||
description: Next.js has the preview mode for statically generated pages. You can learn how it works here.
|
||||
version: legacy
|
||||
---
|
||||
|
||||
> **Note**: This feature is superseded by [Draft Mode](/docs/pages/guides/draft-mode).
|
||||
|
||||
<details>
|
||||
<summary>Examples</summary>
|
||||
|
||||
- [Agility CMS Example](https://github.com/vercel/next.js/tree/canary/examples/cms-agilitycms) ([Demo](https://next-blog-agilitycms.vercel.app/))
|
||||
- [Builder.io Example](https://github.com/vercel/next.js/tree/canary/examples/cms-builder-io) ([Demo](https://cms-builder-io.vercel.app/))
|
||||
- [ButterCMS Example](https://github.com/vercel/next.js/tree/canary/examples/cms-buttercms) ([Demo](https://next-blog-buttercms.vercel.app/))
|
||||
- [Contentful Example](https://github.com/vercel/next.js/tree/canary/examples/cms-contentful) ([Demo](https://app-router-contentful.vercel.app/))
|
||||
- [Cosmic Example](https://github.com/vercel/next.js/tree/canary/examples/cms-cosmic) ([Demo](https://next-blog-cosmic.vercel.app/))
|
||||
- [DatoCMS Example](https://github.com/vercel/next.js/tree/canary/examples/cms-datocms) ([Demo](https://next-blog-datocms.vercel.app/))
|
||||
- [DotCMS Example](https://github.com/vercel/next.js/tree/canary/examples/cms-dotcms) ([Demo](https://nextjs-dotcms-blog.vercel.app/))
|
||||
- [Drupal Example](https://github.com/vercel/next.js/tree/canary/examples/cms-drupal) ([Demo](https://cms-drupal.vercel.app/))
|
||||
- [Enterspeed Example](https://github.com/vercel/next.js/tree/canary/examples/cms-enterspeed) ([Demo](https://next-blog-demo.enterspeed.com/))
|
||||
- [GraphCMS Example](https://github.com/vercel/next.js/tree/canary/examples/cms-graphcms) ([Demo](https://next-blog-graphcms.vercel.app/))
|
||||
- [Keystone Example](https://github.com/vercel/next.js/tree/canary/examples/cms-keystonejs-embedded) ([Demo](https://nextjs-keystone-demo.vercel.app/))
|
||||
- [Kontent.ai Example](https://github.com/vercel/next.js/tree/canary/examples/cms-kontent-ai) ([Demo](https://next-blog-kontent-ai.vercel.app/))
|
||||
- [Makeswift Example](https://github.com/vercel/next.js/tree/canary/examples/cms-makeswift) ([Demo](https://nextjs-makeswift-example.vercel.app/))
|
||||
- [Plasmic Example](https://github.com/vercel/next.js/tree/canary/examples/cms-plasmic) ([Demo](https://nextjs-plasmic-example.vercel.app/))
|
||||
- [Prepr Example](https://github.com/vercel/next.js/tree/canary/examples/cms-prepr) ([Demo](https://next-blog-prepr.vercel.app/))
|
||||
- [Prismic Example](https://github.com/vercel/next.js/tree/canary/examples/cms-prismic) ([Demo](https://next-blog-prismic.vercel.app/))
|
||||
- [Sanity Example](https://github.com/vercel/next.js/tree/canary/examples/cms-sanity) ([Demo](https://next-blog.sanity.build/))
|
||||
- [Sitecore XM Cloud Example](https://github.com/vercel/next.js/tree/canary/examples/cms-sitecore-xmcloud) ([Demo](https://vercel-sitecore-xmcloud-demo.vercel.app/))
|
||||
- [Storyblok Example](https://github.com/vercel/next.js/tree/canary/examples/cms-storyblok) ([Demo](https://next-blog-storyblok.vercel.app/))
|
||||
- [Strapi Example](https://github.com/vercel/next.js/tree/canary/examples/cms-strapi) ([Demo](https://next-blog-strapi.vercel.app/))
|
||||
- [TakeShape Example](https://github.com/vercel/next.js/tree/canary/examples/cms-takeshape) ([Demo](https://next-blog-takeshape.vercel.app/))
|
||||
- [Tina Example](https://github.com/vercel/next.js/tree/canary/examples/cms-tina) ([Demo](https://cms-tina-example.vercel.app/))
|
||||
- [Umbraco Example](https://github.com/vercel/next.js/tree/canary/examples/cms-umbraco) ([Demo](https://nextjs-umbraco-sample-blog.vercel.app/))
|
||||
- [Umbraco Heartcore Example](https://github.com/vercel/next.js/tree/canary/examples/cms-umbraco-heartcore) ([Demo](https://next-blog-umbraco-heartcore.vercel.app/))
|
||||
- [Webiny Example](https://github.com/vercel/next.js/tree/canary/examples/cms-webiny) ([Demo](https://webiny-headlesscms-nextjs-example.vercel.app/))
|
||||
- [WordPress Example](https://github.com/vercel/next.js/tree/canary/examples/cms-wordpress) ([Demo](https://next-blog-wordpress.vercel.app/))
|
||||
- [Blog Starter Example](https://github.com/vercel/next.js/tree/canary/examples/blog-starter) ([Demo](https://next-blog-starter.vercel.app/))
|
||||
|
||||
</details>
|
||||
|
||||
In the [Pages documentation](/docs/pages/building-your-application/routing/pages-and-layouts) and the [Data Fetching documentation](/docs/pages/building-your-application/data-fetching), we talked about how to prerender a page at build time (**Static Generation**) using `getStaticProps` and `getStaticPaths`.
|
||||
|
||||
Static Generation is useful when your pages fetch data from a headless CMS. However, it’s not ideal when you’re writing a draft on your headless CMS and want to **preview** the draft immediately on your page. You’d want Next.js to render these pages at **request time** instead of build time and fetch the draft content instead of the published content. You’d want Next.js to bypass Static Generation only for this specific case.
|
||||
|
||||
Next.js has a feature called **Preview Mode** which solves this problem. Here are instructions on how to use it.
|
||||
|
||||
## Step 1: Create and access a preview API route
|
||||
|
||||
> Take a look at the [API Routes documentation](/docs/pages/building-your-application/routing/api-routes) first if you’re not familiar with Next.js API Routes.
|
||||
|
||||
First, create a **preview API route**. It can have any name - e.g. `pages/api/preview.js` (or `.ts` if using TypeScript).
|
||||
|
||||
In this API route, you need to call `setPreviewData` on the response object. The argument for `setPreviewData` should be an object, and this can be used by `getStaticProps` (more on this later). For now, we’ll use `{}`.
|
||||
|
||||
```js
|
||||
export default function handler(req, res) {
|
||||
// ...
|
||||
res.setPreviewData({})
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
`res.setPreviewData` sets some **cookies** on the browser which turns on the preview mode. Any requests to Next.js containing these cookies will be considered as the **preview mode**, and the behavior for statically generated pages will change (more on this later).
|
||||
|
||||
You can test this manually by creating an API route like below and accessing it from your browser manually:
|
||||
|
||||
```js filename="pages/api/preview.js"
|
||||
// simple example for testing it manually from your browser.
|
||||
export default function handler(req, res) {
|
||||
res.setPreviewData({})
|
||||
res.end('Preview mode enabled')
|
||||
}
|
||||
```
|
||||
|
||||
If you open your browser’s developer tools and visit `/api/preview`, you’ll notice that the `__prerender_bypass` and `__next_preview_data` cookies will be set on this request.
|
||||
|
||||
### Securely accessing it from your Headless CMS
|
||||
|
||||
In practice, you’d want to call this API route _securely_ from your headless CMS. The specific steps will vary depending on which headless CMS you’re using, but here are some common steps you could take.
|
||||
|
||||
These steps assume that the headless CMS you’re using supports setting **custom preview URLs**. If it doesn’t, you can still use this method to secure your preview URLs, but you’ll need to construct and access the preview URL manually.
|
||||
|
||||
**First**, you should create a **secret token string** using a token generator of your choice. This secret will only be known by your Next.js app and your headless CMS. This secret prevents people who don’t have access to your CMS from accessing preview URLs.
|
||||
|
||||
**Second**, if your headless CMS supports setting custom preview URLs, specify the following as the preview URL. This assumes that your preview API route is located at `pages/api/preview.js`.
|
||||
|
||||
```bash filename="Terminal"
|
||||
https://<your-site>/api/preview?secret=<token>&slug=<path>
|
||||
```
|
||||
|
||||
- `<your-site>` should be your deployment domain.
|
||||
- `<token>` should be replaced with the secret token you generated.
|
||||
- `<path>` should be the path for the page that you want to preview. If you want to preview `/posts/foo`, then you should use `&slug=/posts/foo`.
|
||||
|
||||
Your headless CMS might allow you to include a variable in the preview URL so that `<path>` can be set dynamically based on the CMS’s data like so: `&slug=/posts/{entry.fields.slug}`
|
||||
|
||||
**Finally**, in the preview API route:
|
||||
|
||||
- Check that the secret matches and that the `slug` parameter exists (if not, the request should fail).
|
||||
-
|
||||
- Call `res.setPreviewData`.
|
||||
- Then redirect the browser to the path specified by `slug`. (The following example uses a [307 redirect](https://developer.mozilla.org/docs/Web/HTTP/Status/307)).
|
||||
|
||||
```js
|
||||
export default async (req, res) => {
|
||||
// Check the secret and next parameters
|
||||
// This secret should only be known to this API route and the CMS
|
||||
if (req.query.secret !== 'MY_SECRET_TOKEN' || !req.query.slug) {
|
||||
return res.status(401).json({ message: 'Invalid token' })
|
||||
}
|
||||
|
||||
// Fetch the headless CMS to check if the provided `slug` exists
|
||||
// getPostBySlug would implement the required fetching logic to the headless CMS
|
||||
const post = await getPostBySlug(req.query.slug)
|
||||
|
||||
// If the slug doesn't exist prevent preview mode from being enabled
|
||||
if (!post) {
|
||||
return res.status(401).json({ message: 'Invalid slug' })
|
||||
}
|
||||
|
||||
// Enable Preview Mode by setting the cookies
|
||||
res.setPreviewData({})
|
||||
|
||||
// Redirect to the path from the fetched post
|
||||
// We don't redirect to req.query.slug as that might lead to open redirect vulnerabilities
|
||||
res.redirect(post.slug)
|
||||
}
|
||||
```
|
||||
|
||||
If it succeeds, then the browser will be redirected to the path you want to preview with the preview mode cookies being set.
|
||||
|
||||
## Step 2: Update `getStaticProps`
|
||||
|
||||
The next step is to update `getStaticProps` to support the preview mode.
|
||||
|
||||
If you request a page which has `getStaticProps` with the preview mode cookies set (via `res.setPreviewData`), then `getStaticProps` will be called at **request time** (instead of at build time).
|
||||
|
||||
Furthermore, it will be called with a `context` object where:
|
||||
|
||||
- `context.preview` will be `true`.
|
||||
- `context.previewData` will be the same as the argument used for `setPreviewData`.
|
||||
|
||||
```js
|
||||
export async function getStaticProps(context) {
|
||||
// If you request this page with the preview mode cookies set:
|
||||
//
|
||||
// - context.preview will be true
|
||||
// - context.previewData will be the same as
|
||||
// the argument used for `setPreviewData`.
|
||||
}
|
||||
```
|
||||
|
||||
We used `res.setPreviewData({})` in the preview API route, so `context.previewData` will be `{}`. You can use this to pass session information from the preview API route to `getStaticProps` if necessary.
|
||||
|
||||
If you’re also using `getStaticPaths`, then `context.params` will also be available.
|
||||
|
||||
### Fetch preview data
|
||||
|
||||
You can update `getStaticProps` to fetch different data based on `context.preview` and/or `context.previewData`.
|
||||
|
||||
For example, your headless CMS might have a different API endpoint for draft posts. If so, you can use `context.preview` to modify the API endpoint URL like below:
|
||||
|
||||
```js
|
||||
export async function getStaticProps(context) {
|
||||
// If context.preview is true, append "/preview" to the API endpoint
|
||||
// to request draft data instead of published data. This will vary
|
||||
// based on which headless CMS you're using.
|
||||
const res = await fetch(`https://.../${context.preview ? 'preview' : ''}`)
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
That’s it! If you access the preview API route (with `secret` and `slug`) from your headless CMS or manually, you should now be able to see the preview content. And if you update your draft without publishing, you should be able to preview the draft.
|
||||
|
||||
Set this as the preview URL on your headless CMS or access manually, and you should be able to see the preview.
|
||||
|
||||
```bash filename="Terminal"
|
||||
https://<your-site>/api/preview?secret=<token>&slug=<path>
|
||||
```
|
||||
|
||||
## More Details
|
||||
|
||||
> **Good to know**: during rendering `next/router` exposes an `isPreview` flag, see the [router object docs](/docs/pages/api-reference/functions/use-router#router-object) for more info.
|
||||
|
||||
### Specify the Preview Mode duration
|
||||
|
||||
`setPreviewData` takes an optional second parameter which should be an options object. It accepts the following keys:
|
||||
|
||||
- `maxAge`: Specifies the number (in seconds) for the preview session to last for.
|
||||
- `path`: Specifies the path the cookie should be applied under. Defaults to `/` enabling preview mode for all paths.
|
||||
|
||||
```js
|
||||
setPreviewData(data, {
|
||||
maxAge: 60 * 60, // The preview mode cookies expire in 1 hour
|
||||
path: '/about', // The preview mode cookies apply to paths with /about
|
||||
})
|
||||
```
|
||||
|
||||
### Clear the Preview Mode cookies
|
||||
|
||||
By default, no expiration date is set for Preview Mode cookies, so the preview session ends when the browser is closed.
|
||||
|
||||
To clear the Preview Mode cookies manually, create an API route that calls `clearPreviewData()`:
|
||||
|
||||
```js filename="pages/api/clear-preview-mode-cookies.js"
|
||||
export default function handler(req, res) {
|
||||
res.clearPreviewData({})
|
||||
}
|
||||
```
|
||||
|
||||
Then, send a request to `/api/clear-preview-mode-cookies` to invoke the API Route. If calling this route using [`next/link`](/docs/pages/api-reference/components/link), you must pass `prefetch={false}` to prevent calling `clearPreviewData` during link prefetching.
|
||||
|
||||
If a path was specified in the `setPreviewData` call, you must pass the same path to `clearPreviewData`:
|
||||
|
||||
```js filename="pages/api/clear-preview-mode-cookies.js"
|
||||
export default function handler(req, res) {
|
||||
const { path } = req.query
|
||||
|
||||
res.clearPreviewData({ path })
|
||||
}
|
||||
```
|
||||
|
||||
### `previewData` size limits
|
||||
|
||||
You can pass an object to `setPreviewData` and have it be available in `getStaticProps`. However, because the data will be stored in a cookie, there’s a size limitation. Currently, preview data is limited to 2KB.
|
||||
|
||||
### Works with `getServerSideProps`
|
||||
|
||||
The preview mode works on `getServerSideProps` as well. It will also be available on the `context` object containing `preview` and `previewData`.
|
||||
|
||||
> **Good to know**: You shouldn't set the `Cache-Control` header when using Preview Mode because it cannot be bypassed. Instead, we recommend using [ISR](/docs/pages/guides/incremental-static-regeneration).
|
||||
|
||||
### Works with API Routes
|
||||
|
||||
API Routes will have access to `preview` and `previewData` under the request object. For example:
|
||||
|
||||
```js
|
||||
export default function myApiRoute(req, res) {
|
||||
const isPreview = req.preview
|
||||
const previewData = req.previewData
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Unique per `next build`
|
||||
|
||||
Both the bypass cookie value and the private key for encrypting the `previewData` change when `next build` is completed.
|
||||
This ensures that the bypass cookie can’t be guessed.
|
||||
|
||||
> **Good to know**: To test Preview Mode locally over HTTP your browser will need to allow third-party cookies and local storage access.
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/production-checklist.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/production-checklist.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to optimize your Next.js application for production
|
||||
nav_title: Production
|
||||
description: Recommendations to ensure the best performance and user experience before taking your Next.js application to production.
|
||||
source: app/guides/production-checklist
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/redirecting.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/redirecting.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to handle redirects in Next.js
|
||||
nav_title: Redirecting
|
||||
description: Learn the different ways to handle redirects in Next.js.
|
||||
source: app/guides/redirecting
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/sass.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/sass.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to use Sass in Next.js
|
||||
nav_title: Sass
|
||||
description: Learn how to use Sass in your Next.js application.
|
||||
source: app/guides/sass
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/scripts.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/scripts.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to load and optimize scripts
|
||||
nav_title: Scripts
|
||||
description: Optimize 3rd party scripts with the built-in Script component.
|
||||
source: app/guides/scripts
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/self-hosting.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/self-hosting.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to self-host your Next.js application
|
||||
nav_title: Self-Hosting
|
||||
description: Learn how to self-host your Next.js application on a Node.js server, Docker image, or static HTML files (static exports).
|
||||
source: app/guides/self-hosting
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/static-exports.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/static-exports.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to create a static export of your Next.js application
|
||||
nav_title: Static Exports
|
||||
description: Next.js enables starting as a static site or Single-Page Application (SPA), then later optionally upgrading to use features that require a server.
|
||||
source: app/guides/static-exports
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
7
node_modules/next/dist/docs/02-pages/02-guides/tailwind-v3-css.md
generated
vendored
Normal file
7
node_modules/next/dist/docs/02-pages/02-guides/tailwind-v3-css.md
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Tailwind CSS
|
||||
description: Style your Next.js Application using Tailwind CSS.
|
||||
source: app/guides/tailwind-v3-css
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/testing/cypress.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/testing/cypress.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to set up Cypress with Next.js
|
||||
nav_title: Cypress
|
||||
description: Learn how to set up Next.js with Cypress for End-to-End (E2E) and Component Testing.
|
||||
source: app/guides/testing/cypress
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
7
node_modules/next/dist/docs/02-pages/02-guides/testing/index.md
generated
vendored
Normal file
7
node_modules/next/dist/docs/02-pages/02-guides/testing/index.md
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Testing
|
||||
description: Learn how to set up Next.js with three commonly used testing tools — Cypress, Playwright, Vitest, and Jest.
|
||||
source: app/guides/testing
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/testing/jest.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/testing/jest.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to set up Jest with Next.js
|
||||
nav_title: Jest
|
||||
description: Learn how to set up Next.js with Jest for Unit Testing.
|
||||
source: app/guides/testing/jest
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/testing/playwright.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/testing/playwright.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to set up Playwright with Next.js
|
||||
nav_title: Playwright
|
||||
description: Learn how to set up Next.js with Playwright for End-to-End (E2E) and Integration testing.
|
||||
source: app/guides/testing/playwright
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/testing/vitest.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/testing/vitest.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to set up Vitest with Next.js
|
||||
nav_title: Vitest
|
||||
description: Learn how to set up Next.js with Vitest and React Testing Library - two popular unit testing libraries.
|
||||
source: app/guides/testing/vitest
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/third-party-libraries.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/third-party-libraries.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to optimize third-party libraries
|
||||
nav_title: Third Party Libraries
|
||||
description: Optimize the performance of third-party libraries in your application with the `@next/third-parties` package.
|
||||
source: app/guides/third-party-libraries
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
7
node_modules/next/dist/docs/02-pages/02-guides/upgrading/codemods.md
generated
vendored
Normal file
7
node_modules/next/dist/docs/02-pages/02-guides/upgrading/codemods.md
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Codemods
|
||||
description: Use codemods to upgrade your Next.js codebase when new features are released.
|
||||
source: app/guides/upgrading/codemods
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
6
node_modules/next/dist/docs/02-pages/02-guides/upgrading/index.md
generated
vendored
Normal file
6
node_modules/next/dist/docs/02-pages/02-guides/upgrading/index.md
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
title: Upgrading
|
||||
description: Learn how to upgrade to the latest versions of Next.js.
|
||||
---
|
||||
|
||||
Learn how to upgrade to the latest versions of Next.js following the versions-specific guides:
|
||||
27
node_modules/next/dist/docs/02-pages/02-guides/upgrading/version-10.md
generated
vendored
Normal file
27
node_modules/next/dist/docs/02-pages/02-guides/upgrading/version-10.md
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
title: How to upgrade to version 10
|
||||
nav_title: Version 10
|
||||
description: Upgrade your Next.js Application from Version 9 to Version 10.
|
||||
---
|
||||
|
||||
There were no breaking changes between versions 9 and 10.
|
||||
|
||||
To upgrade to version 10, run the following command:
|
||||
|
||||
```bash filename="Terminal"
|
||||
npm i next@10
|
||||
```
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn add next@10
|
||||
```
|
||||
|
||||
```bash filename="Terminal"
|
||||
pnpm up next@10
|
||||
```
|
||||
|
||||
```bash filename="Terminal"
|
||||
bun add next@10
|
||||
```
|
||||
|
||||
> **Good to know:** If you are using TypeScript, ensure you also upgrade `@types/react` and `@types/react-dom` to their corresponding versions.
|
||||
150
node_modules/next/dist/docs/02-pages/02-guides/upgrading/version-11.md
generated
vendored
Normal file
150
node_modules/next/dist/docs/02-pages/02-guides/upgrading/version-11.md
generated
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
---
|
||||
title: How to upgrade to version 11
|
||||
nav_title: Version 11
|
||||
description: Upgrade your Next.js Application from Version 10 to Version 11.
|
||||
---
|
||||
|
||||
To upgrade to version 11, run the following command:
|
||||
|
||||
```bash filename="Terminal"
|
||||
npm i next@11 react@17 react-dom@17
|
||||
```
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn add next@11 react@17 react-dom@17
|
||||
```
|
||||
|
||||
```bash filename="Terminal"
|
||||
pnpm up next@11 react@17 react-dom@17
|
||||
```
|
||||
|
||||
```bash filename="Terminal"
|
||||
bun add next@11 react@17 react-dom@17
|
||||
```
|
||||
|
||||
> **Good to know:** If you are using TypeScript, ensure you also upgrade `@types/react` and `@types/react-dom` to their corresponding versions.
|
||||
|
||||
### Webpack 5
|
||||
|
||||
Webpack 5 is now the default for all Next.js applications. If you did not have a custom webpack configuration, your application is already using webpack 5. If you do have a custom webpack configuration, you can refer to the [Next.js webpack 5 documentation](/docs/messages/webpack5) for upgrade guidance.
|
||||
|
||||
### Cleaning the `distDir` is now a default
|
||||
|
||||
The build output directory (defaults to `.next`) is now cleared by default except for the Next.js caches. You can refer to [the cleaning `distDir` RFC](https://github.com/vercel/next.js/discussions/6009) for more information.
|
||||
|
||||
If your application was relying on this behavior previously you can disable the new default behavior by adding the `cleanDistDir: false` flag in `next.config.js`.
|
||||
|
||||
### `PORT` is now supported for `next dev` and `next start`
|
||||
|
||||
Next.js 11 supports the `PORT` environment variable to set the port the application runs on. Using `-p`/`--port` is still recommended but if you were prohibited from using `-p` in any way you can now use `PORT` as an alternative:
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
PORT=4000 next start
|
||||
```
|
||||
|
||||
### `next.config.js` customization to import images
|
||||
|
||||
Next.js 11 supports static image imports with `next/image`. This new feature relies on being able to process image imports. If you previously added the `next-images` or `next-optimized-images` packages you can either move to the new built-in support using `next/image` or disable the feature:
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
images: {
|
||||
disableStaticImages: true,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Remove `super.componentDidCatch()` from `pages/_app.js`
|
||||
|
||||
The `next/app` component's `componentDidCatch` was deprecated in Next.js 9 as it's no longer needed and has since been a no-op. In Next.js 11, it was removed.
|
||||
|
||||
If your `pages/_app.js` has a custom `componentDidCatch` method you can remove `super.componentDidCatch` as it is no longer needed.
|
||||
|
||||
### Remove `Container` from `pages/_app.js`
|
||||
|
||||
This export was deprecated in Next.js 9 as it's no longer needed and has since been a no-op with a warning during development. In Next.js 11 it was removed.
|
||||
|
||||
If your `pages/_app.js` imports `Container` from `next/app` you can remove `Container` as it was removed. Learn more in [the documentation](/docs/messages/app-container-deprecated).
|
||||
|
||||
### Remove `props.url` usage from page components
|
||||
|
||||
This property was deprecated in Next.js 4 and has since shown a warning during development. With the introduction of `getStaticProps` / `getServerSideProps` these methods already disallowed the usage of `props.url`. In Next.js 11, it was removed completely.
|
||||
|
||||
You can learn more in [the documentation](/docs/messages/url-deprecated).
|
||||
|
||||
### Remove `unsized` property on `next/image`
|
||||
|
||||
The `unsized` property on `next/image` was deprecated in Next.js 10.0.1. You can use `layout="fill"` instead. In Next.js 11 `unsized` was removed.
|
||||
|
||||
### Remove `modules` property on `next/dynamic`
|
||||
|
||||
The `modules` and `render` option for `next/dynamic` were deprecated in Next.js 9.5. This was done in order to make the `next/dynamic` API closer to `React.lazy`. In Next.js 11, the `modules` and `render` options were removed.
|
||||
|
||||
This option hasn't been mentioned in the documentation since Next.js 8 so it's less likely that your application is using it.
|
||||
|
||||
If your application does use `modules` and `render` you can refer to [the documentation](/docs/messages/next-dynamic-modules).
|
||||
|
||||
### Remove `Head.rewind`
|
||||
|
||||
`Head.rewind` has been a no-op since Next.js 9.5, in Next.js 11 it was removed. You can safely remove your usage of `Head.rewind`.
|
||||
|
||||
### Moment.js locales excluded by default
|
||||
|
||||
Moment.js includes translations for a lot of locales by default. Next.js now automatically excludes these locales by default to optimize bundle size for applications using Moment.js.
|
||||
|
||||
To load a specific locale use this snippet:
|
||||
|
||||
```js
|
||||
import moment from 'moment'
|
||||
import 'moment/locale/ja'
|
||||
|
||||
moment.locale('ja')
|
||||
```
|
||||
|
||||
You can opt-out of this new default by adding `excludeDefaultMomentLocales: false` to `next.config.js` if you do not want the new behavior, do note it's highly recommended to not disable this new optimization as it significantly reduces the size of Moment.js.
|
||||
|
||||
### Update usage of `router.events`
|
||||
|
||||
In case you're accessing `router.events` during rendering, in Next.js 11 `router.events` is no longer provided during prerendering. Ensure you're accessing `router.events` in `useEffect`:
|
||||
|
||||
```js
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url, { shallow }) => {
|
||||
console.log(
|
||||
`App is changing to ${url} ${
|
||||
shallow ? 'with' : 'without'
|
||||
} shallow routing`
|
||||
)
|
||||
}
|
||||
|
||||
router.events.on('routeChangeStart', handleRouteChange)
|
||||
|
||||
// If the component is unmounted, unsubscribe
|
||||
// from the event with the `off` method:
|
||||
return () => {
|
||||
router.events.off('routeChangeStart', handleRouteChange)
|
||||
}
|
||||
}, [router])
|
||||
```
|
||||
|
||||
If your application uses `router.router.events` which was an internal property that was not public please make sure to use `router.events` as well.
|
||||
|
||||
## React 16 to 17
|
||||
|
||||
React 17 introduced a new [JSX Transform](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html) that brings a long-time Next.js feature to the wider React ecosystem: Not having to `import React from 'react'` when using JSX. When using React 17 Next.js will automatically use the new transform. This transform does not make the `React` variable global, which was an unintended side-effect of the previous Next.js implementation. A [codemod is available](/docs/pages/guides/upgrading/codemods#add-missing-react-import) to automatically fix cases where you accidentally used `React` without importing it.
|
||||
|
||||
Most applications already use the latest version of React, with Next.js 11 the minimum React version has been updated to 17.0.2.
|
||||
|
||||
To upgrade you can run the following command:
|
||||
|
||||
```
|
||||
npm install react@latest react-dom@latest
|
||||
```
|
||||
|
||||
Or using `yarn`:
|
||||
|
||||
```
|
||||
yarn add react@latest react-dom@latest
|
||||
```
|
||||
153
node_modules/next/dist/docs/02-pages/02-guides/upgrading/version-12.md
generated
vendored
Normal file
153
node_modules/next/dist/docs/02-pages/02-guides/upgrading/version-12.md
generated
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
---
|
||||
title: How to upgrade to version 12
|
||||
nav_title: Version 12
|
||||
description: Upgrade your Next.js Application from Version 11 to Version 12.
|
||||
---
|
||||
|
||||
To upgrade to version 12, run the following command:
|
||||
|
||||
```bash filename="Terminal"
|
||||
npm i next@12 react@17 react-dom@17 eslint-config-next@12
|
||||
```
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn add next@12 react@17 react-dom@17 eslint-config-next@12
|
||||
```
|
||||
|
||||
```bash filename="Terminal"
|
||||
pnpm up next@12 react@17 react-dom@17 eslint-config-next@12
|
||||
```
|
||||
|
||||
```bash filename="Terminal"
|
||||
bun add next@12 react@17 react-dom@17 eslint-config-next@12
|
||||
```
|
||||
|
||||
> **Good to know:** If you are using TypeScript, ensure you also upgrade `@types/react` and `@types/react-dom` to their corresponding versions.
|
||||
|
||||
### Upgrading to 12.2
|
||||
|
||||
[Middleware](/docs/messages/middleware-upgrade-guide) - If you were using Middleware prior to `12.2`, please see the [upgrade guide](/docs/messages/middleware-upgrade-guide) for more information.
|
||||
|
||||
### Upgrading to 12.0
|
||||
|
||||
[Minimum Node.js Version](https://nodejs.org/en/) - The minimum Node.js version has been bumped from `12.0.0` to `12.22.0` which is the first version of Node.js with native ES Modules support.
|
||||
|
||||
[Minimum React Version](https://react.dev/learn/add-react-to-an-existing-project) - The minimum required React version is `17.0.2`. To upgrade you can run the following command in the terminal:
|
||||
|
||||
```bash filename="Terminal"
|
||||
npm install react@latest react-dom@latest
|
||||
|
||||
yarn add react@latest react-dom@latest
|
||||
|
||||
pnpm update react@latest react-dom@latest
|
||||
|
||||
bun add react@latest react-dom@latest
|
||||
```
|
||||
|
||||
#### SWC replacing Babel
|
||||
|
||||
Next.js now uses the Rust-based compiler [SWC](https://swc.rs/) to compile JavaScript/TypeScript. This new compiler is up to 17x faster than Babel when compiling individual files and up to 5x faster Fast Refresh.
|
||||
|
||||
Next.js provides full backward compatibility with applications that have [custom Babel configuration](/docs/pages/guides/babel). All transformations that Next.js handles by default like styled-jsx and tree-shaking of `getStaticProps` / `getStaticPaths` / `getServerSideProps` have been ported to Rust.
|
||||
|
||||
When an application has a custom Babel configuration, Next.js will automatically opt-out of using SWC for compiling JavaScript/Typescript and will fall back to using Babel in the same way that it was used in Next.js 11.
|
||||
|
||||
Many of the integrations with external libraries that currently require custom Babel transformations will be ported to Rust-based SWC transforms in the near future. These include but are not limited to:
|
||||
|
||||
- Styled Components
|
||||
- Emotion
|
||||
- Relay
|
||||
|
||||
In order to prioritize transforms that will help you adopt SWC, please provide your `.babelrc` on [this feedback thread](https://github.com/vercel/next.js/discussions/30174).
|
||||
|
||||
#### SWC replacing Terser for minification
|
||||
|
||||
You can opt-in to replacing Terser with SWC for minifying JavaScript up to 7x faster using a flag in `next.config.js`:
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
swcMinify: true,
|
||||
}
|
||||
```
|
||||
|
||||
Minification using SWC is an opt-in flag to ensure it can be tested against more real-world Next.js applications before it becomes the default in Next.js 12.1. If you have feedback about minification, please leave it on [this feedback thread](https://github.com/vercel/next.js/discussions/30237).
|
||||
|
||||
#### Improvements to styled-jsx CSS parsing
|
||||
|
||||
On top of the Rust-based compiler we've implemented a new CSS parser based on the one used for the styled-jsx Babel transform. This new parser has improved handling of CSS and now errors when invalid CSS is used that would previously slip through and cause unexpected behavior.
|
||||
|
||||
Because of this change invalid CSS will throw an error during development and `next build`. This change only affects styled-jsx usage.
|
||||
|
||||
#### `next/image` changed wrapping element
|
||||
|
||||
`next/image` now renders the `<img>` inside a `<span>` instead of `<div>`.
|
||||
|
||||
If your application has specific CSS targeting span such as `.container span`, upgrading to Next.js 12 might incorrectly match the wrapping element inside the `<Image>` component. You can avoid this by restricting the selector to a specific class such as `.container span.item` and updating the relevant component with that className, such as `<span className="item" />`.
|
||||
|
||||
If your application has specific CSS targeting the `next/image` `<div>` tag, for example `.container div`, it may not match anymore. You can update the selector `.container span`, or preferably, add a new `<div className="wrapper">` wrapping the `<Image>` component and target that instead such as `.container .wrapper`.
|
||||
|
||||
The `className` prop is unchanged and will still be passed to the underlying `<img>` element.
|
||||
|
||||
See the [documentation](/docs/pages/api-reference/components/image#styling-images) for more info.
|
||||
|
||||
#### HMR connection now uses a WebSocket
|
||||
|
||||
Previously, Next.js used a [server-sent events](https://developer.mozilla.org/docs/Web/API/Server-sent_events) connection to receive HMR events. Next.js 12 now uses a WebSocket connection.
|
||||
|
||||
In some cases when proxying requests to the Next.js dev server, you will need to ensure the upgrade request is handled correctly. For example, in `nginx` you would need to add the following configuration:
|
||||
|
||||
```nginx
|
||||
location /_next/webpack-hmr {
|
||||
proxy_pass http://localhost:3000/_next/webpack-hmr;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
}
|
||||
```
|
||||
|
||||
If you are using Apache (2.x), you can add the following configuration to enable web sockets to the server. Review the port, host name and server names.
|
||||
|
||||
```
|
||||
<VirtualHost *:443>
|
||||
# ServerName yourwebsite.local
|
||||
ServerName "${WEBSITE_SERVER_NAME}"
|
||||
ProxyPass / http://localhost:3000/
|
||||
ProxyPassReverse / http://localhost:3000/
|
||||
# Next.js 12 uses websocket
|
||||
<Location /_next/webpack-hmr>
|
||||
RewriteEngine On
|
||||
RewriteCond %{QUERY_STRING} transport=websocket [NC]
|
||||
RewriteCond %{HTTP:Upgrade} websocket [NC]
|
||||
RewriteCond %{HTTP:Connection} upgrade [NC]
|
||||
RewriteRule /(.*) ws://localhost:3000/_next/webpack-hmr/$1 [P,L]
|
||||
ProxyPass ws://localhost:3000/_next/webpack-hmr retry=0 timeout=30
|
||||
ProxyPassReverse ws://localhost:3000/_next/webpack-hmr
|
||||
</Location>
|
||||
</VirtualHost>
|
||||
```
|
||||
|
||||
For custom servers, such as `express`, you may need to use `app.all` to ensure the request is passed correctly, for example:
|
||||
|
||||
```js
|
||||
app.all('/_next/webpack-hmr', (req, res) => {
|
||||
nextjsRequestHandler(req, res)
|
||||
})
|
||||
```
|
||||
|
||||
#### Webpack 4 support has been removed
|
||||
|
||||
If you are already using webpack 5 you can skip this section.
|
||||
|
||||
Next.js has adopted webpack 5 as the default for compilation in Next.js 11. As communicated in the [webpack 5 upgrading documentation](/docs/messages/webpack5) Next.js 12 removes support for webpack 4.
|
||||
|
||||
If your application is still using webpack 4 using the opt-out flag, you will now see an error linking to the [webpack 5 upgrading documentation](/docs/messages/webpack5).
|
||||
|
||||
#### `target` option deprecated
|
||||
|
||||
If you do not have `target` in `next.config.js` you can skip this section.
|
||||
|
||||
The target option has been deprecated in favor of built-in support for tracing what dependencies are needed to run a page.
|
||||
|
||||
During `next build`, Next.js will automatically trace each page and its dependencies to determine all of the files that are needed for deploying a production version of your application.
|
||||
|
||||
If you are currently using the `target` option set to `serverless`, please read the [documentation on how to leverage the new output](/docs/pages/api-reference/config/next-config-js/output).
|
||||
88
node_modules/next/dist/docs/02-pages/02-guides/upgrading/version-13.md
generated
vendored
Normal file
88
node_modules/next/dist/docs/02-pages/02-guides/upgrading/version-13.md
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
---
|
||||
title: How to upgrade to version 13
|
||||
nav_title: Version 13
|
||||
description: Upgrade your Next.js Application from Version 12 to 13.
|
||||
---
|
||||
|
||||
## Upgrading from 12 to 13
|
||||
|
||||
To update to Next.js version 13, run the following command using your preferred package manager:
|
||||
|
||||
```bash filename="Terminal"
|
||||
npm i next@13 react@latest react-dom@latest eslint-config-next@13
|
||||
```
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn add next@13 react@latest react-dom@latest eslint-config-next@13
|
||||
```
|
||||
|
||||
```bash filename="Terminal"
|
||||
pnpm i next@13 react@latest react-dom@latest eslint-config-next@13
|
||||
```
|
||||
|
||||
```bash filename="Terminal"
|
||||
bun add next@13 react@latest react-dom@latest eslint-config-next@13
|
||||
```
|
||||
|
||||
> **Good to know:** If you are using TypeScript, ensure you also upgrade `@types/react` and `@types/react-dom` to their latest versions.
|
||||
|
||||
### v13 Summary
|
||||
|
||||
- The [Supported Browsers](/docs/architecture/supported-browsers) have been changed to drop Internet Explorer and target modern browsers.
|
||||
- The minimum Node.js version has been bumped from 12.22.0 to 16.14.0, since 12.x and 14.x have reached end-of-life.
|
||||
- The minimum React version has been bumped from 17.0.2 to 18.2.0.
|
||||
- The `swcMinify` configuration property was changed from `false` to `true`. See [Next.js Compiler](/docs/architecture/nextjs-compiler) for more info.
|
||||
- The `next/image` import was renamed to `next/legacy/image`. The `next/future/image` import was renamed to `next/image`. A [codemod is available](/docs/pages/guides/upgrading/codemods#next-image-to-legacy-image) to safely and automatically rename your imports.
|
||||
- The `next/link` child can no longer be `<a>`. Add the `legacyBehavior` prop to use the legacy behavior or remove the `<a>` to upgrade. A [codemod is available](/docs/pages/guides/upgrading/codemods#new-link) to automatically upgrade your code.
|
||||
- The `target` configuration property has been removed and superseded by [Output File Tracing](/docs/pages/api-reference/config/next-config-js/output).
|
||||
|
||||
## Migrating shared features
|
||||
|
||||
Next.js 13 introduces a new [`app` directory](/docs/app) with new features and conventions. However, upgrading to Next.js 13 does **not** require using the new `app` Router.
|
||||
|
||||
You can continue using `pages` with new features that work in both directories, such as the updated [Image component](#image-component), [Link component](#link-component), [Script component](#script-component), and [Font optimization](#font-optimization).
|
||||
|
||||
### `<Image/>` Component
|
||||
|
||||
Next.js 12 introduced many improvements to the Image Component with a temporary import: `next/future/image`. These improvements included less client-side JavaScript, easier ways to extend and style images, better accessibility, and native browser lazy loading.
|
||||
|
||||
Starting in Next.js 13, this new behavior is now the default for `next/image`.
|
||||
|
||||
There are two codemods to help you migrate to the new Image Component:
|
||||
|
||||
- [next-image-to-legacy-image](/docs/pages/guides/upgrading/codemods#next-image-to-legacy-image): This codemod will safely and automatically rename `next/image` imports to `next/legacy/image` to maintain the same behavior as Next.js 12. We recommend running this codemod to quickly update to Next.js 13 automatically.
|
||||
- [next-image-experimental](/docs/pages/guides/upgrading/codemods#next-image-experimental): After running the previous codemod, you can optionally run this experimental codemod to upgrade `next/legacy/image` to the new `next/image`, which will remove unused props and add inline styles. Please note this codemod is experimental and only covers static usage (such as `<Image src={img} layout="responsive" />`) but not dynamic usage (such as `<Image {...props} />`).
|
||||
|
||||
Alternatively, you can manually update by following the [migration guide](/docs/pages/guides/upgrading/codemods#next-image-experimental) and also see the [legacy comparison](/docs/pages/api-reference/components/image-legacy#comparison).
|
||||
|
||||
### `<Link>` Component
|
||||
|
||||
The [`<Link>` Component](/docs/pages/api-reference/components/link) no longer requires manually adding an `<a>` tag as a child. This behavior was added as an experimental option in [version 12.2](https://nextjs.org/blog/next-12-2) and is now the default. In Next.js 13, `<Link>` always renders `<a>` and allows you to forward props to the underlying tag.
|
||||
|
||||
For example:
|
||||
|
||||
```jsx
|
||||
import Link from 'next/link'
|
||||
|
||||
// Next.js 12: `<a>` has to be nested otherwise it's excluded
|
||||
<Link href="/about">
|
||||
<a>About</a>
|
||||
</Link>
|
||||
|
||||
// Next.js 13: `<Link>` always renders `<a>` under the hood
|
||||
<Link href="/about">
|
||||
About
|
||||
</Link>
|
||||
```
|
||||
|
||||
To upgrade your links to Next.js 13, you can use the [`new-link` codemod](/docs/pages/guides/upgrading/codemods#new-link).
|
||||
|
||||
### `<Script>` Component
|
||||
|
||||
The behavior of [`next/script`](/docs/pages/api-reference/components/script) has been updated to support both `pages` and `app`. If incrementally adopting `app`, read the [upgrade guide](/docs/pages/guides/upgrading).
|
||||
|
||||
### Font Optimization
|
||||
|
||||
Previously, Next.js helped you optimize fonts by inlining font CSS. Version 13 introduces the new [`next/font`](/docs/pages/api-reference/components/font) module which gives you the ability to customize your font loading experience while still ensuring great performance and privacy.
|
||||
|
||||
See [Optimizing Fonts](/docs/pages/api-reference/components/font) to learn how to use `next/font`.
|
||||
8
node_modules/next/dist/docs/02-pages/02-guides/upgrading/version-14.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/02-guides/upgrading/version-14.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: How to upgrade to version 14
|
||||
nav_title: Version 14
|
||||
description: Upgrade your Next.js Application from Version 13 to 14.
|
||||
source: app/guides/upgrading/version-14
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
226
node_modules/next/dist/docs/02-pages/02-guides/upgrading/version-9.md
generated
vendored
Normal file
226
node_modules/next/dist/docs/02-pages/02-guides/upgrading/version-9.md
generated
vendored
Normal file
@@ -0,0 +1,226 @@
|
||||
---
|
||||
title: How to upgrade to version 9
|
||||
nav_title: Version 9
|
||||
description: Upgrade your Next.js Application from Version 8 to Version 9.
|
||||
---
|
||||
|
||||
To upgrade to version 9, run the following command:
|
||||
|
||||
```bash filename="Terminal"
|
||||
npm i next@9
|
||||
```
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn add next@9
|
||||
```
|
||||
|
||||
```bash filename="Terminal"
|
||||
pnpm up next@9
|
||||
```
|
||||
|
||||
```bash filename="Terminal"
|
||||
bun add next@9
|
||||
```
|
||||
|
||||
> **Good to know:** If you are using TypeScript, ensure you also upgrade `@types/react` and `@types/react-dom` to their corresponding versions.
|
||||
|
||||
## Check your Custom App File (`pages/_app.js`)
|
||||
|
||||
If you previously copied the [Custom `<App>`](/docs/pages/building-your-application/routing/custom-app) example, you may be able to remove your `getInitialProps`.
|
||||
|
||||
Removing `getInitialProps` from `pages/_app.js` (when possible) is important to leverage new Next.js features!
|
||||
|
||||
The following `getInitialProps` does nothing and may be removed:
|
||||
|
||||
```js
|
||||
class MyApp extends App {
|
||||
// Remove me, I do nothing!
|
||||
static async getInitialProps({ Component, ctx }) {
|
||||
let pageProps = {}
|
||||
|
||||
if (Component.getInitialProps) {
|
||||
pageProps = await Component.getInitialProps(ctx)
|
||||
}
|
||||
|
||||
return { pageProps }
|
||||
}
|
||||
|
||||
render() {
|
||||
// ... etc
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
### `@zeit/next-typescript` is no longer necessary
|
||||
|
||||
Next.js will now ignore usage `@zeit/next-typescript` and warn you to remove it. Please remove this plugin from your `next.config.js`.
|
||||
|
||||
Remove references to `@zeit/next-typescript/babel` from your custom `.babelrc` (if present).
|
||||
|
||||
The usage of [`fork-ts-checker-webpack-plugin`](https://github.com/Realytics/fork-ts-checker-webpack-plugin/issues) should also be removed from your `next.config.js`.
|
||||
|
||||
TypeScript Definitions are published with the `next` package, so you need to uninstall `@types/next` as they would conflict.
|
||||
|
||||
The following types are different:
|
||||
|
||||
> This list was created by the community to help you upgrade, if you find other differences please send a pull-request to this list to help other users.
|
||||
|
||||
From:
|
||||
|
||||
```tsx
|
||||
import { NextContext } from 'next'
|
||||
import { NextAppContext, DefaultAppIProps } from 'next/app'
|
||||
import { NextDocumentContext, DefaultDocumentIProps } from 'next/document'
|
||||
```
|
||||
|
||||
to
|
||||
|
||||
```tsx
|
||||
import { NextPageContext } from 'next'
|
||||
import { AppContext, AppInitialProps } from 'next/app'
|
||||
import { DocumentContext, DocumentInitialProps } from 'next/document'
|
||||
```
|
||||
|
||||
### The `config` key is now an export on a page
|
||||
|
||||
You may no longer export a custom variable named `config` from a page (i.e. `export { config }` / `export const config ...`).
|
||||
This exported variable is now used to specify page-level Next.js configuration like Opt-in AMP and API Route features.
|
||||
|
||||
You must rename a non-Next.js-purposed `config` export to something different.
|
||||
|
||||
### `next/dynamic` no longer renders "loading..." by default while loading
|
||||
|
||||
Dynamic components will not render anything by default while loading. You can still customize this behavior by setting the `loading` property:
|
||||
|
||||
```jsx
|
||||
import dynamic from 'next/dynamic'
|
||||
|
||||
const DynamicComponentWithCustomLoading = dynamic(
|
||||
() => import('../components/hello2'),
|
||||
{
|
||||
loading: () => <p>Loading</p>,
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
### `withAmp` has been removed in favor of an exported configuration object
|
||||
|
||||
Next.js now has the concept of page-level configuration, so the `withAmp` higher-order component has been removed for consistency.
|
||||
|
||||
This change can be **automatically migrated by running the following commands in the root of your Next.js project:**
|
||||
|
||||
```bash filename="Terminal"
|
||||
curl -L https://github.com/vercel/next-codemod/archive/master.tar.gz | tar -xz --strip=2 next-codemod-master/transforms/withamp-to-config.js npx jscodeshift -t ./withamp-to-config.js pages/**/*.js
|
||||
```
|
||||
|
||||
To perform this migration by hand, or view what the codemod will produce, see below:
|
||||
|
||||
**Before**
|
||||
|
||||
```jsx
|
||||
import { withAmp } from 'next/amp'
|
||||
|
||||
function Home() {
|
||||
return <h1>My AMP Page</h1>
|
||||
}
|
||||
|
||||
export default withAmp(Home)
|
||||
// or
|
||||
export default withAmp(Home, { hybrid: true })
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```jsx
|
||||
export default function Home() {
|
||||
return <h1>My AMP Page</h1>
|
||||
}
|
||||
|
||||
export const config = {
|
||||
amp: true,
|
||||
// or
|
||||
amp: 'hybrid',
|
||||
}
|
||||
```
|
||||
|
||||
### `next export` no longer exports pages as `index.html`
|
||||
|
||||
Previously, exporting `pages/about.js` would result in `out/about/index.html`. This behavior has been changed to result in `out/about.html`.
|
||||
|
||||
You can revert to the previous behavior by creating a `next.config.js` with the following content:
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
trailingSlash: true,
|
||||
}
|
||||
```
|
||||
|
||||
### `pages/api/` is treated differently
|
||||
|
||||
Pages in `pages/api/` are now considered [API Routes](https://nextjs.org/blog/next-9#api-routes).
|
||||
Pages in this directory will no longer contain a client-side bundle.
|
||||
|
||||
## Deprecated Features
|
||||
|
||||
### `next/dynamic` has deprecated loading multiple modules at once
|
||||
|
||||
The ability to load multiple modules at once has been deprecated in `next/dynamic` to be closer to React's implementation (`React.lazy` and `Suspense`).
|
||||
|
||||
Updating code that relies on this behavior is relatively straightforward! We've provided an example of a before/after to help you migrate your application:
|
||||
|
||||
**Before**
|
||||
|
||||
```jsx
|
||||
import dynamic from 'next/dynamic'
|
||||
|
||||
const HelloBundle = dynamic({
|
||||
modules: () => {
|
||||
const components = {
|
||||
Hello1: () => import('../components/hello1').then((m) => m.default),
|
||||
Hello2: () => import('../components/hello2').then((m) => m.default),
|
||||
}
|
||||
|
||||
return components
|
||||
},
|
||||
render: (props, { Hello1, Hello2 }) => (
|
||||
<div>
|
||||
<h1>{props.title}</h1>
|
||||
<Hello1 />
|
||||
<Hello2 />
|
||||
</div>
|
||||
),
|
||||
})
|
||||
|
||||
function DynamicBundle() {
|
||||
return <HelloBundle title="Dynamic Bundle" />
|
||||
}
|
||||
|
||||
export default DynamicBundle
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```jsx
|
||||
import dynamic from 'next/dynamic'
|
||||
|
||||
const Hello1 = dynamic(() => import('../components/hello1'))
|
||||
const Hello2 = dynamic(() => import('../components/hello2'))
|
||||
|
||||
function HelloBundle({ title }) {
|
||||
return (
|
||||
<div>
|
||||
<h1>{title}</h1>
|
||||
<Hello1 />
|
||||
<Hello2 />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function DynamicBundle() {
|
||||
return <HelloBundle title="Dynamic Bundle" />
|
||||
}
|
||||
|
||||
export default DynamicBundle
|
||||
```
|
||||
213
node_modules/next/dist/docs/02-pages/03-building-your-application/01-routing/01-pages-and-layouts.md
generated
vendored
Normal file
213
node_modules/next/dist/docs/02-pages/03-building-your-application/01-routing/01-pages-and-layouts.md
generated
vendored
Normal file
@@ -0,0 +1,213 @@
|
||||
---
|
||||
title: Pages and Layouts
|
||||
description: Create your first page and shared layout with the Pages Router.
|
||||
---
|
||||
|
||||
The Pages Router has a file-system based router built on the concept of pages.
|
||||
|
||||
When a file is added to the `pages` directory, it's automatically available as a route.
|
||||
|
||||
In Next.js, a **page** is a [React Component](https://react.dev/learn/your-first-component) exported from a `.js`, `.jsx`, `.ts`, or `.tsx` file in the `pages` directory. Each page is associated with a route based on its file name.
|
||||
|
||||
**Example**: If you create `pages/about.js` that exports a React component like below, it will be accessible at `/about`.
|
||||
|
||||
```jsx
|
||||
export default function About() {
|
||||
return <div>About</div>
|
||||
}
|
||||
```
|
||||
|
||||
## Index routes
|
||||
|
||||
The router will automatically route files named `index` to the root of the directory.
|
||||
|
||||
- `pages/index.js` → `/`
|
||||
- `pages/blog/index.js` → `/blog`
|
||||
|
||||
## Nested routes
|
||||
|
||||
The router supports nested files. If you create a nested folder structure, files will automatically be routed in the same way still.
|
||||
|
||||
- `pages/blog/first-post.js` → `/blog/first-post`
|
||||
- `pages/dashboard/settings/username.js` → `/dashboard/settings/username`
|
||||
|
||||
## Pages with Dynamic Routes
|
||||
|
||||
Next.js supports pages with dynamic routes. For example, if you create a file called `pages/posts/[id].js`, then it will be accessible at `posts/1`, `posts/2`, etc.
|
||||
|
||||
> To learn more about dynamic routing, check the [Dynamic Routing documentation](/docs/pages/building-your-application/routing/dynamic-routes).
|
||||
|
||||
## Layout Pattern
|
||||
|
||||
The React model allows us to deconstruct a [page](/docs/pages/building-your-application/routing/pages-and-layouts) into a series of components. Many of these components are often reused between pages. For example, you might have the same navigation bar and footer on every page.
|
||||
|
||||
```jsx filename="components/layout.js"
|
||||
import Navbar from './navbar'
|
||||
import Footer from './footer'
|
||||
|
||||
export default function Layout({ children }) {
|
||||
return (
|
||||
<>
|
||||
<Navbar />
|
||||
<main>{children}</main>
|
||||
<Footer />
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Single Shared Layout with Custom App
|
||||
|
||||
If you only have one layout for your entire application, you can create a [Custom App](/docs/pages/building-your-application/routing/custom-app) and wrap your application with the layout. Since the `<Layout />` component is re-used when changing pages, its component state will be preserved (e.g. input values).
|
||||
|
||||
```jsx filename="pages/_app.js"
|
||||
import Layout from '../components/layout'
|
||||
|
||||
export default function MyApp({ Component, pageProps }) {
|
||||
return (
|
||||
<Layout>
|
||||
<Component {...pageProps} />
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Per-Page Layouts
|
||||
|
||||
If you need multiple layouts, you can add a property `getLayout` to your page, allowing you to return a React component for the layout. This allows you to define the layout on a _per-page basis_. Since we're returning a function, we can have complex nested layouts if desired.
|
||||
|
||||
```jsx filename="pages/index.js"
|
||||
|
||||
import Layout from '../components/layout'
|
||||
import NestedLayout from '../components/nested-layout'
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
/** Your content */
|
||||
)
|
||||
}
|
||||
|
||||
Page.getLayout = function getLayout(page) {
|
||||
return (
|
||||
<Layout>
|
||||
<NestedLayout>{page}</NestedLayout>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/_app.js"
|
||||
export default function MyApp({ Component, pageProps }) {
|
||||
// Use the layout defined at the page level, if available
|
||||
const getLayout = Component.getLayout ?? ((page) => page)
|
||||
|
||||
return getLayout(<Component {...pageProps} />)
|
||||
}
|
||||
```
|
||||
|
||||
When navigating between pages, we want to _persist_ page state (input values, scroll position, etc.) for a Single-Page Application (SPA) experience.
|
||||
|
||||
This layout pattern enables state persistence because the React component tree is maintained between page transitions. With the component tree, React can understand which elements have changed to preserve state.
|
||||
|
||||
> **Good to know**: This process is called [reconciliation](https://react.dev/learn/preserving-and-resetting-state), which is how React understands which elements have changed.
|
||||
|
||||
### With TypeScript
|
||||
|
||||
When using TypeScript, you must first create a new type for your pages which includes a `getLayout` function. Then, you must create a new type for your `AppProps` which overrides the `Component` property to use the previously created type.
|
||||
|
||||
```tsx filename="pages/index.tsx" switcher
|
||||
import type { ReactElement } from 'react'
|
||||
import Layout from '../components/layout'
|
||||
import NestedLayout from '../components/nested-layout'
|
||||
import type { NextPageWithLayout } from './_app'
|
||||
|
||||
const Page: NextPageWithLayout = () => {
|
||||
return <p>hello world</p>
|
||||
}
|
||||
|
||||
Page.getLayout = function getLayout(page: ReactElement) {
|
||||
return (
|
||||
<Layout>
|
||||
<NestedLayout>{page}</NestedLayout>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
export default Page
|
||||
```
|
||||
|
||||
```jsx filename="pages/index.js" switcher
|
||||
import Layout from '../components/layout'
|
||||
import NestedLayout from '../components/nested-layout'
|
||||
|
||||
const Page = () => {
|
||||
return <p>hello world</p>
|
||||
}
|
||||
|
||||
Page.getLayout = function getLayout(page) {
|
||||
return (
|
||||
<Layout>
|
||||
<NestedLayout>{page}</NestedLayout>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
export default Page
|
||||
```
|
||||
|
||||
```tsx filename="pages/_app.tsx" switcher
|
||||
import type { ReactElement, ReactNode } from 'react'
|
||||
import type { NextPage } from 'next'
|
||||
import type { AppProps } from 'next/app'
|
||||
|
||||
export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
|
||||
getLayout?: (page: ReactElement) => ReactNode
|
||||
}
|
||||
|
||||
type AppPropsWithLayout = AppProps & {
|
||||
Component: NextPageWithLayout
|
||||
}
|
||||
|
||||
export default function MyApp({ Component, pageProps }: AppPropsWithLayout) {
|
||||
// Use the layout defined at the page level, if available
|
||||
const getLayout = Component.getLayout ?? ((page) => page)
|
||||
|
||||
return getLayout(<Component {...pageProps} />)
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/_app.js" switcher
|
||||
export default function MyApp({ Component, pageProps }) {
|
||||
// Use the layout defined at the page level, if available
|
||||
const getLayout = Component.getLayout ?? ((page) => page)
|
||||
|
||||
return getLayout(<Component {...pageProps} />)
|
||||
}
|
||||
```
|
||||
|
||||
### Data Fetching
|
||||
|
||||
Inside your layout, you can fetch data on the client-side using `useEffect` or a library like [SWR](https://swr.vercel.app/). Because this file is not a [Page](/docs/pages/building-your-application/routing/pages-and-layouts), you cannot use `getStaticProps` or `getServerSideProps` currently.
|
||||
|
||||
```jsx filename="components/layout.js"
|
||||
import useSWR from 'swr'
|
||||
import Navbar from './navbar'
|
||||
import Footer from './footer'
|
||||
|
||||
export default function Layout({ children }) {
|
||||
const { data, error } = useSWR('/api/navigation', fetcher)
|
||||
|
||||
if (error) return <div>Failed to load</div>
|
||||
if (!data) return <div>Loading...</div>
|
||||
|
||||
return (
|
||||
<>
|
||||
<Navbar links={data.links} />
|
||||
<main>{children}</main>
|
||||
<Footer />
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
64
node_modules/next/dist/docs/02-pages/03-building-your-application/01-routing/02-dynamic-routes.md
generated
vendored
Normal file
64
node_modules/next/dist/docs/02-pages/03-building-your-application/01-routing/02-dynamic-routes.md
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
---
|
||||
title: Dynamic Routes
|
||||
description: Dynamic Routes are pages that allow you to add custom params to your URLs. Start creating Dynamic Routes and learn more here.
|
||||
related:
|
||||
title: Next Steps
|
||||
description: For more information on what to do next, we recommend the following sections
|
||||
links:
|
||||
- pages/building-your-application/routing/linking-and-navigating
|
||||
- pages/api-reference/functions/use-router
|
||||
---
|
||||
|
||||
When you don't know the exact segment names ahead of time and want to create routes from dynamic data, you can use Dynamic Segments that are filled in at request time or [prerendered](/docs/pages/building-your-application/data-fetching/get-static-paths) at build time.
|
||||
|
||||
## Convention
|
||||
|
||||
A Dynamic Segment can be created by wrapping a file or folder name in square brackets: `[segmentName]`. For example, `[id]` or `[slug]`.
|
||||
|
||||
Dynamic Segments can be accessed from [`useRouter`](/docs/pages/api-reference/functions/use-router).
|
||||
|
||||
## Example
|
||||
|
||||
For example, a blog could include the following route `pages/blog/[slug].js` where `[slug]` is the Dynamic Segment for blog posts.
|
||||
|
||||
```jsx
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
export default function Page() {
|
||||
const router = useRouter()
|
||||
return <p>Post: {router.query.slug}</p>
|
||||
}
|
||||
```
|
||||
|
||||
| Route | Example URL | `params` |
|
||||
| ---------------------- | ----------- | --------------- |
|
||||
| `pages/blog/[slug].js` | `/blog/a` | `{ slug: 'a' }` |
|
||||
| `pages/blog/[slug].js` | `/blog/b` | `{ slug: 'b' }` |
|
||||
| `pages/blog/[slug].js` | `/blog/c` | `{ slug: 'c' }` |
|
||||
|
||||
## Catch-all Segments
|
||||
|
||||
Dynamic Segments can be extended to **catch-all** subsequent segments by adding an ellipsis inside the brackets `[...segmentName]`.
|
||||
|
||||
For example, `pages/shop/[...slug].js` will match `/shop/clothes`, but also `/shop/clothes/tops`, `/shop/clothes/tops/t-shirts`, and so on.
|
||||
|
||||
| Route | Example URL | `params` |
|
||||
| ------------------------- | ------------- | --------------------------- |
|
||||
| `pages/shop/[...slug].js` | `/shop/a` | `{ slug: ['a'] }` |
|
||||
| `pages/shop/[...slug].js` | `/shop/a/b` | `{ slug: ['a', 'b'] }` |
|
||||
| `pages/shop/[...slug].js` | `/shop/a/b/c` | `{ slug: ['a', 'b', 'c'] }` |
|
||||
|
||||
## Optional Catch-all Segments
|
||||
|
||||
Catch-all Segments can be made **optional** by including the parameter in double square brackets: `[[...segmentName]]`.
|
||||
|
||||
For example, `pages/shop/[[...slug]].js` will **also** match `/shop`, in addition to `/shop/clothes`, `/shop/clothes/tops`, `/shop/clothes/tops/t-shirts`.
|
||||
|
||||
The difference between **catch-all** and **optional catch-all** segments is that with optional, the route without the parameter is also matched (`/shop` in the example above).
|
||||
|
||||
| Route | Example URL | `params` |
|
||||
| --------------------------- | ------------- | --------------------------- |
|
||||
| `pages/shop/[[...slug]].js` | `/shop` | `{ slug: undefined }` |
|
||||
| `pages/shop/[[...slug]].js` | `/shop/a` | `{ slug: ['a'] }` |
|
||||
| `pages/shop/[[...slug]].js` | `/shop/a/b` | `{ slug: ['a', 'b'] }` |
|
||||
| `pages/shop/[[...slug]].js` | `/shop/a/b/c` | `{ slug: ['a', 'b', 'c'] }` |
|
||||
184
node_modules/next/dist/docs/02-pages/03-building-your-application/01-routing/03-linking-and-navigating.md
generated
vendored
Normal file
184
node_modules/next/dist/docs/02-pages/03-building-your-application/01-routing/03-linking-and-navigating.md
generated
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
---
|
||||
title: Linking and Navigating
|
||||
description: Learn how navigation works in Next.js, and how to use the Link Component and `useRouter` hook.
|
||||
---
|
||||
|
||||
The Next.js router allows you to do client-side route transitions between pages, similar to a single-page application.
|
||||
|
||||
A React component called `Link` is provided to do this client-side route transition.
|
||||
|
||||
```jsx
|
||||
import Link from 'next/link'
|
||||
|
||||
function Home() {
|
||||
return (
|
||||
<ul>
|
||||
<li>
|
||||
<Link href="/">Home</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/about">About Us</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/blog/hello-world">Blog Post</Link>
|
||||
</li>
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
|
||||
export default Home
|
||||
```
|
||||
|
||||
The example above uses multiple links. Each one maps a path (`href`) to a known page:
|
||||
|
||||
- `/` → `pages/index.js`
|
||||
- `/about` → `pages/about.js`
|
||||
- `/blog/hello-world` → `pages/blog/[slug].js`
|
||||
|
||||
Any `<Link />` in the viewport (initially or through scroll) will be prefetched by default (including the corresponding data) for pages using [Static Generation](/docs/pages/building-your-application/data-fetching/get-static-props). The corresponding data for [server-rendered](/docs/pages/building-your-application/data-fetching/get-server-side-props) routes is fetched _only when_ the `<Link />` is clicked.
|
||||
|
||||
## Linking to dynamic paths
|
||||
|
||||
You can also use interpolation to create the path, which comes in handy for [dynamic route segments](/docs/pages/building-your-application/routing/dynamic-routes). For example, to show a list of posts which have been passed to the component as a prop:
|
||||
|
||||
```jsx
|
||||
import Link from 'next/link'
|
||||
|
||||
function Posts({ posts }) {
|
||||
return (
|
||||
<ul>
|
||||
{posts.map((post) => (
|
||||
<li key={post.id}>
|
||||
<Link href={`/blog/${encodeURIComponent(post.slug)}`}>
|
||||
{post.title}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
|
||||
export default Posts
|
||||
```
|
||||
|
||||
> [`encodeURIComponent`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) is used in the example to keep the path utf-8 compatible.
|
||||
|
||||
Alternatively, using a URL Object:
|
||||
|
||||
```jsx
|
||||
import Link from 'next/link'
|
||||
|
||||
function Posts({ posts }) {
|
||||
return (
|
||||
<ul>
|
||||
{posts.map((post) => (
|
||||
<li key={post.id}>
|
||||
<Link
|
||||
href={{
|
||||
pathname: '/blog/[slug]',
|
||||
query: { slug: post.slug },
|
||||
}}
|
||||
>
|
||||
{post.title}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
|
||||
export default Posts
|
||||
```
|
||||
|
||||
Now, instead of using interpolation to create the path, we use a URL object in `href` where:
|
||||
|
||||
- `pathname` is the name of the page in the `pages` directory. `/blog/[slug]` in this case.
|
||||
- `query` is an object with the dynamic segment. `slug` in this case.
|
||||
|
||||
## Injecting the router
|
||||
|
||||
To access the [`router` object](/docs/pages/api-reference/functions/use-router#router-object) in a React component you can use [`useRouter`](/docs/pages/api-reference/functions/use-router) or [`withRouter`](/docs/pages/api-reference/functions/use-router#withrouter).
|
||||
|
||||
In general we recommend using [`useRouter`](/docs/pages/api-reference/functions/use-router).
|
||||
|
||||
## Imperative Routing
|
||||
|
||||
[`next/link`](/docs/pages/api-reference/components/link) should be able to cover most of your routing needs, but you can also do client-side navigations without it, take a look at the [documentation for `next/router`](/docs/pages/api-reference/functions/use-router).
|
||||
|
||||
The following example shows how to do basic page navigations with [`useRouter`](/docs/pages/api-reference/functions/use-router):
|
||||
|
||||
```jsx
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
export default function ReadMore() {
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<button onClick={() => router.push('/about')}>
|
||||
Click here to read more
|
||||
</button>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Shallow Routing
|
||||
|
||||
<details>
|
||||
<summary>Examples</summary>
|
||||
|
||||
- [Shallow Routing](https://github.com/vercel/next.js/tree/canary/examples/with-shallow-routing)
|
||||
|
||||
</details>
|
||||
|
||||
Shallow routing allows you to change the URL without running data fetching methods again, that includes [`getServerSideProps`](/docs/pages/building-your-application/data-fetching/get-server-side-props), [`getStaticProps`](/docs/pages/building-your-application/data-fetching/get-static-props), and [`getInitialProps`](/docs/pages/api-reference/functions/get-initial-props).
|
||||
|
||||
You'll receive the updated `pathname` and the `query` via the [`router` object](/docs/pages/api-reference/functions/use-router#router-object) (added by [`useRouter`](/docs/pages/api-reference/functions/use-router) or [`withRouter`](/docs/pages/api-reference/functions/use-router#withrouter)), without losing state.
|
||||
|
||||
To enable shallow routing, set the `shallow` option to `true`. Consider the following example:
|
||||
|
||||
```jsx
|
||||
import { useEffect } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
// Current URL is '/'
|
||||
function Page() {
|
||||
const router = useRouter()
|
||||
|
||||
useEffect(() => {
|
||||
// Always do navigations after the first render
|
||||
router.push('/?counter=10', undefined, { shallow: true })
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
// The counter changed!
|
||||
}, [router.query.counter])
|
||||
}
|
||||
|
||||
export default Page
|
||||
```
|
||||
|
||||
The URL will get updated to `/?counter=10` and the page won't get replaced, only the state of the route is changed.
|
||||
|
||||
You can also watch for URL changes via [`componentDidUpdate`](https://react.dev/reference/react/Component#componentdidupdate) as shown below:
|
||||
|
||||
```jsx
|
||||
componentDidUpdate(prevProps) {
|
||||
const { pathname, query } = this.props.router
|
||||
// verify props have changed to avoid an infinite loop
|
||||
if (query.counter !== prevProps.router.query.counter) {
|
||||
// fetch data based on the new query
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Caveats
|
||||
|
||||
Shallow routing **only** works for URL changes in the current page. For example, let's assume we have another page called `pages/about.js`, and you run this:
|
||||
|
||||
```js
|
||||
router.push('/?counter=10', '/about?counter=10', { shallow: true })
|
||||
```
|
||||
|
||||
Since that's a new page, it'll unload the current page, load the new one and wait for data fetching even though we asked to do shallow routing.
|
||||
|
||||
When shallow routing is used with proxy it will not ensure the new page matches the current page like previously done without proxy. This is due to proxy being able to rewrite dynamically and can't be verified client-side without a data fetch which is skipped with shallow, so a shallow route change must always be treated as shallow.
|
||||
89
node_modules/next/dist/docs/02-pages/03-building-your-application/01-routing/05-custom-app.md
generated
vendored
Normal file
89
node_modules/next/dist/docs/02-pages/03-building-your-application/01-routing/05-custom-app.md
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
---
|
||||
title: Custom App
|
||||
description: Control page initialization and add a layout that persists for all pages by overriding the default App component used by Next.js.
|
||||
---
|
||||
|
||||
Next.js uses the `App` component to initialize pages. You can override it and control the page initialization and:
|
||||
|
||||
- Create a shared layout between page changes
|
||||
- Inject additional data into pages
|
||||
- [Add global CSS](/docs/app/getting-started/css)
|
||||
|
||||
## Usage
|
||||
|
||||
To override the default `App`, create the file `pages/_app` as shown below:
|
||||
|
||||
```tsx filename="pages/_app.tsx" switcher
|
||||
import type { AppProps } from 'next/app'
|
||||
|
||||
export default function MyApp({ Component, pageProps }: AppProps) {
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/_app.jsx" switcher
|
||||
export default function MyApp({ Component, pageProps }) {
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
```
|
||||
|
||||
The `Component` prop is the active `page`, so whenever you navigate between routes, `Component` will change to the new `page`. Therefore, any props you send to `Component` will be received by the `page`.
|
||||
|
||||
`pageProps` is an object with the initial props that were preloaded for your page by one of our [data fetching methods](/docs/pages/building-your-application/data-fetching), otherwise it's an empty object.
|
||||
|
||||
> **Good to know**:
|
||||
>
|
||||
> - If your app is running and you added a custom `App`, you'll need to restart the development server. Only required if `pages/_app.js` didn't exist before.
|
||||
> - `App` does not support Next.js [Data Fetching methods](/docs/pages/building-your-application/data-fetching) like [`getStaticProps`](/docs/pages/building-your-application/data-fetching/get-static-props) or [`getServerSideProps`](/docs/pages/building-your-application/data-fetching/get-server-side-props).
|
||||
|
||||
## `getInitialProps` with `App`
|
||||
|
||||
Using [`getInitialProps`](/docs/pages/api-reference/functions/get-initial-props) in `App` will disable [Automatic Static Optimization](/docs/pages/building-your-application/rendering/automatic-static-optimization) for pages without [`getStaticProps`](/docs/pages/building-your-application/data-fetching/get-static-props).
|
||||
|
||||
**We do not recommend using this pattern.** Instead, consider [incrementally adopting](/docs/app/guides/migrating/app-router-migration) the App Router, which allows you to more easily fetch data for pages and layouts.
|
||||
|
||||
```tsx filename="pages/_app.tsx" switcher
|
||||
import App, { AppContext, AppInitialProps, AppProps } from 'next/app'
|
||||
|
||||
type AppOwnProps = { example: string }
|
||||
|
||||
export default function MyApp({
|
||||
Component,
|
||||
pageProps,
|
||||
example,
|
||||
}: AppProps & AppOwnProps) {
|
||||
return (
|
||||
<>
|
||||
<p>Data: {example}</p>
|
||||
<Component {...pageProps} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
MyApp.getInitialProps = async (
|
||||
context: AppContext
|
||||
): Promise<AppOwnProps & AppInitialProps> => {
|
||||
const ctx = await App.getInitialProps(context)
|
||||
|
||||
return { ...ctx, example: 'data' }
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/_app.jsx" switcher
|
||||
import App from 'next/app'
|
||||
|
||||
export default function MyApp({ Component, pageProps, example }) {
|
||||
return (
|
||||
<>
|
||||
<p>Data: {example}</p>
|
||||
<Component {...pageProps} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
MyApp.getInitialProps = async (context) => {
|
||||
const ctx = await App.getInitialProps(context)
|
||||
|
||||
return { ...ctx, example: 'data' }
|
||||
}
|
||||
```
|
||||
147
node_modules/next/dist/docs/02-pages/03-building-your-application/01-routing/06-custom-document.md
generated
vendored
Normal file
147
node_modules/next/dist/docs/02-pages/03-building-your-application/01-routing/06-custom-document.md
generated
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
---
|
||||
title: Custom Document
|
||||
description: Extend the default document markup added by Next.js.
|
||||
---
|
||||
|
||||
A custom `Document` can update the `<html>` and `<body>` tags used to render a [Page](/docs/pages/building-your-application/routing/pages-and-layouts).
|
||||
|
||||
To override the default `Document`, create the file `pages/_document` as shown below:
|
||||
|
||||
```tsx filename="pages/_document.tsx" switcher
|
||||
import { Html, Head, Main, NextScript } from 'next/document'
|
||||
|
||||
export default function Document() {
|
||||
return (
|
||||
<Html lang="en">
|
||||
<Head />
|
||||
<body>
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
</Html>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/_document.jsx" switcher
|
||||
import { Html, Head, Main, NextScript } from 'next/document'
|
||||
|
||||
export default function Document() {
|
||||
return (
|
||||
<Html lang="en">
|
||||
<Head />
|
||||
<body>
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
</Html>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
> **Good to know**:
|
||||
>
|
||||
> - `_document` is only rendered on the server, so event handlers like `onClick` cannot be used in this file.
|
||||
> - `<Html>`, `<Head />`, `<Main />` and `<NextScript />` are required for the page to be properly rendered.
|
||||
|
||||
## Caveats
|
||||
|
||||
- The `<Head />` component used in `_document` is not the same as [`next/head`](/docs/pages/api-reference/components/head). The `<Head />` component used here should only be used for any `<head>` code that is common for all pages. For all other cases, such as `<title>` tags, we recommend using [`next/head`](/docs/pages/api-reference/components/head) in your pages or components.
|
||||
- React components outside of `<Main />` will not be initialized by the browser. Do _not_ add application logic here or custom CSS (like `styled-jsx`). If you need shared components in all your pages (like a menu or a toolbar), read [Layouts](/docs/pages/building-your-application/routing/pages-and-layouts#layout-pattern) instead.
|
||||
- `Document` currently does not support Next.js [Data Fetching methods](/docs/pages/building-your-application/data-fetching) like [`getStaticProps`](/docs/pages/building-your-application/data-fetching/get-static-props) or [`getServerSideProps`](/docs/pages/building-your-application/data-fetching/get-server-side-props).
|
||||
|
||||
## Customizing `renderPage`
|
||||
|
||||
Customizing `renderPage` is advanced and only needed for libraries like CSS-in-JS to support server-side rendering. This is not needed for built-in `styled-jsx` support.
|
||||
|
||||
**We do not recommend using this pattern.** Instead, consider [incrementally adopting](/docs/app/guides/migrating/app-router-migration) the App Router, which allows you to more easily fetch data for pages and layouts.
|
||||
|
||||
```tsx filename="pages/_document.tsx" switcher
|
||||
import Document, {
|
||||
Html,
|
||||
Head,
|
||||
Main,
|
||||
NextScript,
|
||||
DocumentContext,
|
||||
DocumentInitialProps,
|
||||
} from 'next/document'
|
||||
|
||||
class MyDocument extends Document {
|
||||
static async getInitialProps(
|
||||
ctx: DocumentContext
|
||||
): Promise<DocumentInitialProps> {
|
||||
const originalRenderPage = ctx.renderPage
|
||||
|
||||
// Run the React rendering logic synchronously
|
||||
ctx.renderPage = () =>
|
||||
originalRenderPage({
|
||||
// Useful for wrapping the whole react tree
|
||||
enhanceApp: (App) => App,
|
||||
// Useful for wrapping in a per-page basis
|
||||
enhanceComponent: (Component) => Component,
|
||||
})
|
||||
|
||||
// Run the parent `getInitialProps`, it now includes the custom `renderPage`
|
||||
const initialProps = await Document.getInitialProps(ctx)
|
||||
|
||||
return initialProps
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Html lang="en">
|
||||
<Head />
|
||||
<body>
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
</Html>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default MyDocument
|
||||
```
|
||||
|
||||
```jsx filename="pages/_document.jsx" switcher
|
||||
import Document, { Html, Head, Main, NextScript } from 'next/document'
|
||||
|
||||
class MyDocument extends Document {
|
||||
static async getInitialProps(ctx) {
|
||||
const originalRenderPage = ctx.renderPage
|
||||
|
||||
// Run the React rendering logic synchronously
|
||||
ctx.renderPage = () =>
|
||||
originalRenderPage({
|
||||
// Useful for wrapping the whole react tree
|
||||
enhanceApp: (App) => App,
|
||||
// Useful for wrapping in a per-page basis
|
||||
enhanceComponent: (Component) => Component,
|
||||
})
|
||||
|
||||
// Run the parent `getInitialProps`, it now includes the custom `renderPage`
|
||||
const initialProps = await Document.getInitialProps(ctx)
|
||||
|
||||
return initialProps
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Html lang="en">
|
||||
<Head />
|
||||
<body>
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
</Html>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default MyDocument
|
||||
```
|
||||
|
||||
> **Good to know**:
|
||||
>
|
||||
> - `getInitialProps` in `_document` is not called during client-side transitions.
|
||||
> - The `ctx` object for `_document` is equivalent to the one received in [`getInitialProps`](/docs/pages/api-reference/functions/get-initial-props#context-object), with the addition of `renderPage`.
|
||||
459
node_modules/next/dist/docs/02-pages/03-building-your-application/01-routing/07-api-routes.md
generated
vendored
Normal file
459
node_modules/next/dist/docs/02-pages/03-building-your-application/01-routing/07-api-routes.md
generated
vendored
Normal file
@@ -0,0 +1,459 @@
|
||||
---
|
||||
title: API Routes
|
||||
description: Next.js supports API Routes, which allow you to build your API without leaving your Next.js app. Learn how it works here.
|
||||
---
|
||||
|
||||
<details>
|
||||
<summary>Examples</summary>
|
||||
|
||||
- [API Routes Request Helpers](https://github.com/vercel/next.js/tree/canary/examples/api-routes-proxy)
|
||||
- [API Routes with GraphQL](https://github.com/vercel/next.js/tree/canary/examples/api-routes-graphql)
|
||||
- [API Routes with REST](https://github.com/vercel/next.js/tree/canary/examples/api-routes-rest)
|
||||
- [API Routes with CORS](https://github.com/vercel/next.js/tree/canary/examples/api-routes-cors)
|
||||
|
||||
</details>
|
||||
|
||||
> **Good to know**: If you are using the App Router, you can use [Server Components](/docs/app/getting-started/server-and-client-components) or [Route Handlers](/docs/app/api-reference/file-conventions/route) instead of API Routes.
|
||||
|
||||
API routes provide a solution to build a **public API** with Next.js.
|
||||
|
||||
Any file inside the folder `pages/api` is mapped to `/api/*` and will be treated as an API endpoint instead of a `page`. They are server-side only bundles and won't increase your client-side bundle size.
|
||||
|
||||
For example, the following API route returns a JSON response with a status code of `200`:
|
||||
|
||||
```ts filename="pages/api/hello.ts" switcher
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
type ResponseData = {
|
||||
message: string
|
||||
}
|
||||
|
||||
export default function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse<ResponseData>
|
||||
) {
|
||||
res.status(200).json({ message: 'Hello from Next.js!' })
|
||||
}
|
||||
```
|
||||
|
||||
```js filename="pages/api/hello.js" switcher
|
||||
export default function handler(req, res) {
|
||||
res.status(200).json({ message: 'Hello from Next.js!' })
|
||||
}
|
||||
```
|
||||
|
||||
> **Good to know**:
|
||||
>
|
||||
> - API Routes [do not specify CORS headers](https://developer.mozilla.org/docs/Web/HTTP/CORS), meaning they are **same-origin only** by default. You can customize such behavior by wrapping the request handler with the [CORS request helpers](https://github.com/vercel/next.js/tree/canary/examples/api-routes-cors).
|
||||
> - API Routes can't be used with [static exports](/docs/pages/guides/static-exports). However, [Route Handlers](/docs/app/api-reference/file-conventions/route) in the App Router can.
|
||||
> - API Routes will be affected by [`pageExtensions` configuration](/docs/pages/api-reference/config/next-config-js/pageExtensions) in `next.config.js`.
|
||||
|
||||
## Parameters
|
||||
|
||||
```tsx
|
||||
export default function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
- `req`: An instance of [http.IncomingMessage](https://nodejs.org/api/http.html#class-httpincomingmessage)
|
||||
- `res`: An instance of [http.ServerResponse](https://nodejs.org/api/http.html#class-httpserverresponse)
|
||||
|
||||
## HTTP Methods
|
||||
|
||||
To handle different HTTP methods in an API route, you can use `req.method` in your request handler, like so:
|
||||
|
||||
```ts filename="pages/api/hello.ts" switcher
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
export default function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
if (req.method === 'POST') {
|
||||
// Process a POST request
|
||||
} else {
|
||||
// Handle any other HTTP method
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```js filename="pages/api/hello.js" switcher
|
||||
export default function handler(req, res) {
|
||||
if (req.method === 'POST') {
|
||||
// Process a POST request
|
||||
} else {
|
||||
// Handle any other HTTP method
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Request Helpers
|
||||
|
||||
API Routes provide built-in request helpers which parse the incoming request (`req`):
|
||||
|
||||
- `req.cookies` - An object containing the cookies sent by the request. Defaults to `{}`
|
||||
- `req.query` - An object containing the [query string](https://en.wikipedia.org/wiki/Query_string). Defaults to `{}`
|
||||
- `req.body` - An object containing the body parsed by `content-type`, or `null` if no body was sent
|
||||
|
||||
### Custom config
|
||||
|
||||
Every API Route can export a `config` object to change the default configuration, which is the following:
|
||||
|
||||
```js
|
||||
export const config = {
|
||||
api: {
|
||||
bodyParser: {
|
||||
sizeLimit: '1mb',
|
||||
},
|
||||
},
|
||||
// Specifies the maximum allowed duration for this function to execute (in seconds)
|
||||
maxDuration: 5,
|
||||
}
|
||||
```
|
||||
|
||||
`bodyParser` is automatically enabled. If you want to consume the body as a `Stream` or with [`raw-body`](https://www.npmjs.com/package/raw-body), you can set this to `false`.
|
||||
|
||||
One use case for disabling the automatic `bodyParsing` is to allow you to verify the raw body of a **webhook** request, for example [from GitHub](https://docs.github.com/en/developers/webhooks-and-events/webhooks/securing-your-webhooks#validating-payloads-from-github).
|
||||
|
||||
```js
|
||||
export const config = {
|
||||
api: {
|
||||
bodyParser: false,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
`bodyParser.sizeLimit` is the maximum size allowed for the parsed body, in any format supported by [bytes](https://github.com/visionmedia/bytes.js), like so:
|
||||
|
||||
```js
|
||||
export const config = {
|
||||
api: {
|
||||
bodyParser: {
|
||||
sizeLimit: '500kb',
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
`externalResolver` is an explicit flag that tells the server that this route is being handled by an external resolver like _express_ or _connect_. Enabling this option disables warnings for unresolved requests.
|
||||
|
||||
```js
|
||||
export const config = {
|
||||
api: {
|
||||
externalResolver: true,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
`responseLimit` is automatically enabled, warning when an API Routes' response body is over 4MB.
|
||||
|
||||
If you are not using Next.js in a serverless environment, and understand the performance implications of not using a CDN or dedicated media host, you can set this limit to `false`.
|
||||
|
||||
```js
|
||||
export const config = {
|
||||
api: {
|
||||
responseLimit: false,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
`responseLimit` can also take the number of bytes or any string format supported by `bytes`, for example `1000`, `'500kb'` or `'3mb'`.
|
||||
This value will be the maximum response size before a warning is displayed. Default is 4MB. (see above)
|
||||
|
||||
```js
|
||||
export const config = {
|
||||
api: {
|
||||
responseLimit: '8mb',
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Response Helpers
|
||||
|
||||
The [Server Response object](https://nodejs.org/api/http.html#http_class_http_serverresponse), (often abbreviated as `res`) includes a set of Express.js-like helper methods to improve the developer experience and increase the speed of creating new API endpoints.
|
||||
|
||||
The included helpers are:
|
||||
|
||||
- `res.status(code)` - A function to set the status code. `code` must be a valid [HTTP status code](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes)
|
||||
- `res.json(body)` - Sends a JSON response. `body` must be a [serializable object](https://developer.mozilla.org/docs/Glossary/Serialization)
|
||||
- `res.send(body)` - Sends the HTTP response. `body` can be a `string`, an `object` or a `Buffer`
|
||||
- `res.redirect([status,] path)` - Redirects to a specified path or URL. `status` must be a valid [HTTP status code](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes). If not specified, `status` defaults to "307" "Temporary redirect".
|
||||
- `res.revalidate(urlPath)` - [Revalidate a page on demand](/docs/pages/guides/incremental-static-regeneration#on-demand-revalidation-with-revalidatepath) using `getStaticProps`. `urlPath` must be a `string`.
|
||||
|
||||
### Setting the status code of a response
|
||||
|
||||
When sending a response back to the client, you can set the status code of the response.
|
||||
|
||||
The following example sets the status code of the response to `200` (`OK`) and returns a `message` property with the value of `Hello from Next.js!` as a JSON response:
|
||||
|
||||
```ts filename="pages/api/hello.ts" switcher
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
type ResponseData = {
|
||||
message: string
|
||||
}
|
||||
|
||||
export default function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse<ResponseData>
|
||||
) {
|
||||
res.status(200).json({ message: 'Hello from Next.js!' })
|
||||
}
|
||||
```
|
||||
|
||||
```js filename="pages/api/hello.js" switcher
|
||||
export default function handler(req, res) {
|
||||
res.status(200).json({ message: 'Hello from Next.js!' })
|
||||
}
|
||||
```
|
||||
|
||||
### Sending a JSON response
|
||||
|
||||
When sending a response back to the client you can send a JSON response, this must be a [serializable object](https://developer.mozilla.org/docs/Glossary/Serialization).
|
||||
In a real world application you might want to let the client know the status of the request depending on the result of the requested endpoint.
|
||||
|
||||
The following example sends a JSON response with the status code `200` (`OK`) and the result of the async operation. It's contained in a try catch block to handle any errors that may occur, with the appropriate status code and error message caught and sent back to the client:
|
||||
|
||||
```ts filename="pages/api/hello.ts" switcher
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
) {
|
||||
try {
|
||||
const result = await someAsyncOperation()
|
||||
res.status(200).json({ result })
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: 'failed to load data' })
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```js filename="pages/api/hello.js" switcher
|
||||
export default async function handler(req, res) {
|
||||
try {
|
||||
const result = await someAsyncOperation()
|
||||
res.status(200).json({ result })
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: 'failed to load data' })
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Sending a HTTP response
|
||||
|
||||
Sending an HTTP response works the same way as when sending a JSON response. The only difference is that the response body can be a `string`, an `object` or a `Buffer`.
|
||||
|
||||
The following example sends a HTTP response with the status code `200` (`OK`) and the result of the async operation.
|
||||
|
||||
```ts filename="pages/api/hello.ts" switcher
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
) {
|
||||
try {
|
||||
const result = await someAsyncOperation()
|
||||
res.status(200).send({ result })
|
||||
} catch (err) {
|
||||
res.status(500).send({ error: 'failed to fetch data' })
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```js filename="pages/api/hello.js" switcher
|
||||
export default async function handler(req, res) {
|
||||
try {
|
||||
const result = await someAsyncOperation()
|
||||
res.status(200).send({ result })
|
||||
} catch (err) {
|
||||
res.status(500).send({ error: 'failed to fetch data' })
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Redirects to a specified path or URL
|
||||
|
||||
Taking a form as an example, you may want to redirect your client to a specified path or URL once they have submitted the form.
|
||||
|
||||
The following example redirects the client to the `/` path if the form is successfully submitted:
|
||||
|
||||
```ts filename="pages/api/hello.ts" switcher
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
) {
|
||||
const { name, message } = req.body
|
||||
|
||||
try {
|
||||
await handleFormInputAsync({ name, message })
|
||||
res.redirect(307, '/')
|
||||
} catch (err) {
|
||||
res.status(500).send({ error: 'Failed to fetch data' })
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```js filename="pages/api/hello.js" switcher
|
||||
export default async function handler(req, res) {
|
||||
const { name, message } = req.body
|
||||
|
||||
try {
|
||||
await handleFormInputAsync({ name, message })
|
||||
res.redirect(307, '/')
|
||||
} catch (err) {
|
||||
res.status(500).send({ error: 'failed to fetch data' })
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Adding TypeScript types
|
||||
|
||||
You can make your API Routes more type-safe by importing the `NextApiRequest` and `NextApiResponse` types from `next`, in addition to those, you can also type your response data:
|
||||
|
||||
```ts
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
type ResponseData = {
|
||||
message: string
|
||||
}
|
||||
|
||||
export default function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse<ResponseData>
|
||||
) {
|
||||
res.status(200).json({ message: 'Hello from Next.js!' })
|
||||
}
|
||||
```
|
||||
|
||||
> **Good to know**: The body of `NextApiRequest` is `any` because the client may include any payload. You should validate the type/shape of the body at runtime before using it.
|
||||
|
||||
## Dynamic API Routes
|
||||
|
||||
API Routes support [dynamic routes](/docs/pages/building-your-application/routing/dynamic-routes), and follow the same file naming rules used for `pages/`.
|
||||
|
||||
```ts filename="pages/api/post/[pid].ts" switcher
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
export default function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
const { pid } = req.query
|
||||
res.end(`Post: ${pid}`)
|
||||
}
|
||||
```
|
||||
|
||||
```js filename="pages/api/post/[pid].js" switcher
|
||||
export default function handler(req, res) {
|
||||
const { pid } = req.query
|
||||
res.end(`Post: ${pid}`)
|
||||
}
|
||||
```
|
||||
|
||||
Now, a request to `/api/post/abc` will respond with the text: `Post: abc`.
|
||||
|
||||
### Catch all API routes
|
||||
|
||||
API Routes can be extended to catch all paths by adding three dots (`...`) inside the brackets. For example:
|
||||
|
||||
- `pages/api/post/[...slug].js` matches `/api/post/a`, but also `/api/post/a/b`, `/api/post/a/b/c` and so on.
|
||||
|
||||
> **Good to know**: You can use names other than `slug`, such as: `[...param]`
|
||||
|
||||
Matched parameters will be sent as a query parameter (`slug` in the example) to the page, and it will always be an array, so, the path `/api/post/a` will have the following `query` object:
|
||||
|
||||
```json
|
||||
{ "slug": ["a"] }
|
||||
```
|
||||
|
||||
And in the case of `/api/post/a/b`, and any other matching path, new parameters will be added to the array, like so:
|
||||
|
||||
```json
|
||||
{ "slug": ["a", "b"] }
|
||||
```
|
||||
|
||||
For example:
|
||||
|
||||
```ts filename="pages/api/post/[...slug].ts" switcher
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
export default function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
const { slug } = req.query
|
||||
res.end(`Post: ${slug.join(', ')}`)
|
||||
}
|
||||
```
|
||||
|
||||
```js filename="pages/api/post/[...slug].js" switcher
|
||||
export default function handler(req, res) {
|
||||
const { slug } = req.query
|
||||
res.end(`Post: ${slug.join(', ')}`)
|
||||
}
|
||||
```
|
||||
|
||||
Now, a request to `/api/post/a/b/c` will respond with the text: `Post: a, b, c`.
|
||||
|
||||
### Optional catch all API routes
|
||||
|
||||
Catch all routes can be made optional by including the parameter in double brackets (`[[...slug]]`).
|
||||
|
||||
For example, `pages/api/post/[[...slug]].js` will match `/api/post`, `/api/post/a`, `/api/post/a/b`, and so on.
|
||||
|
||||
The main difference between catch all and optional catch all routes is that with optional, the route without the parameter is also matched (`/api/post` in the example above).
|
||||
|
||||
The `query` objects are as follows:
|
||||
|
||||
```json
|
||||
{ } // GET `/api/post` (empty object)
|
||||
{ "slug": ["a"] } // `GET /api/post/a` (single-element array)
|
||||
{ "slug": ["a", "b"] } // `GET /api/post/a/b` (multi-element array)
|
||||
```
|
||||
|
||||
### Caveats
|
||||
|
||||
- Predefined API routes take precedence over dynamic API routes, and dynamic API routes over catch all API routes. Take a look at the following examples:
|
||||
- `pages/api/post/create.js` - Will match `/api/post/create`
|
||||
- `pages/api/post/[pid].js` - Will match `/api/post/1`, `/api/post/abc`, etc. But not `/api/post/create`
|
||||
- `pages/api/post/[...slug].js` - Will match `/api/post/1/2`, `/api/post/a/b/c`, etc. But not `/api/post/create`, `/api/post/abc`
|
||||
|
||||
## Streaming responses
|
||||
|
||||
While the Pages Router does support streaming responses with API Routes, we recommend incrementally adopting the App Router and using [Route Handlers](/docs/app/api-reference/file-conventions/route) if you are on Next.js 14+.
|
||||
|
||||
Here's how you can stream a response from an API Route with `writeHead`:
|
||||
|
||||
```ts filename="pages/api/hello.ts" switcher
|
||||
import { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
) {
|
||||
res.writeHead(200, {
|
||||
'Content-Type': 'text/event-stream',
|
||||
'Cache-Control': 'no-store',
|
||||
})
|
||||
let i = 0
|
||||
while (i < 10) {
|
||||
res.write(`data: ${i}\n\n`)
|
||||
i++
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000))
|
||||
}
|
||||
res.end()
|
||||
}
|
||||
```
|
||||
|
||||
```js filename="pages/api/hello.js" switcher
|
||||
export default async function handler(req, res) {
|
||||
res.writeHead(200, {
|
||||
'Content-Type': 'text/event-stream',
|
||||
'Cache-Control': 'no-store',
|
||||
})
|
||||
let i = 0
|
||||
while (i < 10) {
|
||||
res.write(`data: ${i}\n\n`)
|
||||
i++
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000))
|
||||
}
|
||||
res.end()
|
||||
}
|
||||
```
|
||||
98
node_modules/next/dist/docs/02-pages/03-building-your-application/01-routing/08-custom-error.md
generated
vendored
Normal file
98
node_modules/next/dist/docs/02-pages/03-building-your-application/01-routing/08-custom-error.md
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
---
|
||||
title: Custom Errors
|
||||
description: Override and extend the built-in Error page to handle custom errors.
|
||||
---
|
||||
|
||||
## 404 Page
|
||||
|
||||
A 404 page may be accessed very often. Server-rendering an error page for every visit increases the load of the Next.js server. This can result in increased costs and slow experiences.
|
||||
|
||||
To avoid the above pitfalls, Next.js provides a static 404 page by default without having to add any additional files.
|
||||
|
||||
### Customizing The 404 Page
|
||||
|
||||
To create a custom 404 page you can create a `pages/404.js` file. This file is statically generated at build time.
|
||||
|
||||
```jsx filename="pages/404.js"
|
||||
export default function Custom404() {
|
||||
return <h1>404 - Page Not Found</h1>
|
||||
}
|
||||
```
|
||||
|
||||
> **Good to know**: You can use [`getStaticProps`](/docs/pages/building-your-application/data-fetching/get-static-props) inside this page if you need to fetch data at build time.
|
||||
|
||||
## 500 Page
|
||||
|
||||
Server-rendering an error page for every visit adds complexity to responding to errors. To help users get responses to errors as fast as possible, Next.js provides a static 500 page by default without having to add any additional files.
|
||||
|
||||
### Customizing The 500 Page
|
||||
|
||||
To customize the 500 page you can create a `pages/500.js` file. This file is statically generated at build time.
|
||||
|
||||
```jsx filename="pages/500.js"
|
||||
export default function Custom500() {
|
||||
return <h1>500 - Server-side error occurred</h1>
|
||||
}
|
||||
```
|
||||
|
||||
> **Good to know**: You can use [`getStaticProps`](/docs/pages/building-your-application/data-fetching/get-static-props) inside this page if you need to fetch data at build time.
|
||||
|
||||
### More Advanced Error Page Customizing
|
||||
|
||||
500 errors are handled both client-side and server-side by the `Error` component. If you wish to override it, define the file `pages/_error.js` and add the following code:
|
||||
|
||||
```jsx
|
||||
function Error({ statusCode }) {
|
||||
return (
|
||||
<p>
|
||||
{statusCode
|
||||
? `An error ${statusCode} occurred on server`
|
||||
: 'An error occurred on client'}
|
||||
</p>
|
||||
)
|
||||
}
|
||||
|
||||
Error.getInitialProps = ({ res, err }) => {
|
||||
const statusCode = res ? res.statusCode : err ? err.statusCode : 404
|
||||
return { statusCode }
|
||||
}
|
||||
|
||||
export default Error
|
||||
```
|
||||
|
||||
> `pages/_error.js` is only used in production. In development you’ll get an error with the call stack to know where the error originated from.
|
||||
|
||||
### Reusing the built-in error page
|
||||
|
||||
If you want to render the built-in error page you can by importing the `Error` component:
|
||||
|
||||
```jsx
|
||||
import Error from 'next/error'
|
||||
|
||||
export async function getServerSideProps() {
|
||||
const res = await fetch('https://api.github.com/repos/vercel/next.js')
|
||||
const errorCode = res.ok ? false : res.status
|
||||
const json = await res.json()
|
||||
|
||||
return {
|
||||
props: { errorCode, stars: json.stargazers_count },
|
||||
}
|
||||
}
|
||||
|
||||
export default function Page({ errorCode, stars }) {
|
||||
if (errorCode) {
|
||||
return <Error statusCode={errorCode} />
|
||||
}
|
||||
|
||||
return <div>Next stars: {stars}</div>
|
||||
}
|
||||
```
|
||||
|
||||
The `Error` component also takes `title` as a property if you want to pass in a text message along with a `statusCode`.
|
||||
|
||||
If you have a custom `Error` component be sure to import that one instead. `next/error` exports the default component used by Next.js.
|
||||
|
||||
### Caveats
|
||||
|
||||
- `Error` does not currently support Next.js [Data Fetching methods](/docs/pages/building-your-application/data-fetching) like [`getStaticProps`](/docs/pages/building-your-application/data-fetching/get-static-props) or [`getServerSideProps`](/docs/pages/building-your-application/data-fetching/get-server-side-props).
|
||||
- `_error`, like `_app`, is a reserved pathname. `_error` is used to define the customized layouts and behaviors of the error pages. `/_error` will render 404 when accessed directly via [routing](/docs/pages/building-your-application/routing) or rendering in a [custom server](/docs/pages/guides/custom-server).
|
||||
6
node_modules/next/dist/docs/02-pages/03-building-your-application/01-routing/index.md
generated
vendored
Normal file
6
node_modules/next/dist/docs/02-pages/03-building-your-application/01-routing/index.md
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
title: Routing
|
||||
description: Learn the fundamentals of routing for front-end applications with the Pages Router.
|
||||
---
|
||||
|
||||
The Pages Router has a file-system based router built on concepts of pages. When a file is added to the `pages` directory it's automatically available as a route. Learn more about routing in the Pages Router:
|
||||
32
node_modules/next/dist/docs/02-pages/03-building-your-application/02-rendering/01-server-side-rendering.md
generated
vendored
Normal file
32
node_modules/next/dist/docs/02-pages/03-building-your-application/02-rendering/01-server-side-rendering.md
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
title: Server-side Rendering (SSR)
|
||||
description: Use Server-side Rendering to render pages on each request.
|
||||
---
|
||||
|
||||
> Also referred to as "SSR" or "Dynamic Rendering".
|
||||
|
||||
If a page uses **Server-side Rendering**, the page HTML is generated on **each request**.
|
||||
|
||||
To use Server-side Rendering for a page, you need to `export` an `async` function called `getServerSideProps`. This function will be called by the server on every request.
|
||||
|
||||
For example, suppose that your page needs to prerender frequently updated data (fetched from an external API). You can write `getServerSideProps` which fetches this data and passes it to `Page` like below:
|
||||
|
||||
```jsx
|
||||
export default function Page({ data }) {
|
||||
// Render data...
|
||||
}
|
||||
|
||||
// This gets called on every request
|
||||
export async function getServerSideProps() {
|
||||
// Fetch data from external API
|
||||
const res = await fetch(`https://.../data`)
|
||||
const data = await res.json()
|
||||
|
||||
// Pass data to the page via props
|
||||
return { props: { data } }
|
||||
}
|
||||
```
|
||||
|
||||
As you can see, `getServerSideProps` is similar to `getStaticProps`, but the difference is that `getServerSideProps` is run on every request instead of on build time.
|
||||
|
||||
To learn more about how `getServerSideProps` works, check out our [Data Fetching documentation](/docs/pages/building-your-application/data-fetching/get-server-side-props).
|
||||
183
node_modules/next/dist/docs/02-pages/03-building-your-application/02-rendering/02-static-site-generation.md
generated
vendored
Normal file
183
node_modules/next/dist/docs/02-pages/03-building-your-application/02-rendering/02-static-site-generation.md
generated
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
---
|
||||
title: Static Site Generation (SSG)
|
||||
description: Use Static Site Generation (SSG) to prerender pages at build time.
|
||||
---
|
||||
|
||||
<details>
|
||||
<summary>Examples</summary>
|
||||
|
||||
- [Agility CMS Example](https://github.com/vercel/next.js/tree/canary/examples/cms-agilitycms) ([Demo](https://next-blog-agilitycms.vercel.app/))
|
||||
- [Builder.io Example](https://github.com/vercel/next.js/tree/canary/examples/cms-builder-io) ([Demo](https://cms-builder-io.vercel.app/))
|
||||
- [ButterCMS Example](https://github.com/vercel/next.js/tree/canary/examples/cms-buttercms) ([Demo](https://next-blog-buttercms.vercel.app/))
|
||||
- [Contentful Example](https://github.com/vercel/next.js/tree/canary/examples/cms-contentful) ([Demo](https://app-router-contentful.vercel.app/))
|
||||
- [Cosmic Example](https://github.com/vercel/next.js/tree/canary/examples/cms-cosmic) ([Demo](https://next-blog-cosmic.vercel.app/))
|
||||
- [DatoCMS Example](https://github.com/vercel/next.js/tree/canary/examples/cms-datocms) ([Demo](https://next-blog-datocms.vercel.app/))
|
||||
- [DotCMS Example](https://github.com/vercel/next.js/tree/canary/examples/cms-dotcms) ([Demo](https://nextjs-dotcms-blog.vercel.app/))
|
||||
- [Drupal Example](https://github.com/vercel/next.js/tree/canary/examples/cms-drupal) ([Demo](https://cms-drupal.vercel.app/))
|
||||
- [Enterspeed Example](https://github.com/vercel/next.js/tree/canary/examples/cms-enterspeed) ([Demo](https://next-blog-demo.enterspeed.com/))
|
||||
- [GraphCMS Example](https://github.com/vercel/next.js/tree/canary/examples/cms-graphcms) ([Demo](https://next-blog-graphcms.vercel.app/))
|
||||
- [Keystone Example](https://github.com/vercel/next.js/tree/canary/examples/cms-keystonejs-embedded) ([Demo](https://nextjs-keystone-demo.vercel.app/))
|
||||
- [Kontent.ai Example](https://github.com/vercel/next.js/tree/canary/examples/cms-kontent-ai) ([Demo](https://next-blog-kontent-ai.vercel.app/))
|
||||
- [Makeswift Example](https://github.com/vercel/next.js/tree/canary/examples/cms-makeswift) ([Demo](https://nextjs-makeswift-example.vercel.app/))
|
||||
- [Plasmic Example](https://github.com/vercel/next.js/tree/canary/examples/cms-plasmic) ([Demo](https://nextjs-plasmic-example.vercel.app/))
|
||||
- [Prepr Example](https://github.com/vercel/next.js/tree/canary/examples/cms-prepr) ([Demo](https://next-blog-prepr.vercel.app/))
|
||||
- [Prismic Example](https://github.com/vercel/next.js/tree/canary/examples/cms-prismic) ([Demo](https://next-blog-prismic.vercel.app/))
|
||||
- [Sanity Example](https://github.com/vercel/next.js/tree/canary/examples/cms-sanity) ([Demo](https://next-blog.sanity.build/))
|
||||
- [Sitecore XM Cloud Example](https://github.com/vercel/next.js/tree/canary/examples/cms-sitecore-xmcloud) ([Demo](https://vercel-sitecore-xmcloud-demo.vercel.app/))
|
||||
- [Storyblok Example](https://github.com/vercel/next.js/tree/canary/examples/cms-storyblok) ([Demo](https://next-blog-storyblok.vercel.app/))
|
||||
- [Strapi Example](https://github.com/vercel/next.js/tree/canary/examples/cms-strapi) ([Demo](https://next-blog-strapi.vercel.app/))
|
||||
- [TakeShape Example](https://github.com/vercel/next.js/tree/canary/examples/cms-takeshape) ([Demo](https://next-blog-takeshape.vercel.app/))
|
||||
- [Tina Example](https://github.com/vercel/next.js/tree/canary/examples/cms-tina) ([Demo](https://cms-tina-example.vercel.app/))
|
||||
- [Umbraco Example](https://github.com/vercel/next.js/tree/canary/examples/cms-umbraco) ([Demo](https://nextjs-umbraco-sample-blog.vercel.app/))
|
||||
- [Umbraco Heartcore Example](https://github.com/vercel/next.js/tree/canary/examples/cms-umbraco-heartcore) ([Demo](https://next-blog-umbraco-heartcore.vercel.app/))
|
||||
- [Webiny Example](https://github.com/vercel/next.js/tree/canary/examples/cms-webiny) ([Demo](https://webiny-headlesscms-nextjs-example.vercel.app/))
|
||||
- [WordPress Example](https://github.com/vercel/next.js/tree/canary/examples/cms-wordpress) ([Demo](https://next-blog-wordpress.vercel.app/))
|
||||
- [Blog Starter Example](https://github.com/vercel/next.js/tree/canary/examples/blog-starter) ([Demo](https://next-blog-starter.vercel.app/))
|
||||
- [Static Tweet (Demo)](https://react-tweet.vercel.app/)
|
||||
|
||||
</details>
|
||||
|
||||
If a page uses **Static Generation**, the page HTML is generated at **build time**. That means in production, the page HTML is generated when you run `next build`. This HTML will then be reused on each request. It can be cached by a CDN.
|
||||
|
||||
In Next.js, you can statically generate pages **with or without data**. Let's take a look at each case.
|
||||
|
||||
### Static Generation without data
|
||||
|
||||
By default, Next.js prerenders pages using Static Generation without fetching data. Here's an example:
|
||||
|
||||
```jsx
|
||||
function About() {
|
||||
return <div>About</div>
|
||||
}
|
||||
|
||||
export default About
|
||||
```
|
||||
|
||||
Note that this page does not need to fetch any external data to be prerendered. In cases like this, Next.js generates a single HTML file per page during build time.
|
||||
|
||||
### Static Generation with data
|
||||
|
||||
Some pages require fetching external data for prerendering. There are two scenarios, and one or both might apply. In each case, you can use these functions that Next.js provides:
|
||||
|
||||
1. Your page **content** depends on external data: Use `getStaticProps`.
|
||||
2. Your page **paths** depend on external data: Use `getStaticPaths` (usually in addition to `getStaticProps`).
|
||||
|
||||
#### Scenario 1: Your page content depends on external data
|
||||
|
||||
**Example**: Your blog page might need to fetch the list of blog posts from a CMS (content management system).
|
||||
|
||||
```jsx
|
||||
// TODO: Need to fetch `posts` (by calling some API endpoint)
|
||||
// before this page can be prerendered.
|
||||
export default function Blog({ posts }) {
|
||||
return (
|
||||
<ul>
|
||||
{posts.map((post) => (
|
||||
<li>{post.title}</li>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
To fetch this data on prerender, Next.js allows you to `export` an `async` function called `getStaticProps` from the same file. This function gets called at build time and lets you pass fetched data to the page's `props` on prerender.
|
||||
|
||||
```jsx
|
||||
export default function Blog({ posts }) {
|
||||
// Render posts...
|
||||
}
|
||||
|
||||
// This function gets called at build time
|
||||
export async function getStaticProps() {
|
||||
// Call an external API endpoint to get posts
|
||||
const res = await fetch('https://.../posts')
|
||||
const posts = await res.json()
|
||||
|
||||
// By returning { props: { posts } }, the Blog component
|
||||
// will receive `posts` as a prop at build time
|
||||
return {
|
||||
props: {
|
||||
posts,
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To learn more about how `getStaticProps` works, check out the [Data Fetching documentation](/docs/pages/building-your-application/data-fetching/get-static-props).
|
||||
|
||||
#### Scenario 2: Your page paths depend on external data
|
||||
|
||||
Next.js allows you to create pages with **dynamic routes**. For example, you can create a file called `pages/posts/[id].js` to show a single blog post based on `id`. This will allow you to show a blog post with `id: 1` when you access `posts/1`.
|
||||
|
||||
> To learn more about dynamic routing, check the [Dynamic Routing documentation](/docs/pages/building-your-application/routing/dynamic-routes).
|
||||
|
||||
However, which `id` you want to prerender at build time might depend on external data.
|
||||
|
||||
**Example**: suppose that you've only added one blog post (with `id: 1`) to the database. In this case, you'd only want to prerender `posts/1` at build time.
|
||||
|
||||
Later, you might add the second post with `id: 2`. Then you'd want to prerender `posts/2` as well.
|
||||
|
||||
So your page **paths** that are prerendered depend on external data. To handle this, Next.js lets you `export` an `async` function called `getStaticPaths` from a dynamic page (`pages/posts/[id].js` in this case). This function gets called at build time and lets you specify which paths you want to prerender.
|
||||
|
||||
```jsx
|
||||
// This function gets called at build time
|
||||
export async function getStaticPaths() {
|
||||
// Call an external API endpoint to get posts
|
||||
const res = await fetch('https://.../posts')
|
||||
const posts = await res.json()
|
||||
|
||||
// Get the paths we want to prerender based on posts
|
||||
const paths = posts.map((post) => ({
|
||||
params: { id: post.id },
|
||||
}))
|
||||
|
||||
// We'll prerender only these paths at build time.
|
||||
// { fallback: false } means other routes should 404.
|
||||
return { paths, fallback: false }
|
||||
}
|
||||
```
|
||||
|
||||
Also in `pages/posts/[id].js`, you need to export `getStaticProps` so that you can fetch the data about the post with this `id` and use it to prerender the page:
|
||||
|
||||
```jsx
|
||||
export default function Post({ post }) {
|
||||
// Render post...
|
||||
}
|
||||
|
||||
export async function getStaticPaths() {
|
||||
// ...
|
||||
}
|
||||
|
||||
// This also gets called at build time
|
||||
export async function getStaticProps({ params }) {
|
||||
// params contains the post `id`.
|
||||
// If the route is like /posts/1, then params.id is 1
|
||||
const res = await fetch(`https://.../posts/${params.id}`)
|
||||
const post = await res.json()
|
||||
|
||||
// Pass post data to the page via props
|
||||
return { props: { post } }
|
||||
}
|
||||
```
|
||||
|
||||
To learn more about how `getStaticPaths` works, check out the [Data Fetching documentation](/docs/pages/building-your-application/data-fetching/get-static-paths).
|
||||
|
||||
### When should I use Static Generation?
|
||||
|
||||
We recommend using **Static Generation** (with and without data) whenever possible because your page can be built once and served by CDN, which makes it much faster than having a server render the page on every request.
|
||||
|
||||
You can use Static Generation for many types of pages, including:
|
||||
|
||||
- Marketing pages
|
||||
- Blog posts and portfolios
|
||||
- E-commerce product listings
|
||||
- Help and documentation
|
||||
|
||||
You should ask yourself: "Can I prerender this page **ahead** of a user's request?" If the answer is yes, then you should choose Static Generation.
|
||||
|
||||
On the other hand, Static Generation is **not** a good idea if you cannot prerender a page ahead of a user's request. Maybe your page shows frequently updated data, and the page content changes on every request.
|
||||
|
||||
In cases like this, you can do one of the following:
|
||||
|
||||
- Use Static Generation with **Client-side data fetching:** You can skip prerendering some parts of a page and then use client-side JavaScript to populate them. To learn more about this approach, check out the [Data Fetching documentation](/docs/pages/building-your-application/data-fetching/client-side).
|
||||
- Use **Server-Side Rendering:** Next.js prerenders a page on each request. It will be slower because the page cannot be cached by a CDN, but the prerendered page will always be up-to-date. We'll talk about this approach below.
|
||||
48
node_modules/next/dist/docs/02-pages/03-building-your-application/02-rendering/04-automatic-static-optimization.md
generated
vendored
Normal file
48
node_modules/next/dist/docs/02-pages/03-building-your-application/02-rendering/04-automatic-static-optimization.md
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
---
|
||||
title: Automatic Static Optimization
|
||||
description: Next.js automatically optimizes your app to be static HTML whenever possible. Learn how it works here.
|
||||
---
|
||||
|
||||
Next.js automatically determines that a page is static (can be prerendered) if it has no blocking data requirements. This determination is made by the absence of `getServerSideProps` and `getInitialProps` in the page.
|
||||
|
||||
This feature allows Next.js to emit hybrid applications that contain **both server-rendered and statically generated pages**.
|
||||
|
||||
> **Good to know**: Statically generated pages are still reactive. Next.js will hydrate your application client-side to give it full interactivity.
|
||||
|
||||
One of the main benefits of this feature is that optimized pages require no server-side computation, and can be instantly streamed to the end-user from multiple CDN locations. The result is an _ultra fast_ loading experience for your users.
|
||||
|
||||
## How it works
|
||||
|
||||
If `getServerSideProps` or `getInitialProps` is present in a page, Next.js will switch to render the page on-demand, per-request (meaning [Server-Side Rendering](/docs/pages/building-your-application/rendering/server-side-rendering)).
|
||||
|
||||
If the above is not the case, Next.js will **statically optimize** your page automatically by prerendering the page to static HTML.
|
||||
|
||||
During prerendering, the router's `query` object will be empty since we do not have `query` information to provide during this phase. After hydration, Next.js will trigger an update to your application to provide the route parameters in the `query` object.
|
||||
|
||||
The cases where the query will be updated after hydration triggering another render are:
|
||||
|
||||
- The page is a [dynamic-route](/docs/pages/building-your-application/routing/dynamic-routes).
|
||||
- The page has query values in the URL.
|
||||
- [Rewrites](/docs/pages/api-reference/config/next-config-js/rewrites) are configured in your `next.config.js` since these can have parameters that may need to be parsed and provided in the `query`.
|
||||
|
||||
To be able to distinguish if the query is fully updated and ready for use, you can leverage the `isReady` field on [`next/router`](/docs/pages/api-reference/functions/use-router#router-object).
|
||||
|
||||
> **Good to know**: Parameters added with [dynamic routes](/docs/pages/building-your-application/routing/dynamic-routes) to a page that's using [`getStaticProps`](/docs/pages/building-your-application/data-fetching/get-static-props) will always be available inside the `query` object.
|
||||
|
||||
`next build` will emit `.html` files for statically optimized pages. For example, the result for the page `pages/about.js` would be:
|
||||
|
||||
```bash filename="Terminal"
|
||||
.next/server/pages/about.html
|
||||
```
|
||||
|
||||
And if you add `getServerSideProps` to the page, it will then be JavaScript, like so:
|
||||
|
||||
```bash filename="Terminal"
|
||||
.next/server/pages/about.js
|
||||
```
|
||||
|
||||
## Caveats
|
||||
|
||||
- If you have a [custom `App`](/docs/pages/building-your-application/routing/custom-app) with `getInitialProps` then this optimization will be turned off in pages without [Static Generation](/docs/pages/building-your-application/data-fetching/get-static-props).
|
||||
- If you have a [custom `Document`](/docs/pages/building-your-application/routing/custom-document) with `getInitialProps` be sure you check if `ctx.req` is defined before assuming the page is server-side rendered. `ctx.req` will be `undefined` for pages that are prerendered.
|
||||
- Avoid using the `asPath` value on [`next/router`](/docs/pages/api-reference/functions/use-router#router-object) in the rendering tree until the router's `isReady` field is `true`. Statically optimized pages only know `asPath` on the client and not the server, so using it as a prop may lead to mismatch errors. The [`active-class-name` example](https://github.com/vercel/next.js/tree/canary/examples/active-class-name) demonstrates one way to use `asPath` as a prop.
|
||||
71
node_modules/next/dist/docs/02-pages/03-building-your-application/02-rendering/05-client-side-rendering.md
generated
vendored
Normal file
71
node_modules/next/dist/docs/02-pages/03-building-your-application/02-rendering/05-client-side-rendering.md
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
---
|
||||
title: Client-side Rendering (CSR)
|
||||
description: Learn how to implement client-side rendering in the Pages Router.
|
||||
related:
|
||||
description: Learn about the alternative rendering methods in Next.js.
|
||||
links:
|
||||
- pages/building-your-application/rendering/server-side-rendering
|
||||
- pages/building-your-application/rendering/static-site-generation
|
||||
- pages/guides/incremental-static-regeneration
|
||||
---
|
||||
|
||||
In Client-Side Rendering (CSR) with React, the browser downloads a minimal HTML page and the JavaScript needed for the page. The JavaScript is then used to update the DOM and render the page. When the application is first loaded, the user may notice a slight delay before they can see the full page, this is because the page isn't fully rendered until all the JavaScript is downloaded, parsed, and executed.
|
||||
|
||||
After the page has been loaded for the first time, navigating to other pages on the same website is typically faster, as only necessary data needs to be fetched, and JavaScript can re-render parts of the page without requiring a full page refresh.
|
||||
|
||||
In Next.js, there are two ways you can implement client-side rendering:
|
||||
|
||||
1. Using React's `useEffect()` hook inside your pages instead of the server-side rendering methods ([`getStaticProps`](/docs/pages/building-your-application/data-fetching/get-static-props) and [`getServerSideProps`](/docs/pages/building-your-application/data-fetching/get-server-side-props)).
|
||||
2. Using a data fetching library like [SWR](https://swr.vercel.app/) or [TanStack Query](https://tanstack.com/query/latest/) to fetch data on the client (recommended).
|
||||
|
||||
Here's an example of using `useEffect()` inside a Next.js page:
|
||||
|
||||
```jsx filename="pages/index.js"
|
||||
import React, { useState, useEffect } from 'react'
|
||||
|
||||
export function Page() {
|
||||
const [data, setData] = useState(null)
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
const response = await fetch('https://api.example.com/data')
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`)
|
||||
}
|
||||
const result = await response.json()
|
||||
setData(result)
|
||||
}
|
||||
|
||||
fetchData().catch((e) => {
|
||||
// handle the error as needed
|
||||
console.error('An error occurred while fetching the data: ', e)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return <p>{data ? `Your data: ${data}` : 'Loading...'}</p>
|
||||
}
|
||||
```
|
||||
|
||||
In the example above, the component starts by rendering `Loading...`. Then, once the data is fetched, it re-renders and displays the data.
|
||||
|
||||
Although fetching data in a `useEffect` is a pattern you may see in older React Applications, we recommend using a data-fetching library for better performance, caching, optimistic updates, and more. Here's a minimum example using [SWR](https://swr.vercel.app/) to fetch data on the client:
|
||||
|
||||
```jsx filename="pages/index.js"
|
||||
import useSWR from 'swr'
|
||||
|
||||
export function Page() {
|
||||
const { data, error, isLoading } = useSWR(
|
||||
'https://api.example.com/data',
|
||||
fetcher
|
||||
)
|
||||
|
||||
if (error) return <p>Failed to load.</p>
|
||||
if (isLoading) return <p>Loading...</p>
|
||||
|
||||
return <p>Your Data: {data}</p>
|
||||
}
|
||||
```
|
||||
|
||||
> **Good to know**:
|
||||
>
|
||||
> Keep in mind that CSR can impact SEO. Some search engine crawlers might not execute JavaScript and therefore only see the initial empty or loading state of your application. It can also lead to performance issues for users with slower internet connections or devices, as they need to wait for all the JavaScript to load and run before they can see the full page. Next.js promotes a hybrid approach that allows you to use a combination of [server-side rendering](/docs/pages/building-your-application/rendering/server-side-rendering), [static site generation](/docs/pages/building-your-application/rendering/static-site-generation), and client-side rendering, **depending on the needs of each page** in your application. In the App Router, you can also use [Loading UI with Suspense](/docs/app/api-reference/file-conventions/loading) to show a loading indicator while the page is being rendered.
|
||||
21
node_modules/next/dist/docs/02-pages/03-building-your-application/02-rendering/index.md
generated
vendored
Normal file
21
node_modules/next/dist/docs/02-pages/03-building-your-application/02-rendering/index.md
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
title: Rendering
|
||||
description: Learn the fundamentals of rendering in React and Next.js.
|
||||
---
|
||||
|
||||
By default, Next.js **prerenders** every page. This means that Next.js generates HTML for each page in advance, instead of having it all done by client-side JavaScript. Prerendering can result in better performance and SEO.
|
||||
|
||||
Each generated HTML is associated with minimal JavaScript code necessary for that page. When a page is loaded by the browser, its JavaScript code runs and makes the page fully interactive (this process is called [hydration](https://react.dev/reference/react-dom/client/hydrateRoot) in React).
|
||||
|
||||
### Prerendering
|
||||
|
||||
Next.js has two forms of prerendering: **Static Generation** and **Server-side Rendering**. The difference is in **when** it generates the HTML for a page.
|
||||
|
||||
- Static Generation: The HTML is generated at **build time** and will be reused on each request.
|
||||
- Server-side Rendering: The HTML is generated on **each request**.
|
||||
|
||||
Importantly, Next.js lets you choose which prerendering form you'd like to use for each page. You can create a "hybrid" Next.js app by using Static Generation for most pages and using Server-side Rendering for others.
|
||||
|
||||
We recommend using Static Generation over Server-side Rendering for performance reasons. Statically generated pages can be cached by CDN with no extra configuration to boost performance. However, in some cases, Server-side Rendering might be the only option.
|
||||
|
||||
You can also use client-side data fetching along with Static Generation or Server-side Rendering. That means some parts of a page can be rendered entirely by clientside JavaScript. To learn more, take a look at the [Data Fetching](/docs/pages/building-your-application/data-fetching/client-side) documentation.
|
||||
202
node_modules/next/dist/docs/02-pages/03-building-your-application/03-data-fetching/01-get-static-props.md
generated
vendored
Normal file
202
node_modules/next/dist/docs/02-pages/03-building-your-application/03-data-fetching/01-get-static-props.md
generated
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
---
|
||||
title: getStaticProps
|
||||
description: Fetch data and generate static pages with `getStaticProps`. Learn more about this API for data fetching in Next.js.
|
||||
---
|
||||
|
||||
If you export a function called `getStaticProps` (Static Site Generation) from a page, Next.js will prerender this page at build time using the props returned by `getStaticProps`.
|
||||
|
||||
```tsx filename="pages/index.tsx" switcher
|
||||
import type { InferGetStaticPropsType, GetStaticProps } from 'next'
|
||||
|
||||
type Repo = {
|
||||
name: string
|
||||
stargazers_count: number
|
||||
}
|
||||
|
||||
export const getStaticProps = (async (context) => {
|
||||
const res = await fetch('https://api.github.com/repos/vercel/next.js')
|
||||
const repo = await res.json()
|
||||
return { props: { repo } }
|
||||
}) satisfies GetStaticProps<{
|
||||
repo: Repo
|
||||
}>
|
||||
|
||||
export default function Page({
|
||||
repo,
|
||||
}: InferGetStaticPropsType<typeof getStaticProps>) {
|
||||
return repo.stargazers_count
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/index.js" switcher
|
||||
export async function getStaticProps() {
|
||||
const res = await fetch('https://api.github.com/repos/vercel/next.js')
|
||||
const repo = await res.json()
|
||||
return { props: { repo } }
|
||||
}
|
||||
|
||||
export default function Page({ repo }) {
|
||||
return repo.stargazers_count
|
||||
}
|
||||
```
|
||||
|
||||
> Note that irrespective of rendering type, any `props` will be passed to the page component and can be viewed on the client-side in the initial HTML. This is to allow the page to be [hydrated](https://react.dev/reference/react-dom/hydrate) correctly. Make sure that you don't pass any sensitive information that shouldn't be available on the client in `props`.
|
||||
|
||||
The [`getStaticProps` API reference](/docs/pages/api-reference/functions/get-static-props) covers all parameters and props that can be used with `getStaticProps`.
|
||||
|
||||
## When should I use getStaticProps?
|
||||
|
||||
You should use `getStaticProps` if:
|
||||
|
||||
- The data required to render the page is available at build time ahead of a user’s request
|
||||
- The data comes from a headless CMS
|
||||
- The page must be prerendered (for SEO) and be very fast — `getStaticProps` generates `HTML` and `JSON` files, both of which can be cached by a CDN for performance
|
||||
- The data can be publicly cached (not user-specific). This condition can be bypassed in certain specific situation by using a Proxy to rewrite the path.
|
||||
|
||||
## When does getStaticProps run
|
||||
|
||||
`getStaticProps` always runs on the server and never on the client. You can validate code written inside `getStaticProps` is removed from the client-side bundle [with this tool](https://next-code-elimination.vercel.app/).
|
||||
|
||||
- `getStaticProps` always runs during `next build`
|
||||
- `getStaticProps` runs in the background when using [`fallback: true`](/docs/pages/api-reference/functions/get-static-paths#fallback-true)
|
||||
- `getStaticProps` is called before initial render when using [`fallback: blocking`](/docs/pages/api-reference/functions/get-static-paths#fallback-blocking)
|
||||
- `getStaticProps` runs in the background when using `revalidate`
|
||||
- `getStaticProps` runs on-demand in the background when using [`revalidate()`](/docs/pages/guides/incremental-static-regeneration#on-demand-revalidation-with-revalidatepath)
|
||||
|
||||
When combined with [Incremental Static Regeneration](/docs/pages/guides/incremental-static-regeneration), `getStaticProps` will run in the background while the stale page is being revalidated, and the fresh page served to the browser.
|
||||
|
||||
`getStaticProps` does not have access to the incoming request (such as query parameters or HTTP headers) as it generates static HTML. If you need access to the request for your page, consider using [Proxy](/docs/pages/api-reference/file-conventions/proxy) in addition to `getStaticProps`.
|
||||
|
||||
## Using getStaticProps to fetch data from a CMS
|
||||
|
||||
The following example shows how you can fetch a list of blog posts from a CMS.
|
||||
|
||||
```tsx filename="pages/blog.tsx" switcher
|
||||
// posts will be populated at build time by getStaticProps()
|
||||
export default function Blog({ posts }) {
|
||||
return (
|
||||
<ul>
|
||||
{posts.map((post) => (
|
||||
<li>{post.title}</li>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
|
||||
// This function gets called at build time on server-side.
|
||||
// It won't be called on client-side, so you can even do
|
||||
// direct database queries.
|
||||
export async function getStaticProps() {
|
||||
// Call an external API endpoint to get posts.
|
||||
// You can use any data fetching library
|
||||
const res = await fetch('https://.../posts')
|
||||
const posts = await res.json()
|
||||
|
||||
// By returning { props: { posts } }, the Blog component
|
||||
// will receive `posts` as a prop at build time
|
||||
return {
|
||||
props: {
|
||||
posts,
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/blog.js" switcher
|
||||
// posts will be populated at build time by getStaticProps()
|
||||
export default function Blog({ posts }) {
|
||||
return (
|
||||
<ul>
|
||||
{posts.map((post) => (
|
||||
<li>{post.title}</li>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
|
||||
// This function gets called at build time on server-side.
|
||||
// It won't be called on client-side, so you can even do
|
||||
// direct database queries.
|
||||
export async function getStaticProps() {
|
||||
// Call an external API endpoint to get posts.
|
||||
// You can use any data fetching library
|
||||
const res = await fetch('https://.../posts')
|
||||
const posts = await res.json()
|
||||
|
||||
// By returning { props: { posts } }, the Blog component
|
||||
// will receive `posts` as a prop at build time
|
||||
return {
|
||||
props: {
|
||||
posts,
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The [`getStaticProps` API reference](/docs/pages/api-reference/functions/get-static-props) covers all parameters and props that can be used with `getStaticProps`.
|
||||
|
||||
## Write server-side code directly
|
||||
|
||||
As `getStaticProps` runs only on the server-side, it will never run on the client-side. It won’t even be included in the JS bundle for the browser, so you can write direct database queries without them being sent to browsers.
|
||||
|
||||
This means that instead of fetching an **API route** from `getStaticProps` (that itself fetches data from an external source), you can write the server-side code directly in `getStaticProps`.
|
||||
|
||||
Take the following example. An API route is used to fetch some data from a CMS. That API route is then called directly from `getStaticProps`. This produces an additional call, reducing performance. Instead, the logic for fetching the data from the CMS can be shared by using a `lib/` directory. Then it can be shared with `getStaticProps`.
|
||||
|
||||
```js filename="lib/load-posts.js"
|
||||
// The following function is shared
|
||||
// with getStaticProps and API routes
|
||||
// from a `lib/` directory
|
||||
export async function loadPosts() {
|
||||
// Call an external API endpoint to get posts
|
||||
const res = await fetch('https://.../posts/')
|
||||
const data = await res.json()
|
||||
|
||||
return data
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/blog.js"
|
||||
// pages/blog.js
|
||||
import { loadPosts } from '../lib/load-posts'
|
||||
|
||||
// This function runs only on the server side
|
||||
export async function getStaticProps() {
|
||||
// Instead of fetching your `/api` route you can call the same
|
||||
// function directly in `getStaticProps`
|
||||
const posts = await loadPosts()
|
||||
|
||||
// Props returned will be passed to the page component
|
||||
return { props: { posts } }
|
||||
}
|
||||
```
|
||||
|
||||
Alternatively, if you are **not** using API routes to fetch data, then the [`fetch()`](https://developer.mozilla.org/docs/Web/API/Fetch_API) API _can_ be used directly in `getStaticProps` to fetch data.
|
||||
|
||||
To verify what Next.js eliminates from the client-side bundle, you can use the [next-code-elimination tool](https://next-code-elimination.vercel.app/).
|
||||
|
||||
## Statically generates both HTML and JSON
|
||||
|
||||
When a page with `getStaticProps` is prerendered at build time, in addition to the page HTML file, Next.js generates a JSON file holding the result of running `getStaticProps`.
|
||||
|
||||
This JSON file will be used in client-side routing through [`next/link`](/docs/pages/api-reference/components/link) or [`next/router`](/docs/pages/api-reference/functions/use-router). When you navigate to a page that’s prerendered using `getStaticProps`, Next.js fetches this JSON file (pre-computed at build time) and uses it as the props for the page component. This means that client-side page transitions will **not** call `getStaticProps` as only the exported JSON is used.
|
||||
|
||||
When using Incremental Static Generation, `getStaticProps` will be executed in the background to generate the JSON needed for client-side navigation. You may see this in the form of multiple requests being made for the same page, however, this is intended and has no impact on end-user performance.
|
||||
|
||||
## Where can I use getStaticProps
|
||||
|
||||
`getStaticProps` can only be exported from a **page**. You **cannot** export it from non-page files, `_app`, `_document`, or `_error`.
|
||||
|
||||
One of the reasons for this restriction is that React needs to have all the required data before the page is rendered.
|
||||
|
||||
Also, you must use export `getStaticProps` as a standalone function — it will **not** work if you add `getStaticProps` as a property of the page component.
|
||||
|
||||
> **Good to know**: if you have created a [custom app](/docs/pages/building-your-application/routing/custom-app), ensure you are passing the `pageProps` to the page component as shown in the linked document, otherwise the props will be empty.
|
||||
|
||||
## Runs on every request in development
|
||||
|
||||
In development (`next dev`), `getStaticProps` will be called on every request.
|
||||
|
||||
## Preview Mode
|
||||
|
||||
You can temporarily bypass static generation and render the page at **request time** instead of build time using [**Preview Mode**](/docs/pages/guides/preview-mode). For example, you might be using a headless CMS and want to preview drafts before they're published.
|
||||
141
node_modules/next/dist/docs/02-pages/03-building-your-application/03-data-fetching/02-get-static-paths.md
generated
vendored
Normal file
141
node_modules/next/dist/docs/02-pages/03-building-your-application/03-data-fetching/02-get-static-paths.md
generated
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
---
|
||||
title: getStaticPaths
|
||||
description: Fetch data and generate static pages with `getStaticPaths`. Learn more about this API for data fetching in Next.js.
|
||||
---
|
||||
|
||||
If a page has [Dynamic Routes](/docs/pages/building-your-application/routing/dynamic-routes) and uses `getStaticProps`, it needs to define a list of paths to be statically generated.
|
||||
|
||||
When you export a function called `getStaticPaths` (Static Site Generation) from a page that uses dynamic routes, Next.js will statically prerender all the paths specified by `getStaticPaths`.
|
||||
|
||||
```tsx filename="pages/repo/[name].tsx" switcher
|
||||
import type {
|
||||
InferGetStaticPropsType,
|
||||
GetStaticProps,
|
||||
GetStaticPaths,
|
||||
} from 'next'
|
||||
|
||||
type Repo = {
|
||||
name: string
|
||||
stargazers_count: number
|
||||
}
|
||||
|
||||
export const getStaticPaths = (async () => {
|
||||
return {
|
||||
paths: [
|
||||
{
|
||||
params: {
|
||||
name: 'next.js',
|
||||
},
|
||||
}, // See the "paths" section below
|
||||
],
|
||||
fallback: true, // false or "blocking"
|
||||
}
|
||||
}) satisfies GetStaticPaths
|
||||
|
||||
export const getStaticProps = (async (context) => {
|
||||
const res = await fetch('https://api.github.com/repos/vercel/next.js')
|
||||
const repo = await res.json()
|
||||
return { props: { repo } }
|
||||
}) satisfies GetStaticProps<{
|
||||
repo: Repo
|
||||
}>
|
||||
|
||||
export default function Page({
|
||||
repo,
|
||||
}: InferGetStaticPropsType<typeof getStaticProps>) {
|
||||
return repo.stargazers_count
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/repo/[name].js" switcher
|
||||
export async function getStaticPaths() {
|
||||
return {
|
||||
paths: [
|
||||
{
|
||||
params: {
|
||||
name: 'next.js',
|
||||
},
|
||||
}, // See the "paths" section below
|
||||
],
|
||||
fallback: true, // false or "blocking"
|
||||
}
|
||||
}
|
||||
|
||||
export async function getStaticProps() {
|
||||
const res = await fetch('https://api.github.com/repos/vercel/next.js')
|
||||
const repo = await res.json()
|
||||
return { props: { repo } }
|
||||
}
|
||||
|
||||
export default function Page({ repo }) {
|
||||
return repo.stargazers_count
|
||||
}
|
||||
```
|
||||
|
||||
The [`getStaticPaths` API reference](/docs/pages/api-reference/functions/get-static-paths) covers all parameters and props that can be used with `getStaticPaths`.
|
||||
|
||||
## When should I use getStaticPaths?
|
||||
|
||||
You should use `getStaticPaths` if you’re statically prerendering pages that use dynamic routes and:
|
||||
|
||||
- The data comes from a headless CMS
|
||||
- The data comes from a database
|
||||
- The data comes from the filesystem
|
||||
- The data can be publicly cached (not user-specific)
|
||||
- The page must be prerendered (for SEO) and be very fast — `getStaticProps` generates `HTML` and `JSON` files, both of which can be cached by a CDN for performance
|
||||
|
||||
## When does getStaticPaths run
|
||||
|
||||
`getStaticPaths` will only run during build in production, it will not be called during runtime. You can validate code written inside `getStaticPaths` is removed from the client-side bundle [with this tool](https://next-code-elimination.vercel.app/).
|
||||
|
||||
### How does getStaticProps run with regards to getStaticPaths
|
||||
|
||||
- `getStaticProps` runs during `next build` for any `paths` returned during build
|
||||
- `getStaticProps` runs in the background when using `fallback: true`
|
||||
- `getStaticProps` is called before initial render when using `fallback: blocking`
|
||||
|
||||
## Where can I use getStaticPaths
|
||||
|
||||
- `getStaticPaths` **must** be used with `getStaticProps`
|
||||
- You **cannot** use `getStaticPaths` with [`getServerSideProps`](/docs/pages/building-your-application/data-fetching/get-server-side-props)
|
||||
- You can export `getStaticPaths` from a [Dynamic Route](/docs/pages/building-your-application/routing/dynamic-routes) that also uses `getStaticProps`
|
||||
- You **cannot** export `getStaticPaths` from non-page file (e.g. your `components` folder)
|
||||
- You must export `getStaticPaths` as a standalone function, and not a property of the page component
|
||||
|
||||
## Runs on every request in development
|
||||
|
||||
In development (`next dev`), `getStaticPaths` will be called on every request.
|
||||
|
||||
## Generating paths on-demand
|
||||
|
||||
`getStaticPaths` allows you to control which pages are generated during the build instead of on-demand with [`fallback`](/docs/pages/api-reference/functions/get-static-paths#fallback-blocking). Generating more pages during a build will cause slower builds.
|
||||
|
||||
You can defer generating all pages on-demand by returning an empty array for `paths`. This can be especially helpful when deploying your Next.js application to multiple environments. For example, you can have faster builds by generating all pages on-demand for previews (but not production builds). This is helpful for sites with hundreds/thousands of static pages.
|
||||
|
||||
```jsx filename="pages/posts/[id].js"
|
||||
export async function getStaticPaths() {
|
||||
// When this is true (in preview environments) don't
|
||||
// prerender any static pages
|
||||
// (faster builds, but slower initial page load)
|
||||
if (process.env.SKIP_BUILD_STATIC_GENERATION) {
|
||||
return {
|
||||
paths: [],
|
||||
fallback: 'blocking',
|
||||
}
|
||||
}
|
||||
|
||||
// Call an external API endpoint to get posts
|
||||
const res = await fetch('https://.../posts')
|
||||
const posts = await res.json()
|
||||
|
||||
// Get the paths we want to prerender based on posts
|
||||
// In production environments, prerender all pages
|
||||
// (slower builds, but faster initial page load)
|
||||
const paths = posts.map((post) => ({
|
||||
params: { id: post.id },
|
||||
}))
|
||||
|
||||
// { fallback: false } means other routes should 404
|
||||
return { paths, fallback: false }
|
||||
}
|
||||
```
|
||||
107
node_modules/next/dist/docs/02-pages/03-building-your-application/03-data-fetching/03-forms-and-mutations.md
generated
vendored
Normal file
107
node_modules/next/dist/docs/02-pages/03-building-your-application/03-data-fetching/03-forms-and-mutations.md
generated
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
---
|
||||
title: Forms and Mutations
|
||||
nav_title: Forms and Mutations
|
||||
description: Learn how to handle form submissions and data mutations with Next.js.
|
||||
---
|
||||
|
||||
Forms enable you to create and update data in web applications. Next.js provides a powerful way to handle form submissions and data mutations using **API Routes**.
|
||||
|
||||
> **Good to know:**
|
||||
>
|
||||
> - We will soon recommend [incrementally adopting](/docs/app/guides/migrating/app-router-migration) the App Router and using [Server Actions](/docs/app/getting-started/mutating-data) for handling form submissions and data mutations. Server Actions allow you to define asynchronous server functions that can be called directly from your components, without needing to manually create an API Route.
|
||||
> - API Routes [do not specify CORS headers](https://developer.mozilla.org/docs/Web/HTTP/CORS), meaning they are same-origin only by default.
|
||||
> - Since API Routes run on the server, we're able to use sensitive values (like API keys) through [Environment Variables](/docs/pages/guides/environment-variables) without exposing them to the client. This is critical for the security of your application.
|
||||
|
||||
## Examples
|
||||
|
||||
### Redirecting
|
||||
|
||||
If you would like to redirect the user to a different route after a mutation, you can [`redirect`](/docs/pages/building-your-application/routing/api-routes#response-helpers) to any absolute or relative URL:
|
||||
|
||||
```ts filename="pages/api/submit.ts" switcher
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
) {
|
||||
const id = await addPost()
|
||||
res.redirect(307, `/post/${id}`)
|
||||
}
|
||||
```
|
||||
|
||||
```js filename="pages/api/submit.js" switcher
|
||||
export default async function handler(req, res) {
|
||||
const id = await addPost()
|
||||
res.redirect(307, `/post/${id}`)
|
||||
}
|
||||
```
|
||||
|
||||
### Setting cookies
|
||||
|
||||
You can set cookies inside an API Route using the `setHeader` method on the response:
|
||||
|
||||
```ts filename="pages/api/cookie.ts" switcher
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
) {
|
||||
res.setHeader('Set-Cookie', 'username=lee; Path=/; HttpOnly')
|
||||
res.status(200).send('Cookie has been set.')
|
||||
}
|
||||
```
|
||||
|
||||
```js filename="pages/api/cookie.js" switcher
|
||||
export default async function handler(req, res) {
|
||||
res.setHeader('Set-Cookie', 'username=lee; Path=/; HttpOnly')
|
||||
res.status(200).send('Cookie has been set.')
|
||||
}
|
||||
```
|
||||
|
||||
### Reading cookies
|
||||
|
||||
You can read cookies inside an API Route using the [`cookies`](/docs/pages/building-your-application/routing/api-routes#request-helpers) request helper:
|
||||
|
||||
```ts filename="pages/api/cookie.ts" switcher
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
) {
|
||||
const auth = req.cookies.authorization
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
```js filename="pages/api/cookie.js" switcher
|
||||
export default async function handler(req, res) {
|
||||
const auth = req.cookies.authorization
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Deleting cookies
|
||||
|
||||
You can delete cookies inside an API Route using the `setHeader` method on the response:
|
||||
|
||||
```ts filename="pages/api/cookie.ts" switcher
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
) {
|
||||
res.setHeader('Set-Cookie', 'username=; Path=/; HttpOnly; Max-Age=0')
|
||||
res.status(200).send('Cookie has been deleted.')
|
||||
}
|
||||
```
|
||||
|
||||
```js filename="pages/api/cookie.js" switcher
|
||||
export default async function handler(req, res) {
|
||||
res.setHeader('Set-Cookie', 'username=; Path=/; HttpOnly; Max-Age=0')
|
||||
res.status(200).send('Cookie has been deleted.')
|
||||
}
|
||||
```
|
||||
108
node_modules/next/dist/docs/02-pages/03-building-your-application/03-data-fetching/03-get-server-side-props.md
generated
vendored
Normal file
108
node_modules/next/dist/docs/02-pages/03-building-your-application/03-data-fetching/03-get-server-side-props.md
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
---
|
||||
title: getServerSideProps
|
||||
description: Fetch data on each request with `getServerSideProps`.
|
||||
---
|
||||
|
||||
`getServerSideProps` is a Next.js function that can be used to fetch data and render the contents of a page at request time.
|
||||
|
||||
## Example
|
||||
|
||||
You can use `getServerSideProps` by exporting it from a Page Component. The example below shows how you can fetch data from a 3rd party API in `getServerSideProps`, and pass the data to the page as props:
|
||||
|
||||
```tsx filename="pages/index.tsx" switcher
|
||||
import type { InferGetServerSidePropsType, GetServerSideProps } from 'next'
|
||||
|
||||
type Repo = {
|
||||
name: string
|
||||
stargazers_count: number
|
||||
}
|
||||
|
||||
export const getServerSideProps = (async () => {
|
||||
// Fetch data from external API
|
||||
const res = await fetch('https://api.github.com/repos/vercel/next.js')
|
||||
const repo: Repo = await res.json()
|
||||
// Pass data to the page via props
|
||||
return { props: { repo } }
|
||||
}) satisfies GetServerSideProps<{ repo: Repo }>
|
||||
|
||||
export default function Page({
|
||||
repo,
|
||||
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
|
||||
return (
|
||||
<main>
|
||||
<p>{repo.stargazers_count}</p>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/index.js" switcher
|
||||
export async function getServerSideProps() {
|
||||
// Fetch data from external API
|
||||
const res = await fetch('https://api.github.com/repos/vercel/next.js')
|
||||
const repo = await res.json()
|
||||
// Pass data to the page via props
|
||||
return { props: { repo } }
|
||||
}
|
||||
|
||||
export default function Page({ repo }) {
|
||||
return (
|
||||
<main>
|
||||
<p>{repo.stargazers_count}</p>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## When should I use `getServerSideProps`?
|
||||
|
||||
You should use `getServerSideProps` if you need to render a page that relies on personalized user data, or information that can only be known at request time. For example, `authorization` headers or a geolocation.
|
||||
|
||||
If you do not need to fetch the data at request time, or would prefer to cache the data and prerendered HTML, we recommend using [`getStaticProps`](/docs/pages/building-your-application/data-fetching/get-static-props).
|
||||
|
||||
## Behavior
|
||||
|
||||
- `getServerSideProps` runs on the server.
|
||||
- `getServerSideProps` can only be exported from a **page**.
|
||||
- `getServerSideProps` returns JSON.
|
||||
- When a user visits a page, `getServerSideProps` will be used to fetch data at request time, and the data is used to render the initial HTML of the page.
|
||||
- `props` passed to the page component can be viewed on the client as part of the initial HTML. This is to allow the page to be [hydrated](https://react.dev/reference/react-dom/hydrate) correctly. Make sure that you don't pass any sensitive information that shouldn't be available on the client in `props`.
|
||||
- When a user visits the page through [`next/link`](/docs/pages/api-reference/components/link) or [`next/router`](/docs/pages/api-reference/functions/use-router), Next.js sends an API request to the server, which runs `getServerSideProps`.
|
||||
- You do not have to call a Next.js [API Route](/docs/pages/building-your-application/routing/api-routes) to fetch data when using `getServerSideProps` since the function runs on the server. Instead, you can call a CMS, database, or other third-party APIs directly from inside `getServerSideProps`.
|
||||
|
||||
> **Good to know:**
|
||||
>
|
||||
> - See [`getServerSideProps` API reference](/docs/pages/api-reference/functions/get-server-side-props) for parameters and props that can be used with `getServerSideProps`.
|
||||
> - You can use the [next-code-elimination tool](https://next-code-elimination.vercel.app/) to verify what Next.js eliminates from the client-side bundle.
|
||||
|
||||
## Error Handling
|
||||
|
||||
If an error is thrown inside `getServerSideProps`, it will show the `pages/500.js` file. Check out the documentation for [500 page](/docs/pages/building-your-application/routing/custom-error#500-page) to learn more on how to create it. During development, this file will not be used and the development error overlay will be shown instead.
|
||||
|
||||
## Edge Cases
|
||||
|
||||
### Caching with Server-Side Rendering (SSR)
|
||||
|
||||
You can use caching headers (`Cache-Control`) inside `getServerSideProps` to cache dynamic responses. For example, using [`stale-while-revalidate`](https://web.dev/stale-while-revalidate/).
|
||||
|
||||
```jsx
|
||||
// This value is considered fresh for ten seconds (s-maxage=10).
|
||||
// If a request is repeated within the next 10 seconds, the previously
|
||||
// cached value will still be fresh. If the request is repeated before 59 seconds,
|
||||
// the cached value will be stale but still render (stale-while-revalidate=59).
|
||||
//
|
||||
// In the background, a revalidation request will be made to populate the cache
|
||||
// with a fresh value. If you refresh the page, you will see the new value.
|
||||
export async function getServerSideProps({ req, res }) {
|
||||
res.setHeader(
|
||||
'Cache-Control',
|
||||
'public, s-maxage=10, stale-while-revalidate=59'
|
||||
)
|
||||
|
||||
return {
|
||||
props: {},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
However, before reaching for `cache-control`, we recommend seeing if [`getStaticProps`](/docs/pages/building-your-application/data-fetching/get-static-props) with [ISR](/docs/pages/guides/incremental-static-regeneration) is a better fit for your use case.
|
||||
70
node_modules/next/dist/docs/02-pages/03-building-your-application/03-data-fetching/05-client-side.md
generated
vendored
Normal file
70
node_modules/next/dist/docs/02-pages/03-building-your-application/03-data-fetching/05-client-side.md
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
---
|
||||
title: Client-side Fetching
|
||||
description: Learn about client-side data fetching, and how to use SWR, a data fetching React Hook library that handles caching, revalidation, focus tracking, refetching on interval and more.
|
||||
---
|
||||
|
||||
Client-side data fetching is useful when your page doesn't require SEO indexing, when you don't need to prerender your data, or when the content of your pages needs to update frequently. Unlike the server-side rendering APIs, you can use client-side data fetching at the component level.
|
||||
|
||||
If done at the page level, the data is fetched at runtime, and the content of the page is updated as the data changes. When used at the component level, the data is fetched at the time of the component mount, and the content of the component is updated as the data changes.
|
||||
|
||||
It's important to note that using client-side data fetching can affect the performance of your application and the load speed of your pages. This is because the data fetching is done at the time of the component or pages mount, and the data is not cached.
|
||||
|
||||
## Client-side data fetching with useEffect
|
||||
|
||||
The following example shows how you can fetch data on the client side using the useEffect hook.
|
||||
|
||||
```jsx
|
||||
import { useState, useEffect } from 'react'
|
||||
|
||||
function Profile() {
|
||||
const [data, setData] = useState(null)
|
||||
const [isLoading, setLoading] = useState(true)
|
||||
|
||||
useEffect(() => {
|
||||
fetch('/api/profile-data')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
setData(data)
|
||||
setLoading(false)
|
||||
})
|
||||
}, [])
|
||||
|
||||
if (isLoading) return <p>Loading...</p>
|
||||
if (!data) return <p>No profile data</p>
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>{data.name}</h1>
|
||||
<p>{data.bio}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Client-side data fetching with SWR
|
||||
|
||||
The team behind Next.js has created a React Hook library for data fetching called [**SWR**](https://swr.vercel.app/). It is **highly recommended** if you are fetching data on the client-side. It handles caching, revalidation, focus tracking, refetching on intervals, and more.
|
||||
|
||||
Using the same example as above, we can now use SWR to fetch the profile data. SWR will automatically cache the data for us and will revalidate the data if it becomes stale.
|
||||
|
||||
For more information on using SWR, check out the [SWR docs](https://swr.vercel.app/docs/getting-started).
|
||||
|
||||
```jsx
|
||||
import useSWR from 'swr'
|
||||
|
||||
const fetcher = (...args) => fetch(...args).then((res) => res.json())
|
||||
|
||||
function Profile() {
|
||||
const { data, error } = useSWR('/api/profile-data', fetcher)
|
||||
|
||||
if (error) return <div>Failed to load</div>
|
||||
if (!data) return <div>Loading...</div>
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>{data.name}</h1>
|
||||
<p>{data.bio}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
37
node_modules/next/dist/docs/02-pages/03-building-your-application/03-data-fetching/index.md
generated
vendored
Normal file
37
node_modules/next/dist/docs/02-pages/03-building-your-application/03-data-fetching/index.md
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
---
|
||||
title: Data Fetching
|
||||
description: Next.js allows you to fetch data in multiple ways, with prerendering, server-side rendering or static-site generation, and incremental static regeneration. Learn how to manage your application data in Next.js.
|
||||
---
|
||||
|
||||
Data fetching in Next.js allows you to render your content in different ways, depending on your application's use case. These include prerendering with **Server-side Rendering** or **Static Generation**, and updating or creating content at runtime with **Incremental Static Regeneration**.
|
||||
|
||||
## Examples
|
||||
|
||||
- [Agility CMS Example](https://github.com/vercel/next.js/tree/canary/examples/cms-agilitycms) ([Demo](https://next-blog-agilitycms.vercel.app/))
|
||||
- [Builder.io Example](https://github.com/vercel/next.js/tree/canary/examples/cms-builder-io) ([Demo](https://cms-builder-io.vercel.app/))
|
||||
- [ButterCMS Example](https://github.com/vercel/next.js/tree/canary/examples/cms-buttercms) ([Demo](https://next-blog-buttercms.vercel.app/))
|
||||
- [Contentful Example](https://github.com/vercel/next.js/tree/canary/examples/cms-contentful) ([Demo](https://app-router-contentful.vercel.app/))
|
||||
- [Cosmic Example](https://github.com/vercel/next.js/tree/canary/examples/cms-cosmic) ([Demo](https://next-blog-cosmic.vercel.app/))
|
||||
- [DatoCMS Example](https://github.com/vercel/next.js/tree/canary/examples/cms-datocms) ([Demo](https://next-blog-datocms.vercel.app/))
|
||||
- [DotCMS Example](https://github.com/vercel/next.js/tree/canary/examples/cms-dotcms) ([Demo](https://nextjs-dotcms-blog.vercel.app/))
|
||||
- [Drupal Example](https://github.com/vercel/next.js/tree/canary/examples/cms-drupal) ([Demo](https://cms-drupal.vercel.app/))
|
||||
- [Enterspeed Example](https://github.com/vercel/next.js/tree/canary/examples/cms-enterspeed) ([Demo](https://next-blog-demo.enterspeed.com/))
|
||||
- [GraphCMS Example](https://github.com/vercel/next.js/tree/canary/examples/cms-graphcms) ([Demo](https://next-blog-graphcms.vercel.app/))
|
||||
- [Keystone Example](https://github.com/vercel/next.js/tree/canary/examples/cms-keystonejs-embedded) ([Demo](https://nextjs-keystone-demo.vercel.app/))
|
||||
- [Kontent.ai Example](https://github.com/vercel/next.js/tree/canary/examples/cms-kontent-ai) ([Demo](https://next-blog-kontent-ai.vercel.app/))
|
||||
- [Makeswift Example](https://github.com/vercel/next.js/tree/canary/examples/cms-makeswift) ([Demo](https://nextjs-makeswift-example.vercel.app/))
|
||||
- [Plasmic Example](https://github.com/vercel/next.js/tree/canary/examples/cms-plasmic) ([Demo](https://nextjs-plasmic-example.vercel.app/))
|
||||
- [Prepr Example](https://github.com/vercel/next.js/tree/canary/examples/cms-prepr) ([Demo](https://next-blog-prepr.vercel.app/))
|
||||
- [Prismic Example](https://github.com/vercel/next.js/tree/canary/examples/cms-prismic) ([Demo](https://next-blog-prismic.vercel.app/))
|
||||
- [Sanity Example](https://github.com/vercel/next.js/tree/canary/examples/cms-sanity) ([Demo](https://next-blog.sanity.build/))
|
||||
- [Sitecore XM Cloud Example](https://github.com/vercel/next.js/tree/canary/examples/cms-sitecore-xmcloud) ([Demo](https://vercel-sitecore-xmcloud-demo.vercel.app/))
|
||||
- [Storyblok Example](https://github.com/vercel/next.js/tree/canary/examples/cms-storyblok) ([Demo](https://next-blog-storyblok.vercel.app/))
|
||||
- [Strapi Example](https://github.com/vercel/next.js/tree/canary/examples/cms-strapi) ([Demo](https://next-blog-strapi.vercel.app/))
|
||||
- [TakeShape Example](https://github.com/vercel/next.js/tree/canary/examples/cms-takeshape) ([Demo](https://next-blog-takeshape.vercel.app/))
|
||||
- [Tina Example](https://github.com/vercel/next.js/tree/canary/examples/cms-tina) ([Demo](https://cms-tina-example.vercel.app/))
|
||||
- [Umbraco Example](https://github.com/vercel/next.js/tree/canary/examples/cms-umbraco) ([Demo](https://nextjs-umbraco-sample-blog.vercel.app/))
|
||||
- [Umbraco Heartcore Example](https://github.com/vercel/next.js/tree/canary/examples/cms-umbraco-heartcore) ([Demo](https://next-blog-umbraco-heartcore.vercel.app/))
|
||||
- [Webiny Example](https://github.com/vercel/next.js/tree/canary/examples/cms-webiny) ([Demo](https://webiny-headlesscms-nextjs-example.vercel.app/))
|
||||
- [WordPress Example](https://github.com/vercel/next.js/tree/canary/examples/cms-wordpress) ([Demo](https://next-blog-wordpress.vercel.app/))
|
||||
- [Blog Starter Example](https://github.com/vercel/next.js/tree/canary/examples/blog-starter) ([Demo](https://next-blog-starter.vercel.app/))
|
||||
- [Static Tweet (Demo)](https://react-tweet.vercel.app/)
|
||||
104
node_modules/next/dist/docs/02-pages/03-building-your-application/06-configuring/12-error-handling.md
generated
vendored
Normal file
104
node_modules/next/dist/docs/02-pages/03-building-your-application/06-configuring/12-error-handling.md
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
---
|
||||
title: Error Handling
|
||||
description: Handle errors in your Next.js app.
|
||||
---
|
||||
|
||||
This documentation explains how you can handle development, server-side, and client-side errors.
|
||||
|
||||
## Handling Errors in Development
|
||||
|
||||
When there is a runtime error during the development phase of your Next.js application, you will encounter an **overlay**. It is a modal that covers the webpage. It is **only** visible when the development server runs using `next dev` via `pnpm dev`, `npm run dev`, `yarn dev`, or `bun dev` and will not be shown in production. Fixing the error will automatically dismiss the overlay.
|
||||
|
||||
Here is an example of an overlay:
|
||||
|
||||
{/* TODO UPDATE SCREENSHOT */}
|
||||

|
||||
|
||||
## Handling Server Errors
|
||||
|
||||
Next.js provides a static 500 page by default to handle server-side errors that occur in your application. You can also [customize this page](/docs/pages/building-your-application/routing/custom-error#customizing-the-500-page) by creating a `pages/500.js` file.
|
||||
|
||||
Having a 500 page in your application does not show specific errors to the app user.
|
||||
|
||||
You can also use [404 page](/docs/pages/building-your-application/routing/custom-error#404-page) to handle specific runtime error like `file not found`.
|
||||
|
||||
## Handling Client Errors
|
||||
|
||||
React [Error Boundaries](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary) is a graceful way to handle a JavaScript error on the client so that the other parts of the application continue working. In addition to preventing the page from crashing, it allows you to provide a custom fallback component and even log error information.
|
||||
|
||||
To use Error Boundaries for your Next.js application, you must create a class component `ErrorBoundary` and wrap the `Component` prop in the `pages/_app.js` file. This component will be responsible to:
|
||||
|
||||
- Render a fallback UI after an error is thrown
|
||||
- Provide a way to reset the Application's state
|
||||
- Log error information
|
||||
|
||||
You can create an `ErrorBoundary` class component by extending `React.Component`. For example:
|
||||
|
||||
```jsx
|
||||
class ErrorBoundary extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
// Define a state variable to track whether is an error or not
|
||||
this.state = { hasError: false }
|
||||
}
|
||||
static getDerivedStateFromError(error) {
|
||||
// Update state so the next render will show the fallback UI
|
||||
|
||||
return { hasError: true }
|
||||
}
|
||||
componentDidCatch(error, errorInfo) {
|
||||
// You can use your own error logging service here
|
||||
console.log({ error, errorInfo })
|
||||
}
|
||||
render() {
|
||||
// Check if the error is thrown
|
||||
if (this.state.hasError) {
|
||||
// You can render any custom fallback UI
|
||||
return (
|
||||
<div>
|
||||
<h2>Oops, there is an error!</h2>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => this.setState({ hasError: false })}
|
||||
>
|
||||
Try again?
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Return children components in case of no error
|
||||
|
||||
return this.props.children
|
||||
}
|
||||
}
|
||||
|
||||
export default ErrorBoundary
|
||||
```
|
||||
|
||||
The `ErrorBoundary` component keeps track of an `hasError` state. The value of this state variable is a boolean. When the value of `hasError` is `true`, then the `ErrorBoundary` component will render a fallback UI. Otherwise, it will render the children components.
|
||||
|
||||
After creating an `ErrorBoundary` component, import it in the `pages/_app.js` file to wrap the `Component` prop in your Next.js application.
|
||||
|
||||
```jsx
|
||||
// Import the ErrorBoundary component
|
||||
import ErrorBoundary from '../components/ErrorBoundary'
|
||||
|
||||
function MyApp({ Component, pageProps }) {
|
||||
return (
|
||||
// Wrap the Component prop with ErrorBoundary component
|
||||
<ErrorBoundary>
|
||||
<Component {...pageProps} />
|
||||
</ErrorBoundary>
|
||||
)
|
||||
}
|
||||
|
||||
export default MyApp
|
||||
```
|
||||
|
||||
You can learn more about [Error Boundaries](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary) in React's documentation.
|
||||
|
||||
### Reporting Errors
|
||||
|
||||
To monitor client errors, use a service like [Sentry](https://github.com/vercel/next.js/tree/canary/examples/with-sentry), Bugsnag or Datadog.
|
||||
6
node_modules/next/dist/docs/02-pages/03-building-your-application/06-configuring/index.md
generated
vendored
Normal file
6
node_modules/next/dist/docs/02-pages/03-building-your-application/06-configuring/index.md
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
title: Configuring
|
||||
description: Learn how to configure your Next.js application.
|
||||
---
|
||||
|
||||
Next.js allows you to customize your project to meet specific requirements. This includes integrations with TypeScript, ESlint, and more, as well as internal configuration options such as Absolute Imports and Environment Variables.
|
||||
4
node_modules/next/dist/docs/02-pages/03-building-your-application/index.md
generated
vendored
Normal file
4
node_modules/next/dist/docs/02-pages/03-building-your-application/index.md
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: Building Your Application
|
||||
description: Learn how to use Next.js features to build your application.
|
||||
---
|
||||
8
node_modules/next/dist/docs/02-pages/04-api-reference/01-components/font.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/04-api-reference/01-components/font.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: Font Module
|
||||
nav_title: Font
|
||||
description: API Reference for the Font Module
|
||||
source: app/api-reference/components/font
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
7
node_modules/next/dist/docs/02-pages/04-api-reference/01-components/form.md
generated
vendored
Normal file
7
node_modules/next/dist/docs/02-pages/04-api-reference/01-components/form.md
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Form
|
||||
description: Learn how to use the `<Form>` component to handle form submissions and search params updates with client-side navigation.
|
||||
source: app/api-reference/components/form
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
67
node_modules/next/dist/docs/02-pages/04-api-reference/01-components/head.md
generated
vendored
Normal file
67
node_modules/next/dist/docs/02-pages/04-api-reference/01-components/head.md
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
---
|
||||
title: Head
|
||||
description: Add custom elements to the `head` of your page with the built-in Head component.
|
||||
---
|
||||
|
||||
We expose a built-in component for appending elements to the `head` of the page:
|
||||
|
||||
```jsx
|
||||
import Head from 'next/head'
|
||||
|
||||
function IndexPage() {
|
||||
return (
|
||||
<div>
|
||||
<Head>
|
||||
<title>My page title</title>
|
||||
</Head>
|
||||
<p>Hello world!</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default IndexPage
|
||||
```
|
||||
|
||||
## Avoid duplicated tags
|
||||
|
||||
To avoid duplicate tags in your `head` you can use the `key` property, which will make sure the tag is only rendered once, as in the following example:
|
||||
|
||||
```jsx
|
||||
import Head from 'next/head'
|
||||
|
||||
function IndexPage() {
|
||||
return (
|
||||
<div>
|
||||
<Head>
|
||||
<title>My page title</title>
|
||||
<meta property="og:title" content="My page title" key="title" />
|
||||
</Head>
|
||||
<Head>
|
||||
<meta property="og:title" content="My new title" key="title" />
|
||||
</Head>
|
||||
<p>Hello world!</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default IndexPage
|
||||
```
|
||||
|
||||
In this case only the second `<meta property="og:title" />` is rendered. `meta` tags with duplicate `key` attributes are automatically handled.
|
||||
|
||||
> **Good to know**: `<title>` and `<base>` tags are automatically checked for duplicates by Next.js, so using key is not necessary for these tags.
|
||||
|
||||
> The contents of `head` get cleared upon unmounting the component, so make sure each page completely defines what it needs in `head`, without making assumptions about what other pages added.
|
||||
|
||||
## Use minimal nesting
|
||||
|
||||
`title`, `meta` or any other elements (e.g. `script`) need to be contained as **direct** children of the `Head` element,
|
||||
or wrapped into maximum one level of `<React.Fragment>` or arrays—otherwise the tags won't be correctly picked up on client-side navigations.
|
||||
|
||||
## Use `next/script` for scripts
|
||||
|
||||
We recommend using [`next/script`](/docs/pages/guides/scripts) in your component instead of manually creating a `<script>` in `next/head`.
|
||||
|
||||
## No `html` or `body` tags
|
||||
|
||||
You **cannot** use `<Head>` to set attributes on `<html>` or `<body>` tags. This will result in an `next-head-count is missing` error. `next/head` can only handle tags inside the HTML `<head>` tag.
|
||||
659
node_modules/next/dist/docs/02-pages/04-api-reference/01-components/image-legacy.md
generated
vendored
Normal file
659
node_modules/next/dist/docs/02-pages/04-api-reference/01-components/image-legacy.md
generated
vendored
Normal file
@@ -0,0 +1,659 @@
|
||||
---
|
||||
title: Image (Legacy)
|
||||
description: Backwards compatible Image Optimization with the Legacy Image component.
|
||||
version: legacy
|
||||
---
|
||||
|
||||
Starting with Next.js 13, the `next/image` component was rewritten to improve both the performance and developer experience. In order to provide a backwards compatible upgrade solution, the old `next/image` was renamed to `next/legacy/image`.
|
||||
|
||||
> **Warning**: `next/legacy/image` is deprecated and will be removed in a future version of Next.js. Please use [`next/image`](/docs/app/api-reference/components/image) instead.
|
||||
|
||||
## Comparison
|
||||
|
||||
Compared to `next/legacy/image`, the new `next/image` component has the following changes:
|
||||
|
||||
- Removes `<span>` wrapper around `<img>` in favor of [native computed aspect ratio](https://caniuse.com/mdn-html_elements_img_aspect_ratio_computed_from_attributes)
|
||||
- Adds support for canonical `style` prop
|
||||
- Removes `layout` prop in favor of `style` or `className`
|
||||
- Removes `objectFit` prop in favor of `style` or `className`
|
||||
- Removes `objectPosition` prop in favor of `style` or `className`
|
||||
- Removes `IntersectionObserver` implementation in favor of [native lazy loading](https://caniuse.com/loading-lazy-attr)
|
||||
- Removes `lazyBoundary` prop since there is no native equivalent
|
||||
- Removes `lazyRoot` prop since there is no native equivalent
|
||||
- Removes `loader` config in favor of [`loader`](#loader) prop
|
||||
- Changed `alt` prop from optional to required
|
||||
- Changed `onLoadingComplete` callback to receive reference to `<img>` element
|
||||
|
||||
## Required Props
|
||||
|
||||
The `<Image />` component requires the following properties.
|
||||
|
||||
### src
|
||||
|
||||
Must be one of the following:
|
||||
|
||||
- A [statically imported](/docs/pages/api-reference/components/image#src) image file
|
||||
- A path string. This can be either an absolute external URL, or an internal path depending on the [loader](#loader) prop or [loader configuration](#loader-configuration).
|
||||
|
||||
When using the default [loader](#loader), also consider the following for source images:
|
||||
|
||||
- When src is an external URL, you must also configure [remotePatterns](#remote-patterns)
|
||||
- When src is [animated](#animated-images) or not a known format (JPEG, PNG, WebP, AVIF, GIF, TIFF) the image will be served as-is
|
||||
- When src is SVG format, it will be blocked unless `unoptimized` or `dangerouslyAllowSVG` is enabled
|
||||
|
||||
### width
|
||||
|
||||
The `width` property can represent either the _rendered_ width or _original_ width in pixels, depending on the [`layout`](#layout) and [`sizes`](#sizes) properties.
|
||||
|
||||
When using `layout="intrinsic"` or `layout="fixed"` the `width` property represents the _rendered_ width in pixels, so it will affect how large the image appears.
|
||||
|
||||
When using `layout="responsive"`, `layout="fill"`, the `width` property represents the _original_ width in pixels, so it will only affect the aspect ratio.
|
||||
|
||||
The `width` property is required, except for [statically imported images](/docs/pages/api-reference/components/image#src), or those with `layout="fill"`.
|
||||
|
||||
### height
|
||||
|
||||
The `height` property can represent either the _rendered_ height or _original_ height in pixels, depending on the [`layout`](#layout) and [`sizes`](#sizes) properties.
|
||||
|
||||
When using `layout="intrinsic"` or `layout="fixed"` the `height` property represents the _rendered_ height in pixels, so it will affect how large the image appears.
|
||||
|
||||
When using `layout="responsive"`, `layout="fill"`, the `height` property represents the _original_ height in pixels, so it will only affect the aspect ratio.
|
||||
|
||||
The `height` property is required, except for [statically imported images](/docs/pages/api-reference/components/image#src), or those with `layout="fill"`.
|
||||
|
||||
## Optional Props
|
||||
|
||||
The `<Image />` component accepts a number of additional properties beyond those which are required. This section describes the most commonly-used properties of the Image component. Find details about more rarely-used properties in the [Advanced Props](#advanced-props) section.
|
||||
|
||||
### layout
|
||||
|
||||
The layout behavior of the image as the viewport changes size.
|
||||
|
||||
| `layout` | Behavior | `srcSet` | `sizes` | Has wrapper and sizer |
|
||||
| --------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ------- | --------------------- |
|
||||
| `intrinsic` (default) | Scale _down_ to fit width of container, up to image size | `1x`, `2x` (based on [imageSizes](#image-sizes)) | N/A | yes |
|
||||
| `fixed` | Sized to `width` and `height` exactly | `1x`, `2x` (based on [imageSizes](#image-sizes)) | N/A | yes |
|
||||
| `responsive` | Scale to fit width of container | `640w`, `750w`, ... `2048w`, `3840w` (based on [imageSizes](#image-sizes) and [deviceSizes](#device-sizes)) | `100vw` | yes |
|
||||
| `fill` | Grow in both X and Y axes to fill container | `640w`, `750w`, ... `2048w`, `3840w` (based on [imageSizes](#image-sizes) and [deviceSizes](#device-sizes)) | `100vw` | yes |
|
||||
|
||||
- [Demo the `intrinsic` layout (default)](https://image-legacy-component.nextjs.gallery/layout-intrinsic)
|
||||
- When `intrinsic`, the image will scale the dimensions down for smaller viewports, but maintain the original dimensions for larger viewports.
|
||||
- [Demo the `fixed` layout](https://image-legacy-component.nextjs.gallery/layout-fixed)
|
||||
- When `fixed`, the image dimensions will not change as the viewport changes (no responsiveness) similar to the native `img` element.
|
||||
- [Demo the `responsive` layout](https://image-legacy-component.nextjs.gallery/layout-responsive)
|
||||
- When `responsive`, the image will scale the dimensions down for smaller viewports and scale up for larger viewports.
|
||||
- Ensure the parent element uses `display: block` in their stylesheet.
|
||||
- [Demo the `fill` layout](https://image-legacy-component.nextjs.gallery/layout-fill)
|
||||
- When `fill`, the image will stretch both width and height to the dimensions of the parent element, provided the parent element is relative.
|
||||
- This is usually paired with the [`objectFit`](#objectfit) property.
|
||||
- Ensure the parent element has `position: relative` in their stylesheet.
|
||||
- [Demo background image](https://image-legacy-component.nextjs.gallery/background)
|
||||
|
||||
### loader
|
||||
|
||||
A custom function used to resolve URLs. Setting the loader as a prop on the Image component overrides the default loader defined in the [`images` section of `next.config.js`](#loader-configuration).
|
||||
|
||||
A `loader` is a function returning a URL string for the image, given the following parameters:
|
||||
|
||||
- [`src`](#src)
|
||||
- [`width`](#width)
|
||||
- [`quality`](#quality)
|
||||
|
||||
Here is an example of using a custom loader:
|
||||
|
||||
```js
|
||||
import Image from 'next/legacy/image'
|
||||
|
||||
const myLoader = ({ src, width, quality }) => {
|
||||
return `https://example.com/${src}?w=${width}&q=${quality || 75}`
|
||||
}
|
||||
|
||||
const MyImage = (props) => {
|
||||
return (
|
||||
<Image
|
||||
loader={myLoader}
|
||||
src="me.png"
|
||||
alt="Picture of the author"
|
||||
width={500}
|
||||
height={500}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### sizes
|
||||
|
||||
A string that provides information about how wide the image will be at different breakpoints. The value of `sizes` will greatly affect performance for images using `layout="responsive"` or `layout="fill"`. It will be ignored for images using `layout="intrinsic"` or `layout="fixed"`.
|
||||
|
||||
The `sizes` property serves two important purposes related to image performance:
|
||||
|
||||
First, the value of `sizes` is used by the browser to determine which size of the image to download, from `next/legacy/image`'s automatically-generated source set. When the browser chooses, it does not yet know the size of the image on the page, so it selects an image that is the same size or larger than the viewport. The `sizes` property allows you to tell the browser that the image will actually be smaller than full screen. If you don't specify a `sizes` value, a default value of `100vw` (full screen width) is used.
|
||||
|
||||
Second, the `sizes` value is parsed and used to trim the values in the automatically-created source set. If the `sizes` property includes sizes such as `50vw`, which represent a percentage of the viewport width, then the source set is trimmed to not include any values which are too small to ever be necessary.
|
||||
|
||||
For example, if you know your styling will cause an image to be full-width on mobile devices, in a 2-column layout on tablets, and a 3-column layout on desktop displays, you should include a sizes property such as the following:
|
||||
|
||||
```js
|
||||
import Image from 'next/legacy/image'
|
||||
const Example = () => (
|
||||
<div className="grid-element">
|
||||
<Image
|
||||
src="/example.png"
|
||||
layout="fill"
|
||||
sizes="(max-width: 768px) 100vw,
|
||||
(max-width: 1200px) 50vw,
|
||||
33vw"
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
```
|
||||
|
||||
This example `sizes` could have a dramatic effect on performance metrics. Without the `33vw` sizes, the image selected from the server would be 3 times as wide as it needs to be. Because file size is proportional to the square of the width, without `sizes` the user would download an image that's 9 times larger than necessary.
|
||||
|
||||
Learn more about `srcset` and `sizes`:
|
||||
|
||||
- [web.dev](https://web.dev/learn/design/responsive-images/#sizes)
|
||||
- [mdn](https://developer.mozilla.org/docs/Web/HTML/Element/img#attr-sizes)
|
||||
|
||||
### quality
|
||||
|
||||
The quality of the optimized image, an integer between `1` and `100` where `100` is the best quality. Defaults to `75`.
|
||||
|
||||
### priority
|
||||
|
||||
When true, the image will be considered high priority and
|
||||
[preload](https://web.dev/preload-responsive-images/). Lazy loading is automatically disabled for images using `priority`.
|
||||
|
||||
You should use the `priority` property on any image detected as the [Largest Contentful Paint (LCP)](https://nextjs.org/learn/seo/web-performance/lcp) element. It may be appropriate to have multiple priority images, as different images may be the LCP element for different viewport sizes.
|
||||
|
||||
Should only be used when the image is visible above the fold. Defaults to `false`.
|
||||
|
||||
### placeholder
|
||||
|
||||
A placeholder to use while the image is loading. Possible values are `blur` or `empty`. Defaults to `empty`.
|
||||
|
||||
When `blur`, the [`blurDataURL`](#blurdataurl) property will be used as the placeholder. If `src` is an object from a [static import](/docs/pages/api-reference/components/image#src) and the imported image is `.jpg`, `.png`, `.webp`, or `.avif`, then `blurDataURL` will be automatically populated.
|
||||
|
||||
For dynamic images, you must provide the [`blurDataURL`](#blurdataurl) property. Solutions such as [Plaiceholder](https://github.com/joe-bell/plaiceholder) can help with `base64` generation.
|
||||
|
||||
When `empty`, there will be no placeholder while the image is loading, only empty space.
|
||||
|
||||
Try it out:
|
||||
|
||||
- [Demo the `blur` placeholder](https://image-legacy-component.nextjs.gallery/placeholder)
|
||||
- [Demo the shimmer effect with `blurDataURL` prop](https://image-legacy-component.nextjs.gallery/shimmer)
|
||||
- [Demo the color effect with `blurDataURL` prop](https://image-legacy-component.nextjs.gallery/color)
|
||||
|
||||
## Advanced Props
|
||||
|
||||
In some cases, you may need more advanced usage. The `<Image />` component optionally accepts the following advanced properties.
|
||||
|
||||
### style
|
||||
|
||||
Allows [passing CSS styles](https://developer.mozilla.org/docs/Web/HTML/Element/style) to the underlying image element.
|
||||
|
||||
Note that all `layout` modes apply their own styles to the image element, and these automatic styles take precedence over the `style` prop.
|
||||
|
||||
Also keep in mind that the required `width` and `height` props can interact with your styling. If you use styling to modify an image's `width`, you must set the `height="auto"` style as well, or your image will be distorted.
|
||||
|
||||
### objectFit
|
||||
|
||||
Defines how the image will fit into its parent container when using `layout="fill"`.
|
||||
|
||||
This value is passed to the [object-fit CSS property](https://developer.mozilla.org/docs/Web/CSS/object-fit) for the `src` image.
|
||||
|
||||
### objectPosition
|
||||
|
||||
Defines how the image is positioned within its parent element when using `layout="fill"`.
|
||||
|
||||
This value is passed to the [object-position CSS property](https://developer.mozilla.org/docs/Web/CSS/object-position) applied to the image.
|
||||
|
||||
### onLoadingComplete
|
||||
|
||||
A callback function that is invoked once the image is completely loaded and the [placeholder](#placeholder) has been removed.
|
||||
|
||||
The `onLoadingComplete` function accepts one parameter, an object with the following properties:
|
||||
|
||||
- [`naturalWidth`](https://developer.mozilla.org/docs/Web/API/HTMLImageElement/naturalWidth)
|
||||
- [`naturalHeight`](https://developer.mozilla.org/docs/Web/API/HTMLImageElement/naturalHeight)
|
||||
|
||||
### loading
|
||||
|
||||
The loading behavior of the image. Defaults to `lazy`.
|
||||
|
||||
When `lazy`, defer loading the image until it reaches a calculated distance from
|
||||
the viewport.
|
||||
|
||||
When `eager`, load the image immediately.
|
||||
|
||||
[Learn more](https://developer.mozilla.org/docs/Web/HTML/Element/img#attr-loading)
|
||||
|
||||
### blurDataURL
|
||||
|
||||
A [Data URL](https://developer.mozilla.org/docs/Web/HTTP/Basics_of_HTTP/Data_URIs) to
|
||||
be used as a placeholder image before the `src` image successfully loads. Only takes effect when combined
|
||||
with [`placeholder="blur"`](#placeholder).
|
||||
|
||||
Must be a base64-encoded image. It will be enlarged and blurred, so a very small image (10px or
|
||||
less) is recommended. Including larger images as placeholders may harm your application performance.
|
||||
|
||||
Try it out:
|
||||
|
||||
- [Demo the default `blurDataURL` prop](https://image-legacy-component.nextjs.gallery/placeholder)
|
||||
- [Demo the shimmer effect with `blurDataURL` prop](https://image-legacy-component.nextjs.gallery/shimmer)
|
||||
- [Demo the color effect with `blurDataURL` prop](https://image-legacy-component.nextjs.gallery/color)
|
||||
|
||||
You can also [generate a solid color Data URL](https://png-pixel.com) to match the image.
|
||||
|
||||
### lazyBoundary
|
||||
|
||||
A string (with similar syntax to the margin property) that acts as the bounding box used to detect the intersection of the viewport with the image and trigger lazy [loading](#loading). Defaults to `"200px"`.
|
||||
|
||||
If the image is nested in a scrollable parent element other than the root document, you will also need to assign the [lazyRoot](#lazyroot) prop.
|
||||
|
||||
[Learn more](https://developer.mozilla.org/docs/Web/API/IntersectionObserver/rootMargin)
|
||||
|
||||
### lazyRoot
|
||||
|
||||
A React [Ref](https://react.dev/learn/referencing-values-with-refs) pointing to the scrollable parent element. Defaults to `null` (the document viewport).
|
||||
|
||||
The Ref must point to a DOM element or a React component that [forwards the Ref](https://react.dev/reference/react/forwardRef) to the underlying DOM element.
|
||||
|
||||
**Example pointing to a DOM element**
|
||||
|
||||
```jsx
|
||||
import Image from 'next/legacy/image'
|
||||
import React from 'react'
|
||||
|
||||
const Example = () => {
|
||||
const lazyRoot = React.useRef(null)
|
||||
|
||||
return (
|
||||
<div ref={lazyRoot} style={{ overflowX: 'scroll', width: '500px' }}>
|
||||
<Image lazyRoot={lazyRoot} src="/one.jpg" width="500" height="500" />
|
||||
<Image lazyRoot={lazyRoot} src="/two.jpg" width="500" height="500" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
**Example pointing to a React component**
|
||||
|
||||
```jsx
|
||||
import Image from 'next/legacy/image'
|
||||
import React from 'react'
|
||||
|
||||
const Container = React.forwardRef((props, ref) => {
|
||||
return (
|
||||
<div ref={ref} style={{ overflowX: 'scroll', width: '500px' }}>
|
||||
{props.children}
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
const Example = () => {
|
||||
const lazyRoot = React.useRef(null)
|
||||
|
||||
return (
|
||||
<Container ref={lazyRoot}>
|
||||
<Image lazyRoot={lazyRoot} src="/one.jpg" width="500" height="500" />
|
||||
<Image lazyRoot={lazyRoot} src="/two.jpg" width="500" height="500" />
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
[Learn more](https://developer.mozilla.org/docs/Web/API/IntersectionObserver/root)
|
||||
|
||||
### unoptimized
|
||||
|
||||
When true, the source image will be served as-is from the `src` instead of changing quality, size, or format. Defaults to `false`.
|
||||
|
||||
This is useful for images that do not benefit from optimization such as small images (less than 1KB), vector images (SVG), or animated images (GIF).
|
||||
|
||||
```js
|
||||
import Image from 'next/image'
|
||||
|
||||
const UnoptimizedImage = (props) => {
|
||||
return <Image {...props} unoptimized />
|
||||
}
|
||||
```
|
||||
|
||||
Since Next.js 12.3.0, this prop can be assigned to all images by updating `next.config.js` with the following configuration:
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
images: {
|
||||
unoptimized: true,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Other Props
|
||||
|
||||
Other properties on the `<Image />` component will be passed to the underlying
|
||||
`img` element with the exception of the following:
|
||||
|
||||
- `srcSet`. Use
|
||||
[Device Sizes](#device-sizes)
|
||||
instead.
|
||||
- `ref`. Use [`onLoadingComplete`](#onloadingcomplete) instead.
|
||||
- `decoding`. It is always `"async"`.
|
||||
|
||||
## Configuration Options
|
||||
|
||||
### Remote Patterns
|
||||
|
||||
To protect your application from malicious users, configuration is required in order to use external images. This ensures that only external images from your account can be served from the Next.js Image Optimization API. These external images can be configured with the `remotePatterns` property in your `next.config.js` file, as shown below:
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
images: {
|
||||
remotePatterns: [
|
||||
{
|
||||
protocol: 'https',
|
||||
hostname: 'example.com',
|
||||
port: '',
|
||||
pathname: '/account123/**',
|
||||
search: '',
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
> **Good to know**: The example above will ensure the `src` property of `next/legacy/image` must start with `https://example.com/account123/` and must not have a query string. Any other protocol, hostname, port, or unmatched path will respond with 400 Bad Request.
|
||||
|
||||
Below is an example of the `remotePatterns` property in the `next.config.js` file using a wildcard pattern in the `hostname`:
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
images: {
|
||||
remotePatterns: [
|
||||
{
|
||||
protocol: 'https',
|
||||
hostname: '**.example.com',
|
||||
port: '',
|
||||
search: '',
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
> **Good to know**: The example above will ensure the `src` property of `next/legacy/image` must start with `https://img1.example.com` or `https://me.avatar.example.com` or any number of subdomains. It cannot have a port or query string. Any other protocol or unmatched hostname will respond with 400 Bad Request.
|
||||
|
||||
Wildcard patterns can be used for both `pathname` and `hostname` and have the following syntax:
|
||||
|
||||
- `*` match a single path segment or subdomain
|
||||
- `**` match any number of path segments at the end or subdomains at the beginning
|
||||
|
||||
The `**` syntax does not work in the middle of the pattern.
|
||||
|
||||
> **Good to know**: When omitting `protocol`, `port`, `pathname`, or `search` then the wildcard `**` is implied. This is not recommended because it may allow malicious actors to optimize urls you did not intend.
|
||||
|
||||
Below is an example of the `remotePatterns` property in the `next.config.js` file using `search`:
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
images: {
|
||||
remotePatterns: [
|
||||
{
|
||||
protocol: 'https',
|
||||
hostname: 'assets.example.com',
|
||||
search: '?v=1727111025337',
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
> **Good to know**: The example above will ensure the `src` property of `next/legacy/image` must start with `https://assets.example.com` and must have the exact query string `?v=1727111025337`. Any other protocol or query string will respond with 400 Bad Request.
|
||||
|
||||
### Domains
|
||||
|
||||
> **Warning**: Deprecated since Next.js 14 in favor of strict [`remotePatterns`](#remote-patterns) in order to protect your application from malicious users. Only use `domains` if you own all the content served from the domain.
|
||||
|
||||
Similar to [`remotePatterns`](#remote-patterns), the `domains` configuration can be used to provide a list of allowed hostnames for external images.
|
||||
|
||||
However, the `domains` configuration does not support wildcard pattern matching and it cannot restrict protocol, port, or pathname.
|
||||
|
||||
Below is an example of the `domains` property in the `next.config.js` file:
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
images: {
|
||||
domains: ['assets.acme.com'],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Loader Configuration
|
||||
|
||||
If you want to use a cloud provider to optimize images instead of using the Next.js built-in Image Optimization API, you can configure the `loader` and `path` prefix in your `next.config.js` file. This allows you to use relative URLs for the Image [`src`](#src) and automatically generate the correct absolute URL for your provider.
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
images: {
|
||||
loader: 'imgix',
|
||||
path: 'https://example.com/myaccount/',
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
#### Customizing the Built-in Image Path
|
||||
|
||||
If you want to change or prefix the default path for the built-in Next.js image optimization, you can do so with the `path` property. The default value for `path` is `/_next/image`.
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
images: {
|
||||
path: '/my-prefix/_next/image',
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Built-in Loaders
|
||||
|
||||
The following Image Optimization cloud providers are included:
|
||||
|
||||
- Default: Works automatically with `next dev`, `next start`, or a custom server
|
||||
- [Vercel](https://vercel.com): Works automatically when you deploy on Vercel, no configuration necessary. [Learn more](https://vercel.com/docs/concepts/image-optimization?utm_source=next-site&utm_medium=docs&utm_campaign=next-website)
|
||||
- [Imgix](https://www.imgix.com): `loader: 'imgix'`
|
||||
- [Cloudinary](https://cloudinary.com): `loader: 'cloudinary'`
|
||||
- [Akamai](https://www.akamai.com): `loader: 'akamai'`
|
||||
- Custom: `loader: 'custom'` use a custom cloud provider by implementing the [`loader`](#loader) prop on the `next/legacy/image` component
|
||||
|
||||
If you need a different provider, you can use the [`loader`](#loader) prop with `next/legacy/image`.
|
||||
|
||||
> Images cannot be optimized at build time using [`output: 'export'`](/docs/pages/guides/static-exports), only on-demand. To use `next/legacy/image` with `output: 'export'`, you will need to use a different loader than the default. [Read more in the discussion.](https://github.com/vercel/next.js/discussions/19065)
|
||||
|
||||
## Advanced
|
||||
|
||||
The following configuration is for advanced use cases and is usually not necessary. If you choose to configure the properties below, you will override any changes to the Next.js defaults in future updates.
|
||||
|
||||
### Device Sizes
|
||||
|
||||
If you know the expected device widths of your users, you can specify a list of device width breakpoints using the `deviceSizes` property in `next.config.js`. These widths are used when the `next/legacy/image` component uses `layout="responsive"` or `layout="fill"` to ensure the correct image is served for user's device.
|
||||
|
||||
If no configuration is provided, the default below is used.
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
images: {
|
||||
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Image Sizes
|
||||
|
||||
You can specify a list of image widths using the `images.imageSizes` property in your `next.config.js` file. These widths are concatenated with the array of [device sizes](#device-sizes) to form the full array of sizes used to generate image [srcset](https://developer.mozilla.org/docs/Web/API/HTMLImageElement/srcset)s.
|
||||
|
||||
The reason there are two separate lists is that imageSizes is only used for images which provide a [`sizes`](#sizes) prop, which indicates that the image is less than the full width of the screen. **Therefore, the sizes in imageSizes should all be smaller than the smallest size in deviceSizes.**
|
||||
|
||||
If no configuration is provided, the default below is used.
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
images: {
|
||||
imageSizes: [32, 48, 64, 96, 128, 256, 384],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Acceptable Formats
|
||||
|
||||
The default [Image Optimization API](#loader-configuration) will automatically detect the browser's supported image formats via the request's `Accept` header in order to determine the best output format.
|
||||
|
||||
If the `Accept` header matches more than one of the configured formats, the first match in the array is used. Therefore, the array order matters. If there is no match (or the source image is [animated](#animated-images)), the Image Optimization API will fallback to the original image's format.
|
||||
|
||||
If no configuration is provided, the default below is used.
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
images: {
|
||||
formats: ['image/webp'],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
You can enable AVIF support, which will fallback to the original format of the src image if the browser [does not support AVIF](https://caniuse.com/avif):
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
images: {
|
||||
formats: ['image/avif'],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
You can also enable both AVIF and WebP formats together. AVIF will be preferred for browsers that support it, with WebP as a fallback:
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
images: {
|
||||
formats: ['image/avif', 'image/webp'],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
> **Good to know**:
|
||||
>
|
||||
> - We still recommend using WebP for most use cases.
|
||||
> - AVIF generally takes 50% longer to encode but it compresses 20% smaller compared to WebP. This means that the first time an image is requested, it will typically be slower and then subsequent requests that are cached will be faster.
|
||||
> - When using multiple formats, Next.js will cache each format separately. This means increased storage requirements compared to using a single format, as both AVIF and WebP versions of images will be stored for different browser support.
|
||||
> - If you self-host with a Proxy/CDN in front of Next.js, you must configure the Proxy to forward the `Accept` header.
|
||||
|
||||
## Caching Behavior
|
||||
|
||||
The following describes the caching algorithm for the default [loader](#loader). For all other loaders, please refer to your cloud provider's documentation.
|
||||
|
||||
Images are optimized dynamically upon request and stored in the `<distDir>/cache/images` directory. The optimized image file will be served for subsequent requests until the expiration is reached. When a request is made that matches a cached but expired file, the expired image is served stale immediately. Then the image is optimized again in the background (also called revalidation) and saved to the cache with the new expiration date.
|
||||
|
||||
The cache status of an image can be determined by reading the value of the `x-nextjs-cache` (`x-vercel-cache` when deployed on Vercel) response header. The possible values are the following:
|
||||
|
||||
- `MISS` - the path is not in the cache (occurs at most once, on the first visit)
|
||||
- `STALE` - the path is in the cache but exceeded the revalidate time so it will be updated in the background
|
||||
- `HIT` - the path is in the cache and has not exceeded the revalidate time
|
||||
|
||||
The expiration (or rather Max Age) is defined by either the [`minimumCacheTTL`](#minimum-cache-ttl) configuration or the upstream image `Cache-Control` header, whichever is larger. Specifically, the `max-age` value of the `Cache-Control` header is used. If both `s-maxage` and `max-age` are found, then `s-maxage` is preferred. The `max-age` is also passed-through to any downstream clients including CDNs and browsers.
|
||||
|
||||
- You can configure [`minimumCacheTTL`](#minimum-cache-ttl) to increase the cache duration when the upstream image does not include `Cache-Control` header or the value is very low.
|
||||
- You can configure [`deviceSizes`](#device-sizes) and [`imageSizes`](#image-sizes) to reduce the total number of possible generated images.
|
||||
- You can configure [formats](#acceptable-formats) to disable multiple formats in favor of a single image format.
|
||||
|
||||
### Minimum Cache TTL
|
||||
|
||||
You can configure the Time to Live (TTL) in seconds for cached optimized images. In many cases, it's better to use a [Static Image Import](/docs/pages/api-reference/components/image#src) which will automatically hash the file contents and cache the image forever with a `Cache-Control` header of `immutable`.
|
||||
|
||||
If no configuration is provided, the default below is used.
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
images: {
|
||||
minimumCacheTTL: 14400, // 4 hours
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
You can increase the TTL to reduce the number of revalidations and potentially lower cost:
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
images: {
|
||||
minimumCacheTTL: 2678400, // 31 days
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
The expiration (or rather Max Age) of the optimized image is defined by either the `minimumCacheTTL` or the upstream image `Cache-Control` header, whichever is larger.
|
||||
|
||||
If you need to change the caching behavior per image, you can configure [`headers`](/docs/pages/api-reference/config/next-config-js/headers) to set the `Cache-Control` header on the upstream image (e.g. `/some-asset.jpg`, not `/_next/image` itself).
|
||||
|
||||
There is no mechanism to invalidate the cache at this time, so its best to keep `minimumCacheTTL` low. Otherwise you may need to manually change the [`src`](#src) prop or delete `<distDir>/cache/images`.
|
||||
|
||||
### Disable Static Imports
|
||||
|
||||
The default behavior allows you to import static files such as `import icon from './icon.png'` and then pass that to the `src` property.
|
||||
|
||||
In some cases, you may wish to disable this feature if it conflicts with other plugins that expect the import to behave differently.
|
||||
|
||||
You can disable static image imports inside your `next.config.js`:
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
images: {
|
||||
disableStaticImages: true,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Dangerously Allow SVG
|
||||
|
||||
The default [loader](#loader) does not optimize SVG images for a few reasons. First, SVG is a vector format meaning it can be resized losslessly. Second, SVG has many of the same features as HTML/CSS, which can lead to vulnerabilities without proper [Content Security Policy (CSP) headers](/docs/app/api-reference/config/next-config-js/headers#content-security-policy).
|
||||
|
||||
Therefore, we recommended using the [`unoptimized`](#unoptimized) prop when the [`src`](#src) prop is known to be SVG. This happens automatically when `src` ends with `".svg"`.
|
||||
|
||||
However, if you need to serve SVG images with the default Image Optimization API, you can set `dangerouslyAllowSVG` inside your `next.config.js`:
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
images: {
|
||||
dangerouslyAllowSVG: true,
|
||||
contentDispositionType: 'attachment',
|
||||
contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;",
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
In addition, it is strongly recommended to also set `contentDispositionType` to force the browser to download the image, as well as `contentSecurityPolicy` to prevent scripts embedded in the image from executing.
|
||||
|
||||
### `contentDispositionType`
|
||||
|
||||
The default [loader](#loader) sets the [`Content-Disposition`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition#as_a_response_header_for_the_main_body) header to `attachment` for added protection since the API can serve arbitrary remote images.
|
||||
|
||||
The default value is `attachment` which forces the browser to download the image when visiting directly. This is particularly important when [`dangerouslyAllowSVG`](#dangerously-allow-svg) is true.
|
||||
|
||||
You can optionally configure `inline` to allow the browser to render the image when visiting directly, without downloading it.
|
||||
|
||||
```js filename="next.config.js"
|
||||
module.exports = {
|
||||
images: {
|
||||
contentDispositionType: 'inline',
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Animated Images
|
||||
|
||||
The default [loader](#loader) will automatically bypass Image Optimization for animated images and serve the image as-is.
|
||||
|
||||
Auto-detection for animated files is best-effort and supports GIF, APNG, and WebP. If you want to explicitly bypass Image Optimization for a given animated image, use the [unoptimized](#unoptimized) prop.
|
||||
|
||||
## Version History
|
||||
|
||||
| Version | Changes |
|
||||
| --------- | ------------------------------------------------------------------------------------------------------------------- |
|
||||
| `v16.0.0` | `next/legacy/image` deprecated and will be removed in a future version of Next.js. Please use `next/image` instead. |
|
||||
| `v13.0.0` | `next/image` renamed to `next/legacy/image` |
|
||||
7
node_modules/next/dist/docs/02-pages/04-api-reference/01-components/image.md
generated
vendored
Normal file
7
node_modules/next/dist/docs/02-pages/04-api-reference/01-components/image.md
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Image
|
||||
description: Optimize Images in your Next.js Application using the built-in `next/image` Component.
|
||||
source: app/api-reference/components/image
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
7
node_modules/next/dist/docs/02-pages/04-api-reference/01-components/index.md
generated
vendored
Normal file
7
node_modules/next/dist/docs/02-pages/04-api-reference/01-components/index.md
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Components
|
||||
description: API Reference for Next.js built-in components in the Pages Router.
|
||||
source: app/api-reference/components
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
7
node_modules/next/dist/docs/02-pages/04-api-reference/01-components/link.md
generated
vendored
Normal file
7
node_modules/next/dist/docs/02-pages/04-api-reference/01-components/link.md
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Link
|
||||
description: API reference for the `<Link>` component.
|
||||
source: app/api-reference/components/link
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
7
node_modules/next/dist/docs/02-pages/04-api-reference/01-components/script.md
generated
vendored
Normal file
7
node_modules/next/dist/docs/02-pages/04-api-reference/01-components/script.md
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Script
|
||||
description: Optimize third-party scripts in your Next.js application using the built-in `next/script` Component.
|
||||
source: app/api-reference/components/script
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
4
node_modules/next/dist/docs/02-pages/04-api-reference/02-file-conventions/index.md
generated
vendored
Normal file
4
node_modules/next/dist/docs/02-pages/04-api-reference/02-file-conventions/index.md
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: File-system conventions
|
||||
description: API Reference for Next.js file-system conventions.
|
||||
---
|
||||
7
node_modules/next/dist/docs/02-pages/04-api-reference/02-file-conventions/instrumentation.md
generated
vendored
Normal file
7
node_modules/next/dist/docs/02-pages/04-api-reference/02-file-conventions/instrumentation.md
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: instrumentation.js
|
||||
description: API reference for the instrumentation.js file.
|
||||
source: app/api-reference/file-conventions/instrumentation
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
7
node_modules/next/dist/docs/02-pages/04-api-reference/02-file-conventions/proxy.md
generated
vendored
Normal file
7
node_modules/next/dist/docs/02-pages/04-api-reference/02-file-conventions/proxy.md
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Proxy
|
||||
description: Learn how to use Proxy to run code before a request is completed.
|
||||
source: app/api-reference/file-conventions/proxy
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
8
node_modules/next/dist/docs/02-pages/04-api-reference/02-file-conventions/public-folder.md
generated
vendored
Normal file
8
node_modules/next/dist/docs/02-pages/04-api-reference/02-file-conventions/public-folder.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: public Folder
|
||||
nav_title: public
|
||||
description: Next.js allows you to serve static files, like images, in the public directory. You can learn how it works here.
|
||||
source: app/api-reference/file-conventions/public-folder
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
7
node_modules/next/dist/docs/02-pages/04-api-reference/02-file-conventions/src-folder.md
generated
vendored
Normal file
7
node_modules/next/dist/docs/02-pages/04-api-reference/02-file-conventions/src-folder.md
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: src Directory
|
||||
description: Save pages under the `src` folder as an alternative to the root `pages` directory.
|
||||
source: app/api-reference/file-conventions/src-folder
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
58
node_modules/next/dist/docs/02-pages/04-api-reference/03-functions/get-initial-props.md
generated
vendored
Normal file
58
node_modules/next/dist/docs/02-pages/04-api-reference/03-functions/get-initial-props.md
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
---
|
||||
title: getInitialProps
|
||||
description: Fetch dynamic data on the server for your React component with getInitialProps.
|
||||
---
|
||||
|
||||
> **Good to know**: `getInitialProps` is a legacy API. We recommend using [`getStaticProps`](/docs/pages/building-your-application/data-fetching/get-static-props) or [`getServerSideProps`](/docs/pages/building-your-application/data-fetching/get-server-side-props) instead.
|
||||
|
||||
`getInitialProps` is an `async` function that can be added to the default exported React component for the page. It will run on both the server-side and again on the client-side during page transitions. The result of the function will be forwarded to the React component as `props`.
|
||||
|
||||
```tsx filename="pages/index.tsx" switcher
|
||||
import { NextPageContext } from 'next'
|
||||
|
||||
Page.getInitialProps = async (ctx: NextPageContext) => {
|
||||
const res = await fetch('https://api.github.com/repos/vercel/next.js')
|
||||
const json = await res.json()
|
||||
return { stars: json.stargazers_count }
|
||||
}
|
||||
|
||||
export default function Page({ stars }: { stars: number }) {
|
||||
return stars
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/index.js" switcher
|
||||
Page.getInitialProps = async (ctx) => {
|
||||
const res = await fetch('https://api.github.com/repos/vercel/next.js')
|
||||
const json = await res.json()
|
||||
return { stars: json.stargazers_count }
|
||||
}
|
||||
|
||||
export default function Page({ stars }) {
|
||||
return stars
|
||||
}
|
||||
```
|
||||
|
||||
> **Good to know**:
|
||||
>
|
||||
> - Data returned from `getInitialProps` is serialized when server rendering. Ensure the returned object from `getInitialProps` is a plain `Object`, and not using `Date`, `Map` or `Set`.
|
||||
> - For the initial page load, `getInitialProps` will run on the server only. `getInitialProps` will then also run on the client when navigating to a different route with the [`next/link`](/docs/pages/api-reference/components/link) component or by using [`next/router`](/docs/pages/api-reference/functions/use-router).
|
||||
> - If `getInitialProps` is used in a custom `_app.js`, and the page being navigated to is using `getServerSideProps`, then `getInitialProps` will **only** run on the server.
|
||||
|
||||
## Context Object
|
||||
|
||||
`getInitialProps` receives a single argument called `context`, which is an object with the following properties:
|
||||
|
||||
| Name | Description |
|
||||
| ---------- | ----------------------------------------------------------------------------------------------------- |
|
||||
| `pathname` | Current route, the path of the page in `/pages` |
|
||||
| `query` | Query string of the URL, parsed as an object |
|
||||
| `asPath` | `String` of the actual path (including the query) shown in the browser |
|
||||
| `req` | [HTTP request object](https://nodejs.org/api/http.html#http_class_http_incomingmessage) (server only) |
|
||||
| `res` | [HTTP response object](https://nodejs.org/api/http.html#http_class_http_serverresponse) (server only) |
|
||||
| `err` | Error object if any error is encountered during the rendering |
|
||||
|
||||
## Caveats
|
||||
|
||||
- `getInitialProps` can only be used in `pages/` top level files, and not in nested components. To have nested data fetching at the component level, consider exploring the [App Router](/docs/app/getting-started/fetching-data).
|
||||
- Regardless of whether your route is static or dynamic, any data returned from `getInitialProps` as `props` will be able to be examined on the client-side in the initial HTML. This is to allow the page to be [hydrated](https://react.dev/reference/react-dom/hydrate) correctly. Make sure that you don't pass any sensitive information that shouldn't be available on the client in `props`.
|
||||
140
node_modules/next/dist/docs/02-pages/04-api-reference/03-functions/get-server-side-props.md
generated
vendored
Normal file
140
node_modules/next/dist/docs/02-pages/04-api-reference/03-functions/get-server-side-props.md
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
---
|
||||
title: getServerSideProps
|
||||
description: API reference for `getServerSideProps`. Learn how to fetch data on each request with Next.js.
|
||||
---
|
||||
|
||||
When exporting a function called `getServerSideProps` (Server-Side Rendering) from a page, Next.js will prerender this page on each request using the data returned by `getServerSideProps`. This is useful if you want to fetch data that changes often, and have the page update to show the most current data.
|
||||
|
||||
```tsx filename="pages/index.tsx" switcher
|
||||
import type { InferGetServerSidePropsType, GetServerSideProps } from 'next'
|
||||
|
||||
type Repo = {
|
||||
name: string
|
||||
stargazers_count: number
|
||||
}
|
||||
|
||||
export const getServerSideProps = (async () => {
|
||||
// Fetch data from external API
|
||||
const res = await fetch('https://api.github.com/repos/vercel/next.js')
|
||||
const repo: Repo = await res.json()
|
||||
// Pass data to the page via props
|
||||
return { props: { repo } }
|
||||
}) satisfies GetServerSideProps<{ repo: Repo }>
|
||||
|
||||
export default function Page({
|
||||
repo,
|
||||
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
|
||||
return (
|
||||
<main>
|
||||
<p>{repo.stargazers_count}</p>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/index.js" switcher
|
||||
export async function getServerSideProps() {
|
||||
// Fetch data from external API
|
||||
const res = await fetch('https://api.github.com/repos/vercel/next.js')
|
||||
const repo = await res.json()
|
||||
// Pass data to the page via props
|
||||
return { props: { repo } }
|
||||
}
|
||||
|
||||
export default function Page({ repo }) {
|
||||
return (
|
||||
<main>
|
||||
<p>{repo.stargazers_count}</p>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
You can import modules in top-level scope for use in `getServerSideProps`. Imports used will **not be bundled for the client-side**. This means you can write **server-side code directly in `getServerSideProps`**, including fetching data from your database.
|
||||
|
||||
## Context parameter
|
||||
|
||||
The `context` parameter is an object containing the following keys:
|
||||
|
||||
| Name | Description |
|
||||
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `params` | If this page uses a [dynamic route](/docs/pages/building-your-application/routing/dynamic-routes), `params` contains the route parameters. If the page name is `[id].js`, then `params` will look like `{ id: ... }`. |
|
||||
| `req` | [The `HTTP` IncomingMessage object](https://nodejs.org/api/http.html#http_class_http_incomingmessage), with an additional `cookies` prop, which is an object with string keys mapping to string values of cookies. |
|
||||
| `res` | [The `HTTP` response object](https://nodejs.org/api/http.html#http_class_http_serverresponse). |
|
||||
| `query` | An object representing the query string, including dynamic route parameters. |
|
||||
| `preview` | (Deprecated for `draftMode`) `preview` is `true` if the page is in the [Preview Mode](/docs/pages/guides/preview-mode) and `false` otherwise. |
|
||||
| `previewData` | (Deprecated for `draftMode`) The [preview](/docs/pages/guides/preview-mode) data set by `setPreviewData`. |
|
||||
| `draftMode` | `draftMode` is `true` if the page is in the [Draft Mode](/docs/pages/guides/draft-mode) and `false` otherwise. |
|
||||
| `resolvedUrl` | A normalized version of the request `URL` that strips the `_next/data` prefix for client transitions and includes original query values. |
|
||||
| `locale` | Contains the active locale (if enabled). |
|
||||
| `locales` | Contains all supported locales (if enabled). |
|
||||
| `defaultLocale` | Contains the configured default locale (if enabled). |
|
||||
|
||||
## getServerSideProps return values
|
||||
|
||||
The `getServerSideProps` function should return an object with **any one of the following** properties:
|
||||
|
||||
### `props`
|
||||
|
||||
The `props` object is a key-value pair, where each value is received by the page component. It should be a [serializable object](https://developer.mozilla.org/docs/Glossary/Serialization) so that any props passed, could be serialized with [`JSON.stringify`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify).
|
||||
|
||||
```jsx
|
||||
export async function getServerSideProps(context) {
|
||||
return {
|
||||
props: { message: `Next.js is awesome` }, // will be passed to the page component as props
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### `notFound`
|
||||
|
||||
The `notFound` boolean allows the page to return a `404` status and [404 Page](/docs/pages/building-your-application/routing/custom-error#404-page). With `notFound: true`, the page will return a `404` even if there was a successfully generated page before. This is meant to support use cases like user-generated content getting removed by its author.
|
||||
|
||||
```js
|
||||
export async function getServerSideProps(context) {
|
||||
const res = await fetch(`https://.../data`)
|
||||
const data = await res.json()
|
||||
|
||||
if (!data) {
|
||||
return {
|
||||
notFound: true,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
props: { data }, // will be passed to the page component as props
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### `redirect`
|
||||
|
||||
The `redirect` object allows redirecting to internal and external resources. It should match the shape of `{ destination: string, permanent: boolean }`. In some rare cases, you might need to assign a custom status code for older `HTTP` clients to properly redirect. In these cases, you can use the `statusCode` property instead of the `permanent` property, but not both.
|
||||
|
||||
```js
|
||||
export async function getServerSideProps(context) {
|
||||
const res = await fetch(`https://.../data`)
|
||||
const data = await res.json()
|
||||
|
||||
if (!data) {
|
||||
return {
|
||||
redirect: {
|
||||
destination: '/',
|
||||
permanent: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
props: {}, // will be passed to the page component as props
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Version History
|
||||
|
||||
| Version | Changes |
|
||||
| --------- | ------------------------------------------------------------------------------------------------- |
|
||||
| `v13.4.0` | [App Router](/docs/app/getting-started/fetching-data) is now stable with simplified data fetching |
|
||||
| `v10.0.0` | `locale`, `locales`, `defaultLocale`, and `notFound` options added. |
|
||||
| `v9.3.0` | `getServerSideProps` introduced. |
|
||||
259
node_modules/next/dist/docs/02-pages/04-api-reference/03-functions/get-static-paths.md
generated
vendored
Normal file
259
node_modules/next/dist/docs/02-pages/04-api-reference/03-functions/get-static-paths.md
generated
vendored
Normal file
@@ -0,0 +1,259 @@
|
||||
---
|
||||
title: getStaticPaths
|
||||
description: API reference for `getStaticPaths`. Learn how to fetch data and generate static pages with `getStaticPaths`.
|
||||
---
|
||||
|
||||
When exporting a function called `getStaticPaths` from a page that uses [Dynamic Routes](/docs/pages/building-your-application/routing/dynamic-routes), Next.js will statically prerender all the paths specified by `getStaticPaths`.
|
||||
|
||||
```tsx filename="pages/repo/[name].tsx" switcher
|
||||
import type {
|
||||
InferGetStaticPropsType,
|
||||
GetStaticProps,
|
||||
GetStaticPaths,
|
||||
} from 'next'
|
||||
|
||||
type Repo = {
|
||||
name: string
|
||||
stargazers_count: number
|
||||
}
|
||||
|
||||
export const getStaticPaths = (async () => {
|
||||
return {
|
||||
paths: [
|
||||
{
|
||||
params: {
|
||||
name: 'next.js',
|
||||
},
|
||||
}, // See the "paths" section below
|
||||
],
|
||||
fallback: true, // false or "blocking"
|
||||
}
|
||||
}) satisfies GetStaticPaths
|
||||
|
||||
export const getStaticProps = (async (context) => {
|
||||
const res = await fetch('https://api.github.com/repos/vercel/next.js')
|
||||
const repo = await res.json()
|
||||
return { props: { repo } }
|
||||
}) satisfies GetStaticProps<{
|
||||
repo: Repo
|
||||
}>
|
||||
|
||||
export default function Page({
|
||||
repo,
|
||||
}: InferGetStaticPropsType<typeof getStaticProps>) {
|
||||
return repo.stargazers_count
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/repo/[name].js" switcher
|
||||
export async function getStaticPaths() {
|
||||
return {
|
||||
paths: [
|
||||
{
|
||||
params: {
|
||||
name: 'next.js',
|
||||
},
|
||||
}, // See the "paths" section below
|
||||
],
|
||||
fallback: true, // false or "blocking"
|
||||
}
|
||||
}
|
||||
|
||||
export async function getStaticProps() {
|
||||
const res = await fetch('https://api.github.com/repos/vercel/next.js')
|
||||
const repo = await res.json()
|
||||
return { props: { repo } }
|
||||
}
|
||||
|
||||
export default function Page({ repo }) {
|
||||
return repo.stargazers_count
|
||||
}
|
||||
```
|
||||
|
||||
## getStaticPaths return values
|
||||
|
||||
The `getStaticPaths` function should return an object with the following **required** properties:
|
||||
|
||||
### `paths`
|
||||
|
||||
The `paths` key determines which paths will be prerendered. For example, suppose that you have a page that uses [Dynamic Routes](/docs/pages/building-your-application/routing/dynamic-routes) named `pages/posts/[id].js`. If you export `getStaticPaths` from this page and return the following for `paths`:
|
||||
|
||||
```js
|
||||
return {
|
||||
paths: [
|
||||
{ params: { id: '1' }},
|
||||
{
|
||||
params: { id: '2' },
|
||||
// with i18n configured the locale for the path can be returned as well
|
||||
locale: "en",
|
||||
},
|
||||
],
|
||||
fallback: ...
|
||||
}
|
||||
```
|
||||
|
||||
Then, Next.js will statically generate `/posts/1` and `/posts/2` during `next build` using the page component in `pages/posts/[id].js`.
|
||||
|
||||
The value for each `params` object must match the parameters used in the page name:
|
||||
|
||||
- If the page name is `pages/posts/[postId]/[commentId]`, then `params` should contain `postId` and `commentId`.
|
||||
- If the page name uses [catch-all routes](/docs/pages/building-your-application/routing/dynamic-routes#catch-all-segments) like `pages/[...slug]`, then `params` should contain `slug` (which is an array). If this array is `['hello', 'world']`, then Next.js will statically generate the page at `/hello/world`.
|
||||
- If the page uses an [optional catch-all route](/docs/pages/building-your-application/routing/dynamic-routes#optional-catch-all-segments), use `null`, `[]`, `undefined` or `false` to render the root-most route. For example, if you supply `slug: false` for `pages/[[...slug]]`, Next.js will statically generate the page `/`.
|
||||
|
||||
The `params` strings are **case-sensitive** and ideally should be normalized to ensure the paths are generated correctly. For example, if `WoRLD` is returned for a param it will only match if `WoRLD` is the actual path visited, not `world` or `World`.
|
||||
|
||||
Separate of the `params` object a `locale` field can be returned when [i18n is configured](/docs/pages/guides/internationalization), which configures the locale for the path being generated.
|
||||
|
||||
### `fallback: false`
|
||||
|
||||
If `fallback` is `false`, then any paths not returned by `getStaticPaths` will result in a **404 page**.
|
||||
|
||||
When `next build` is run, Next.js will check if `getStaticPaths` returned `fallback: false`, it will then build **only** the paths returned by `getStaticPaths`. This option is useful if you have a small number of paths to create, or new page data is not added often. If you find that you need to add more paths, and you have `fallback: false`, you will need to run `next build` again so that the new paths can be generated.
|
||||
|
||||
The following example prerenders one blog post per page called `pages/posts/[id].js`. The list of blog posts will be fetched from a CMS and returned by `getStaticPaths`. Then, for each page, it fetches the post data from a CMS using [`getStaticProps`](/docs/pages/building-your-application/data-fetching/get-static-props).
|
||||
|
||||
```jsx filename="pages/posts/[id].js"
|
||||
function Post({ post }) {
|
||||
// Render post...
|
||||
}
|
||||
|
||||
// This function gets called at build time
|
||||
export async function getStaticPaths() {
|
||||
// Call an external API endpoint to get posts
|
||||
const res = await fetch('https://.../posts')
|
||||
const posts = await res.json()
|
||||
|
||||
// Get the paths we want to prerender based on posts
|
||||
const paths = posts.map((post) => ({
|
||||
params: { id: post.id },
|
||||
}))
|
||||
|
||||
// We'll prerender only these paths at build time.
|
||||
// { fallback: false } means other routes should 404.
|
||||
return { paths, fallback: false }
|
||||
}
|
||||
|
||||
// This also gets called at build time
|
||||
export async function getStaticProps({ params }) {
|
||||
// params contains the post `id`.
|
||||
// If the route is like /posts/1, then params.id is 1
|
||||
const res = await fetch(`https://.../posts/${params.id}`)
|
||||
const post = await res.json()
|
||||
|
||||
// Pass post data to the page via props
|
||||
return { props: { post } }
|
||||
}
|
||||
|
||||
export default Post
|
||||
```
|
||||
|
||||
### `fallback: true`
|
||||
|
||||
<details>
|
||||
<summary>Examples</summary>
|
||||
|
||||
- [Static generation of a large number of pages](https://react-tweet.vercel.app/)
|
||||
|
||||
</details>
|
||||
|
||||
If `fallback` is `true`, then the behavior of `getStaticProps` changes in the following ways:
|
||||
|
||||
- The paths returned from `getStaticPaths` will be rendered to `HTML` at build time by `getStaticProps`.
|
||||
- The paths that have not been generated at build time will **not** result in a 404 page. Instead, Next.js will serve a [“fallback”](#fallback-pages) version of the page on the first request to such a path. Web crawlers, such as Google, won't be served a fallback and instead the path will behave as in [`fallback: 'blocking'`](#fallback-blocking).
|
||||
- When a page with `fallback: true` is navigated to through `next/link` or `next/router` (client-side) Next.js will _not_ serve a fallback and instead the page will behave as [`fallback: 'blocking'`](#fallback-blocking).
|
||||
- In the background, Next.js will statically generate the requested path `HTML` and `JSON`. This includes running `getStaticProps`.
|
||||
- When complete, the browser receives the `JSON` for the generated path. This will be used to automatically render the page with the required props. From the user’s perspective, the page will be swapped from the fallback page to the full page.
|
||||
- At the same time, Next.js adds this path to the list of prerendered pages. Subsequent requests to the same path will serve the generated page, like other pages prerendered at build time.
|
||||
|
||||
> **Good to know**: `fallback: true` is not supported when using [`output: 'export'`](/docs/pages/guides/static-exports).
|
||||
|
||||
#### When is `fallback: true` useful?
|
||||
|
||||
`fallback: true` is useful if your app has a very large number of static pages that depend on data (such as a very large e-commerce site). If you want to prerender all product pages, the builds would take a very long time.
|
||||
|
||||
Instead, you may statically generate a small subset of pages and use `fallback: true` for the rest. When someone requests a page that is not generated yet, the user will see the page with a loading indicator or skeleton component.
|
||||
|
||||
Shortly after, `getStaticProps` finishes and the page will be rendered with the requested data. From now on, everyone who requests the same page will get the statically prerendered page.
|
||||
|
||||
This ensures that users always have a fast experience while preserving fast builds and the benefits of Static Generation.
|
||||
|
||||
`fallback: true` will not _update_ generated pages, for that take a look at [Incremental Static Regeneration](/docs/pages/guides/incremental-static-regeneration).
|
||||
|
||||
### `fallback: 'blocking'`
|
||||
|
||||
If `fallback` is `'blocking'`, new paths not returned by `getStaticPaths` will wait for the `HTML` to be generated, identical to SSR (hence why _blocking_), and then be cached for future requests so it only happens once per path.
|
||||
|
||||
`getStaticProps` will behave as follows:
|
||||
|
||||
- The paths returned from `getStaticPaths` will be rendered to `HTML` at build time by `getStaticProps`.
|
||||
- The paths that have not been generated at build time will **not** result in a 404 page. Instead, Next.js will SSR on the first request and return the generated `HTML`.
|
||||
- When complete, the browser receives the `HTML` for the generated path. From the user’s perspective, it will transition from "the browser is requesting the page" to "the full page is loaded". There is no flash of loading/fallback state.
|
||||
- At the same time, Next.js adds this path to the list of prerendered pages. Subsequent requests to the same path will serve the generated page, like other pages prerendered at build time.
|
||||
|
||||
`fallback: 'blocking'` will not _update_ generated pages by default. To update generated pages, use [Incremental Static Regeneration](/docs/pages/guides/incremental-static-regeneration) in conjunction with `fallback: 'blocking'`.
|
||||
|
||||
> **Good to know**: `fallback: 'blocking'` is not supported when using [`output: 'export'`](/docs/pages/guides/static-exports).
|
||||
|
||||
### Fallback pages
|
||||
|
||||
In the “fallback” version of a page:
|
||||
|
||||
- The page’s props will be empty.
|
||||
- Using the [router](/docs/pages/api-reference/functions/use-router), you can detect if the fallback is being rendered, `router.isFallback` will be `true`.
|
||||
|
||||
The following example showcases using `isFallback`:
|
||||
|
||||
```jsx filename="pages/posts/[id].js"
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
function Post({ post }) {
|
||||
const router = useRouter()
|
||||
|
||||
// If the page is not yet generated, this will be displayed
|
||||
// initially until getStaticProps() finishes running
|
||||
if (router.isFallback) {
|
||||
return <div>Loading...</div>
|
||||
}
|
||||
|
||||
// Render post...
|
||||
}
|
||||
|
||||
// This function gets called at build time
|
||||
export async function getStaticPaths() {
|
||||
return {
|
||||
// Only `/posts/1` and `/posts/2` are generated at build time
|
||||
paths: [{ params: { id: '1' } }, { params: { id: '2' } }],
|
||||
// Enable statically generating additional pages
|
||||
// For example: `/posts/3`
|
||||
fallback: true,
|
||||
}
|
||||
}
|
||||
|
||||
// This also gets called at build time
|
||||
export async function getStaticProps({ params }) {
|
||||
// params contains the post `id`.
|
||||
// If the route is like /posts/1, then params.id is 1
|
||||
const res = await fetch(`https://.../posts/${params.id}`)
|
||||
const post = await res.json()
|
||||
|
||||
// Pass post data to the page via props
|
||||
return {
|
||||
props: { post },
|
||||
// Re-generate the post at most once per second
|
||||
// if a request comes in
|
||||
revalidate: 1,
|
||||
}
|
||||
}
|
||||
|
||||
export default Post
|
||||
```
|
||||
|
||||
## Version History
|
||||
|
||||
| Version | Changes |
|
||||
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `v13.4.0` | [App Router](/docs/app/getting-started/fetching-data) is now stable with simplified data fetching, including [`generateStaticParams()`](/docs/app/api-reference/functions/generate-static-params) |
|
||||
| `v12.2.0` | [On-Demand Incremental Static Regeneration](/docs/pages/guides/incremental-static-regeneration#on-demand-revalidation-with-revalidatepath) is stable. |
|
||||
| `v12.1.0` | [On-Demand Incremental Static Regeneration](/docs/pages/guides/incremental-static-regeneration#on-demand-revalidation-with-revalidatepath) added (beta). |
|
||||
| `v9.5.0` | Stable [Incremental Static Regeneration](/docs/pages/guides/incremental-static-regeneration) |
|
||||
| `v9.3.0` | `getStaticPaths` introduced. |
|
||||
229
node_modules/next/dist/docs/02-pages/04-api-reference/03-functions/get-static-props.md
generated
vendored
Normal file
229
node_modules/next/dist/docs/02-pages/04-api-reference/03-functions/get-static-props.md
generated
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
---
|
||||
title: getStaticProps
|
||||
description: API reference for `getStaticProps`. Learn how to use `getStaticProps` to generate static pages with Next.js.
|
||||
---
|
||||
|
||||
Exporting a function called `getStaticProps` will prerender a page at build time using the props returned from the function:
|
||||
|
||||
```tsx filename="pages/index.tsx" switcher
|
||||
import type { InferGetStaticPropsType, GetStaticProps } from 'next'
|
||||
|
||||
type Repo = {
|
||||
name: string
|
||||
stargazers_count: number
|
||||
}
|
||||
|
||||
export const getStaticProps = (async (context) => {
|
||||
const res = await fetch('https://api.github.com/repos/vercel/next.js')
|
||||
const repo = await res.json()
|
||||
return { props: { repo } }
|
||||
}) satisfies GetStaticProps<{
|
||||
repo: Repo
|
||||
}>
|
||||
|
||||
export default function Page({
|
||||
repo,
|
||||
}: InferGetStaticPropsType<typeof getStaticProps>) {
|
||||
return repo.stargazers_count
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/index.js" switcher
|
||||
export async function getStaticProps() {
|
||||
const res = await fetch('https://api.github.com/repos/vercel/next.js')
|
||||
const repo = await res.json()
|
||||
return { props: { repo } }
|
||||
}
|
||||
|
||||
export default function Page({ repo }) {
|
||||
return repo.stargazers_count
|
||||
}
|
||||
```
|
||||
|
||||
You can import modules in top-level scope for use in `getStaticProps`. Imports used will **not be bundled for the client-side**. This means you can write **server-side code directly in `getStaticProps`**, including fetching data from your database.
|
||||
|
||||
## Context parameter
|
||||
|
||||
The `context` parameter is an object containing the following keys:
|
||||
|
||||
| Name | Description |
|
||||
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `params` | Contains the route parameters for pages using [dynamic routes](/docs/pages/building-your-application/routing/dynamic-routes). For example, if the page name is `[id].js`, then `params` will look like `{ id: ... }`. You should use this together with `getStaticPaths`, which we'll explain later. |
|
||||
| `preview` | (Deprecated for `draftMode`) `preview` is `true` if the page is in the [Preview Mode](/docs/pages/guides/preview-mode) and `false` otherwise. |
|
||||
| `previewData` | (Deprecated for `draftMode`) The [preview](/docs/pages/guides/preview-mode) data set by `setPreviewData`. |
|
||||
| `draftMode` | `draftMode` is `true` if the page is in the [Draft Mode](/docs/pages/guides/draft-mode) and `false` otherwise. |
|
||||
| `locale` | Contains the active locale (if enabled). |
|
||||
| `locales` | Contains all supported locales (if enabled). |
|
||||
| `defaultLocale` | Contains the configured default locale (if enabled). |
|
||||
| `revalidateReason` | Provides a reason for why the function was called. Can be one of: "build" (run at build time), "stale" (revalidate period expired, or running in [development mode](/docs/pages/building-your-application/data-fetching/get-static-props#runs-on-every-request-in-development)), "on-demand" (triggered via [on-demand revalidation](/docs/pages/guides/incremental-static-regeneration#on-demand-revalidation-with-revalidatepath)) |
|
||||
|
||||
## getStaticProps return values
|
||||
|
||||
The `getStaticProps` function should return an object containing either `props`, `redirect`, or `notFound` followed by an **optional** `revalidate` property.
|
||||
|
||||
### `props`
|
||||
|
||||
The `props` object is a key-value pair, where each value is received by the page component. It should be a [serializable object](https://developer.mozilla.org/docs/Glossary/Serialization) so that any props passed, could be serialized with [`JSON.stringify`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify).
|
||||
|
||||
```jsx
|
||||
export async function getStaticProps(context) {
|
||||
return {
|
||||
props: { message: `Next.js is awesome` }, // will be passed to the page component as props
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### `revalidate`
|
||||
|
||||
The `revalidate` property is the amount in seconds after which a page re-generation can occur (defaults to `false` or no revalidation).
|
||||
|
||||
```js
|
||||
// This function gets called at build time on server-side.
|
||||
// It may be called again, on a serverless function, if
|
||||
// revalidation is enabled and a new request comes in
|
||||
export async function getStaticProps() {
|
||||
const res = await fetch('https://.../posts')
|
||||
const posts = await res.json()
|
||||
|
||||
return {
|
||||
props: {
|
||||
posts,
|
||||
},
|
||||
// Next.js will attempt to re-generate the page:
|
||||
// - When a request comes in
|
||||
// - At most once every 10 seconds
|
||||
revalidate: 10, // In seconds
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Learn more about [Incremental Static Regeneration](/docs/pages/guides/incremental-static-regeneration).
|
||||
|
||||
The cache status of a page leveraging ISR can be determined by reading the value of the `x-nextjs-cache` response header. The possible values are the following:
|
||||
|
||||
- `MISS` - the path is not in the cache (occurs at most once, on the first visit)
|
||||
- `STALE` - the path is in the cache but exceeded the revalidate time so it will be updated in the background
|
||||
- `HIT` - the path is in the cache and has not exceeded the revalidate time
|
||||
|
||||
### `notFound`
|
||||
|
||||
The `notFound` boolean allows the page to return a `404` status and [404 Page](/docs/pages/building-your-application/routing/custom-error#404-page). With `notFound: true`, the page will return a `404` even if there was a successfully generated page before. This is meant to support use cases like user-generated content getting removed by its author. Note, `notFound` follows the same `revalidate` behavior [described here](#revalidate).
|
||||
|
||||
```js
|
||||
export async function getStaticProps(context) {
|
||||
const res = await fetch(`https://.../data`)
|
||||
const data = await res.json()
|
||||
|
||||
if (!data) {
|
||||
return {
|
||||
notFound: true,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
props: { data }, // will be passed to the page component as props
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> **Good to know**: `notFound` is not needed for [`fallback: false`](/docs/pages/api-reference/functions/get-static-paths#fallback-false) mode as only paths returned from `getStaticPaths` will be prerendered.
|
||||
|
||||
### `redirect`
|
||||
|
||||
The `redirect` object allows redirecting to internal or external resources. It should match the shape of `{ destination: string, permanent: boolean }`.
|
||||
|
||||
In some rare cases, you might need to assign a custom status code for older `HTTP` clients to properly redirect. In these cases, you can use the `statusCode` property instead of the `permanent` property, **but not both**. You can also set `basePath: false` similar to redirects in `next.config.js`.
|
||||
|
||||
```js
|
||||
export async function getStaticProps(context) {
|
||||
const res = await fetch(`https://...`)
|
||||
const data = await res.json()
|
||||
|
||||
if (!data) {
|
||||
return {
|
||||
redirect: {
|
||||
destination: '/',
|
||||
permanent: false,
|
||||
// statusCode: 301
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
props: { data }, // will be passed to the page component as props
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If the redirects are known at build-time, they should be added in [`next.config.js`](/docs/pages/api-reference/config/next-config-js/redirects) instead.
|
||||
|
||||
## Reading files: Use `process.cwd()`
|
||||
|
||||
Files can be read directly from the filesystem in `getStaticProps`.
|
||||
|
||||
In order to do so you have to get the full path to a file.
|
||||
|
||||
Since Next.js compiles your code into a separate directory you can't use `__dirname` as the path it returns will be different from the Pages Router.
|
||||
|
||||
Instead you can use `process.cwd()` which gives you the directory where Next.js is being executed.
|
||||
|
||||
```jsx
|
||||
import { promises as fs } from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
// posts will be populated at build time by getStaticProps()
|
||||
function Blog({ posts }) {
|
||||
return (
|
||||
<ul>
|
||||
{posts.map((post) => (
|
||||
<li>
|
||||
<h3>{post.filename}</h3>
|
||||
<p>{post.content}</p>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
|
||||
// This function gets called at build time on server-side.
|
||||
// It won't be called on client-side, so you can even do
|
||||
// direct database queries.
|
||||
export async function getStaticProps() {
|
||||
const postsDirectory = path.join(process.cwd(), 'posts')
|
||||
const filenames = await fs.readdir(postsDirectory)
|
||||
|
||||
const posts = filenames.map(async (filename) => {
|
||||
const filePath = path.join(postsDirectory, filename)
|
||||
const fileContents = await fs.readFile(filePath, 'utf8')
|
||||
|
||||
// Generally you would parse/transform the contents
|
||||
// For example you can transform markdown to HTML here
|
||||
|
||||
return {
|
||||
filename,
|
||||
content: fileContents,
|
||||
}
|
||||
})
|
||||
// By returning { props: { posts } }, the Blog component
|
||||
// will receive `posts` as a prop at build time
|
||||
return {
|
||||
props: {
|
||||
posts: await Promise.all(posts),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default Blog
|
||||
```
|
||||
|
||||
## Version History
|
||||
|
||||
| Version | Changes |
|
||||
| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `v13.4.0` | [App Router](/docs/app/getting-started/fetching-data) is now stable with simplified data fetching |
|
||||
| `v12.2.0` | [On-Demand Incremental Static Regeneration](/docs/pages/guides/incremental-static-regeneration#on-demand-revalidation-with-revalidatepath) is stable. |
|
||||
| `v12.1.0` | [On-Demand Incremental Static Regeneration](/docs/pages/guides/incremental-static-regeneration#on-demand-revalidation-with-revalidatepath) added (beta). |
|
||||
| `v10.0.0` | `locale`, `locales`, `defaultLocale`, and `notFound` options added. |
|
||||
| `v10.0.0` | `fallback: 'blocking'` return option added. |
|
||||
| `v9.5.0` | Stable [Incremental Static Regeneration](/docs/pages/guides/incremental-static-regeneration) |
|
||||
| `v9.3.0` | `getStaticProps` introduced. |
|
||||
7
node_modules/next/dist/docs/02-pages/04-api-reference/03-functions/index.md
generated
vendored
Normal file
7
node_modules/next/dist/docs/02-pages/04-api-reference/03-functions/index.md
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Functions
|
||||
description: API Reference for Functions and Hooks in Pages Router.
|
||||
source: app/api-reference/functions
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
7
node_modules/next/dist/docs/02-pages/04-api-reference/03-functions/next-request.md
generated
vendored
Normal file
7
node_modules/next/dist/docs/02-pages/04-api-reference/03-functions/next-request.md
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: NextRequest
|
||||
description: API Reference for NextRequest.
|
||||
source: app/api-reference/functions/next-request
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
7
node_modules/next/dist/docs/02-pages/04-api-reference/03-functions/next-response.md
generated
vendored
Normal file
7
node_modules/next/dist/docs/02-pages/04-api-reference/03-functions/next-response.md
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: NextResponse
|
||||
description: API Reference for NextResponse.
|
||||
source: app/api-reference/functions/next-response
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
242
node_modules/next/dist/docs/02-pages/04-api-reference/03-functions/use-params.md
generated
vendored
Normal file
242
node_modules/next/dist/docs/02-pages/04-api-reference/03-functions/use-params.md
generated
vendored
Normal file
@@ -0,0 +1,242 @@
|
||||
---
|
||||
title: useParams
|
||||
description: API Reference for the useParams hook in the Pages Router.
|
||||
---
|
||||
|
||||
`useParams` is a hook that lets you read a route's [dynamic params](/docs/pages/building-your-application/routing/dynamic-routes) filled in by the current URL.
|
||||
|
||||
```tsx filename="pages/shop/[slug].tsx" switcher
|
||||
import { useParams } from 'next/navigation'
|
||||
|
||||
export default function ShopPage() {
|
||||
const params = useParams<{ slug: string }>()
|
||||
|
||||
if (!params) {
|
||||
// Render fallback UI while params are not yet available
|
||||
return null
|
||||
}
|
||||
|
||||
// Route -> /shop/[slug]
|
||||
// URL -> /shop/shoes
|
||||
// `params` -> { slug: 'shoes' }
|
||||
return <>Shop: {params.slug}</>
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/shop/[slug].js" switcher
|
||||
import { useParams } from 'next/navigation'
|
||||
|
||||
export default function ShopPage() {
|
||||
const params = useParams()
|
||||
|
||||
if (!params) {
|
||||
// Render fallback UI while params are not yet available
|
||||
return null
|
||||
}
|
||||
|
||||
// Route -> /shop/[slug]
|
||||
// URL -> /shop/shoes
|
||||
// `params` -> { slug: 'shoes' }
|
||||
return <>Shop: {params.slug}</>
|
||||
}
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
```tsx
|
||||
const params = useParams()
|
||||
```
|
||||
|
||||
`useParams` does not take any parameters.
|
||||
|
||||
## Returns
|
||||
|
||||
`useParams` returns an object containing the current route's filled in [dynamic parameters](/docs/pages/building-your-application/routing/dynamic-routes), or `null` during [prerendering](#behavior-during-prerendering).
|
||||
|
||||
- Each property in the object is an active dynamic segment.
|
||||
- The property name is the segment's name, and the property value is what the segment is filled in with.
|
||||
- The property value will either be a `string` or array of `string`s depending on the [type of dynamic segment](/docs/pages/building-your-application/routing/dynamic-routes).
|
||||
- If the route contains no dynamic parameters, `useParams` returns an empty object.
|
||||
|
||||
For example:
|
||||
|
||||
| Route | URL | `useParams()` |
|
||||
| ---------------------------- | ----------- | ------------------------- |
|
||||
| `pages/shop/page.js` | `/shop` | `{}` |
|
||||
| `pages/shop/[slug].js` | `/shop/1` | `{ slug: '1' }` |
|
||||
| `pages/shop/[tag]/[item].js` | `/shop/1/2` | `{ tag: '1', item: '2' }` |
|
||||
| `pages/shop/[...slug].js` | `/shop/1/2` | `{ slug: ['1', '2'] }` |
|
||||
|
||||
> **Good to know**: `useParams` is a [React Hook](https://react.dev/learn#using-hooks) and cannot be used with classes.
|
||||
|
||||
## Behavior
|
||||
|
||||
### Behavior during prerendering
|
||||
|
||||
For pages that are [statically optimized](/docs/pages/building-your-application/rendering/automatic-static-optimization), `useParams` will return `null` on the initial render. After hydration, the value will be updated to the actual params once the router is ready.
|
||||
|
||||
This is because params cannot be known during static generation for dynamic routes.
|
||||
|
||||
```tsx filename="pages/shop/[slug].tsx" switcher
|
||||
import { useParams } from 'next/navigation'
|
||||
|
||||
export default function ShopPage() {
|
||||
const params = useParams<{ slug: string }>()
|
||||
|
||||
if (!params) {
|
||||
// Return a fallback UI while params are loading
|
||||
// This prevents hydration mismatches
|
||||
return <ShopPageSkeleton />
|
||||
}
|
||||
|
||||
return <>Shop: {params.slug}</>
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/shop/[slug].js" switcher
|
||||
import { useParams } from 'next/navigation'
|
||||
|
||||
export default function ShopPage() {
|
||||
const params = useParams()
|
||||
|
||||
if (!params) {
|
||||
// Return a fallback UI while params are loading
|
||||
// This prevents hydration mismatches
|
||||
return <ShopPageSkeleton />
|
||||
}
|
||||
|
||||
return <>Shop: {params.slug}</>
|
||||
}
|
||||
```
|
||||
|
||||
### Using with `getServerSideProps`
|
||||
|
||||
When using [`getServerSideProps`](/docs/pages/building-your-application/data-fetching/get-server-side-props), the page is server-rendered on each request and `useParams` will return the actual params immediately:
|
||||
|
||||
```tsx filename="pages/shop/[slug].tsx" switcher
|
||||
import { useParams } from 'next/navigation'
|
||||
|
||||
export default function ShopPage() {
|
||||
const params = useParams<{ slug: string }>()
|
||||
|
||||
// With getServerSideProps, this fallback is never rendered because
|
||||
// params is always available on the server. However, keeping
|
||||
// the fallback allows this component to be reused on other pages
|
||||
// that may not use getServerSideProps.
|
||||
if (!params) {
|
||||
return null
|
||||
}
|
||||
|
||||
return <>Shop: {params.slug}</>
|
||||
}
|
||||
|
||||
export async function getServerSideProps() {
|
||||
return { props: {} }
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/shop/[slug].js" switcher
|
||||
import { useParams } from 'next/navigation'
|
||||
|
||||
export default function ShopPage() {
|
||||
const params = useParams()
|
||||
|
||||
// With getServerSideProps, this fallback is never rendered because
|
||||
// params is always available on the server. However, keeping
|
||||
// the fallback allows this component to be reused on other pages
|
||||
// that may not use getServerSideProps.
|
||||
if (!params) {
|
||||
return null
|
||||
}
|
||||
|
||||
return <>Shop: {params.slug}</>
|
||||
}
|
||||
|
||||
export async function getServerSideProps() {
|
||||
return { props: {} }
|
||||
}
|
||||
```
|
||||
|
||||
### Comparison with `router.query`
|
||||
|
||||
`useParams` only returns the dynamic route parameters, whereas [`router.query`](/docs/pages/api-reference/functions/use-router#router-object) from `useRouter` includes both dynamic parameters and query string parameters.
|
||||
|
||||
```tsx filename="pages/shop/[slug].tsx" switcher
|
||||
import { useRouter } from 'next/router'
|
||||
import { useParams } from 'next/navigation'
|
||||
|
||||
export default function ShopPage() {
|
||||
const router = useRouter()
|
||||
const params = useParams()
|
||||
|
||||
// URL -> /shop/shoes?color=red
|
||||
|
||||
// router.query -> { slug: 'shoes', color: 'red' }
|
||||
// params -> { slug: 'shoes' }
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/shop/[slug].js" switcher
|
||||
import { useRouter } from 'next/router'
|
||||
import { useParams } from 'next/navigation'
|
||||
|
||||
export default function ShopPage() {
|
||||
const router = useRouter()
|
||||
const params = useParams()
|
||||
|
||||
// URL -> /shop/shoes?color=red
|
||||
|
||||
// router.query -> { slug: 'shoes', color: 'red' }
|
||||
// params -> { slug: 'shoes' }
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Sharing components with App Router
|
||||
|
||||
`useParams` from `next/navigation` works in both the Pages Router and App Router. This allows you to create shared components that work in either context:
|
||||
|
||||
```tsx filename="components/breadcrumb.tsx" switcher
|
||||
import { useParams } from 'next/navigation'
|
||||
|
||||
// This component works in both pages/ and app/
|
||||
export function Breadcrumb() {
|
||||
const params = useParams<{ slug: string }>()
|
||||
|
||||
if (!params) {
|
||||
// Fallback for Pages Router during prerendering
|
||||
return <nav>Home / ...</nav>
|
||||
}
|
||||
|
||||
return <nav>Home / {params.slug}</nav>
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="components/breadcrumb.js" switcher
|
||||
import { useParams } from 'next/navigation'
|
||||
|
||||
// This component works in both pages/ and app/
|
||||
export function Breadcrumb() {
|
||||
const params = useParams()
|
||||
|
||||
if (!params) {
|
||||
// Fallback for Pages Router during prerendering
|
||||
return <nav>Home / ...</nav>
|
||||
}
|
||||
|
||||
return <nav>Home / {params.slug}</nav>
|
||||
}
|
||||
```
|
||||
|
||||
> **Good to know**: When using this component in the App Router, `useParams` never returns `null`, so the fallback branch will not be rendered.
|
||||
|
||||
## Version History
|
||||
|
||||
| Version | Changes |
|
||||
| --------- | ----------------------- |
|
||||
| `v13.3.0` | `useParams` introduced. |
|
||||
7
node_modules/next/dist/docs/02-pages/04-api-reference/03-functions/use-report-web-vitals.md
generated
vendored
Normal file
7
node_modules/next/dist/docs/02-pages/04-api-reference/03-functions/use-report-web-vitals.md
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: useReportWebVitals
|
||||
description: useReportWebVitals
|
||||
source: app/api-reference/functions/use-report-web-vitals
|
||||
---
|
||||
|
||||
{/* DO NOT EDIT. The content of this doc is generated from the source above. To edit the content of this page, navigate to the source page in your editor. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
||||
588
node_modules/next/dist/docs/02-pages/04-api-reference/03-functions/use-router.md
generated
vendored
Normal file
588
node_modules/next/dist/docs/02-pages/04-api-reference/03-functions/use-router.md
generated
vendored
Normal file
@@ -0,0 +1,588 @@
|
||||
---
|
||||
title: useRouter
|
||||
description: Learn more about the API of the Next.js Router, and access the router instance in your page with the useRouter hook.
|
||||
---
|
||||
|
||||
If you want to access the [`router` object](#router-object) inside any function component in your app, you can use the `useRouter` hook, take a look at the following example:
|
||||
|
||||
```jsx
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
function ActiveLink({ children, href }) {
|
||||
const router = useRouter()
|
||||
const style = {
|
||||
marginRight: 10,
|
||||
color: router.asPath === href ? 'red' : 'black',
|
||||
}
|
||||
|
||||
const handleClick = (e) => {
|
||||
e.preventDefault()
|
||||
router.push(href)
|
||||
}
|
||||
|
||||
return (
|
||||
<a href={href} onClick={handleClick} style={style}>
|
||||
{children}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
||||
export default ActiveLink
|
||||
```
|
||||
|
||||
> `useRouter` is a [React Hook](https://react.dev/learn#using-hooks), meaning it cannot be used with classes. You can either use [withRouter](#withrouter) or wrap your class in a function component.
|
||||
|
||||
## `router` object
|
||||
|
||||
The following is the definition of the `router` object returned by both [`useRouter`](#top) and [`withRouter`](#withrouter):
|
||||
|
||||
- `pathname`: `String` - The path for current route file that comes after `/pages`. Therefore, `basePath`, `locale` and trailing slash (`trailingSlash: true`) are not included.
|
||||
- `query`: `Object` - The query string parsed to an object, including [dynamic route](/docs/pages/building-your-application/routing/dynamic-routes) parameters. It will be an empty object during prerendering if the page doesn't use [Server-side Rendering](/docs/pages/building-your-application/data-fetching/get-server-side-props). Defaults to `{}`
|
||||
- `asPath`: `String` - The path as shown in the browser including the search params and respecting the `trailingSlash` configuration. `basePath` and `locale` are not included.
|
||||
- `isFallback`: `boolean` - Whether the current page is in [fallback mode](/docs/pages/api-reference/functions/get-static-paths#fallback-true).
|
||||
- `basePath`: `String` - The active [basePath](/docs/app/api-reference/config/next-config-js/basePath) (if enabled).
|
||||
- `locale`: `String` - The active locale (if enabled).
|
||||
- `locales`: `String[]` - All supported locales (if enabled).
|
||||
- `defaultLocale`: `String` - The current default locale (if enabled).
|
||||
- `domainLocales`: `Array<{domain, defaultLocale, locales}>` - Any configured domain locales.
|
||||
- `isReady`: `boolean` - Whether the router fields are updated client-side and ready for use. Should only be used inside of `useEffect` methods and not for conditionally rendering on the server. See related docs for use case with [automatically statically optimized pages](/docs/pages/building-your-application/rendering/automatic-static-optimization)
|
||||
- `isPreview`: `boolean` - Whether the application is currently in [preview mode](/docs/pages/guides/preview-mode).
|
||||
|
||||
> Using the `asPath` field may lead to a mismatch between client and server if the page is rendered using server-side rendering or [automatic static optimization](/docs/pages/building-your-application/rendering/automatic-static-optimization). Avoid using `asPath` until the `isReady` field is `true`.
|
||||
|
||||
The following methods are included inside `router`:
|
||||
|
||||
### router.push
|
||||
|
||||
Handles client-side transitions, this method is useful for cases where [`next/link`](/docs/pages/api-reference/components/link) is not enough.
|
||||
|
||||
```js
|
||||
router.push(url, as, options)
|
||||
```
|
||||
|
||||
- `url`: `UrlObject | String` - The URL to navigate to (see [Node.JS URL module documentation](https://nodejs.org/api/url.html#legacy-urlobject) for `UrlObject` properties).
|
||||
- `as`: `UrlObject | String` - Optional decorator for the path that will be shown in the browser URL bar. Before Next.js 9.5.3 this was used for dynamic routes.
|
||||
- `options` - Optional object with the following configuration options:
|
||||
- `scroll` - Optional boolean, controls scrolling to the top of the page after navigation. Defaults to `true`
|
||||
- [`shallow`](/docs/pages/building-your-application/routing/linking-and-navigating#shallow-routing): Update the path of the current page without rerunning [`getStaticProps`](/docs/pages/building-your-application/data-fetching/get-static-props), [`getServerSideProps`](/docs/pages/building-your-application/data-fetching/get-server-side-props) or [`getInitialProps`](/docs/pages/api-reference/functions/get-initial-props). Defaults to `false`
|
||||
- `locale` - Optional string, indicates locale of the new page
|
||||
|
||||
> You don't need to use `router.push` for external URLs. [window.location](https://developer.mozilla.org/docs/Web/API/Window/location) is better suited for those cases.
|
||||
|
||||
Navigating to `pages/about.js`, which is a predefined route:
|
||||
|
||||
```jsx
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
export default function Page() {
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<button type="button" onClick={() => router.push('/about')}>
|
||||
Click me
|
||||
</button>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
Navigating `pages/post/[pid].js`, which is a dynamic route:
|
||||
|
||||
```jsx
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
export default function Page() {
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<button type="button" onClick={() => router.push('/post/abc')}>
|
||||
Click me
|
||||
</button>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
Redirecting the user to `pages/login.js`, useful for pages behind [authentication](/docs/pages/guides/authentication):
|
||||
|
||||
```jsx
|
||||
import { useEffect } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
// Here you would fetch and return the user
|
||||
const useUser = () => ({ user: null, loading: false })
|
||||
|
||||
export default function Page() {
|
||||
const { user, loading } = useUser()
|
||||
const router = useRouter()
|
||||
|
||||
useEffect(() => {
|
||||
if (!(user || loading)) {
|
||||
router.push('/login')
|
||||
}
|
||||
}, [user, loading])
|
||||
|
||||
return <p>Redirecting...</p>
|
||||
}
|
||||
```
|
||||
|
||||
#### Resetting state after navigation
|
||||
|
||||
When navigating to the same page in Next.js, the page's state **will not** be reset by default as React does not unmount unless the parent component has changed.
|
||||
|
||||
```jsx filename="pages/[slug].js"
|
||||
import Link from 'next/link'
|
||||
import { useState } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter()
|
||||
const [count, setCount] = useState(0)
|
||||
return (
|
||||
<div>
|
||||
<h1>Page: {router.query.slug}</h1>
|
||||
<p>Count: {count}</p>
|
||||
<button onClick={() => setCount(count + 1)}>Increase count</button>
|
||||
<Link href="/one">one</Link> <Link href="/two">two</Link>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
In the above example, navigating between `/one` and `/two` **will not** reset the count . The `useState` is maintained between renders because the top-level React component, `Page`, is the same.
|
||||
|
||||
If you do not want this behavior, you have a couple of options:
|
||||
|
||||
- Manually ensure each state is updated using `useEffect`. In the above example, that could look like:
|
||||
|
||||
```jsx
|
||||
useEffect(() => {
|
||||
setCount(0)
|
||||
}, [router.query.slug])
|
||||
```
|
||||
|
||||
- Use a React `key` to [tell React to remount the component](https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). To do this for all pages, you can use a custom app:
|
||||
|
||||
```jsx filename="pages/_app.js"
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
export default function MyApp({ Component, pageProps }) {
|
||||
const router = useRouter()
|
||||
return <Component key={router.asPath} {...pageProps} />
|
||||
}
|
||||
```
|
||||
|
||||
#### With URL object
|
||||
|
||||
You can use a URL object in the same way you can use it for [`next/link`](/docs/pages/api-reference/components/link#passing-a-url-object). Works for both the `url` and `as` parameters:
|
||||
|
||||
```jsx
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
export default function ReadMore({ post }) {
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
router.push({
|
||||
pathname: '/post/[pid]',
|
||||
query: { pid: post.id },
|
||||
})
|
||||
}}
|
||||
>
|
||||
Click here to read more
|
||||
</button>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### router.replace
|
||||
|
||||
Similar to the `replace` prop in [`next/link`](/docs/pages/api-reference/components/link), `router.replace` will prevent adding a new URL entry into the `history` stack.
|
||||
|
||||
```js
|
||||
router.replace(url, as, options)
|
||||
```
|
||||
|
||||
- The API for `router.replace` is exactly the same as the API for [`router.push`](#routerpush).
|
||||
|
||||
Take a look at the following example:
|
||||
|
||||
```jsx
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
export default function Page() {
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<button type="button" onClick={() => router.replace('/home')}>
|
||||
Click me
|
||||
</button>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### router.prefetch
|
||||
|
||||
Prefetch pages for faster client-side transitions. This method is only useful for navigations without [`next/link`](/docs/pages/api-reference/components/link), as `next/link` takes care of prefetching pages automatically.
|
||||
|
||||
> This is a production only feature. Next.js doesn't prefetch pages in development.
|
||||
|
||||
```js
|
||||
router.prefetch(url, as, options)
|
||||
```
|
||||
|
||||
- `url` - The URL to prefetch, including explicit routes (e.g. `/dashboard`) and dynamic routes (e.g. `/product/[id]`)
|
||||
- `as` - Optional decorator for `url`. Before Next.js 9.5.3 this was used to prefetch dynamic routes.
|
||||
- `options` - Optional object with the following allowed fields:
|
||||
- `locale` - allows providing a different locale from the active one. If `false`, `url` has to include the locale as the active locale won't be used.
|
||||
|
||||
Let's say you have a login page, and after a login, you redirect the user to the dashboard. For that case, we can prefetch the dashboard to make a faster transition, like in the following example:
|
||||
|
||||
```jsx
|
||||
import { useCallback, useEffect } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
export default function Login() {
|
||||
const router = useRouter()
|
||||
const handleSubmit = useCallback((e) => {
|
||||
e.preventDefault()
|
||||
|
||||
fetch('/api/login', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
/* Form data */
|
||||
}),
|
||||
}).then((res) => {
|
||||
// Do a fast client-side transition to the already prefetched dashboard page
|
||||
if (res.ok) router.push('/dashboard')
|
||||
})
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
// Prefetch the dashboard page
|
||||
router.prefetch('/dashboard')
|
||||
}, [router])
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit}>
|
||||
{/* Form fields */}
|
||||
<button type="submit">Login</button>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### router.beforePopState
|
||||
|
||||
In some cases (for example, if using a [Custom Server](/docs/pages/guides/custom-server)), you may wish to listen to [popstate](https://developer.mozilla.org/docs/Web/API/Window/popstate_event) and do something before the router acts on it.
|
||||
|
||||
```js
|
||||
router.beforePopState(cb)
|
||||
```
|
||||
|
||||
- `cb` - The function to run on incoming `popstate` events. The function receives the state of the event as an object with the following props:
|
||||
- `url`: `String` - the route for the new state. This is usually the name of a `page`
|
||||
- `as`: `String` - the url that will be shown in the browser
|
||||
- `options`: `Object` - Additional options sent by [router.push](#routerpush)
|
||||
|
||||
If `cb` returns `false`, the Next.js router will not handle `popstate`, and you'll be responsible for handling it in that case. See [Disabling file-system routing](/docs/pages/guides/custom-server#disabling-file-system-routing).
|
||||
|
||||
You could use `beforePopState` to manipulate the request, or force a SSR refresh, as in the following example:
|
||||
|
||||
```jsx
|
||||
import { useEffect } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
export default function Page() {
|
||||
const router = useRouter()
|
||||
|
||||
useEffect(() => {
|
||||
router.beforePopState(({ url, as, options }) => {
|
||||
// I only want to allow these two routes!
|
||||
if (as !== '/' && as !== '/other') {
|
||||
// Have SSR render bad routes as a 404.
|
||||
window.location.href = as
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
}, [router])
|
||||
|
||||
return <p>Welcome to the page</p>
|
||||
}
|
||||
```
|
||||
|
||||
### router.back
|
||||
|
||||
Navigate back in history. Equivalent to clicking the browser’s back button. It executes `window.history.back()`.
|
||||
|
||||
```jsx
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
export default function Page() {
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<button type="button" onClick={() => router.back()}>
|
||||
Click here to go back
|
||||
</button>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### router.reload
|
||||
|
||||
Reload the current URL. Equivalent to clicking the browser’s refresh button. It executes `window.location.reload()`.
|
||||
|
||||
```jsx
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
export default function Page() {
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<button type="button" onClick={() => router.reload()}>
|
||||
Click here to reload
|
||||
</button>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### router.events
|
||||
|
||||
You can listen to different events happening inside the Next.js Router. Here's a list of supported events:
|
||||
|
||||
- `routeChangeStart(url, { shallow })` - Fires when a route starts to change
|
||||
- `routeChangeComplete(url, { shallow })` - Fires when a route changed completely
|
||||
- `routeChangeError(err, url, { shallow })` - Fires when there's an error when changing routes, or a route load is cancelled
|
||||
- `err.cancelled` - Indicates if the navigation was cancelled
|
||||
- `beforeHistoryChange(url, { shallow })` - Fires before changing the browser's history
|
||||
- `hashChangeStart(url, { shallow })` - Fires when the hash will change but not the page
|
||||
- `hashChangeComplete(url, { shallow })` - Fires when the hash has changed but not the page
|
||||
|
||||
> **Good to know**: Here `url` is the URL shown in the browser, including the [`basePath`](/docs/app/api-reference/config/next-config-js/basePath).
|
||||
|
||||
For example, to listen to the router event `routeChangeStart`, open or create `pages/_app.js` and subscribe to the event, like so:
|
||||
|
||||
```jsx
|
||||
import { useEffect } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
export default function MyApp({ Component, pageProps }) {
|
||||
const router = useRouter()
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url, { shallow }) => {
|
||||
console.log(
|
||||
`App is changing to ${url} ${
|
||||
shallow ? 'with' : 'without'
|
||||
} shallow routing`
|
||||
)
|
||||
}
|
||||
|
||||
router.events.on('routeChangeStart', handleRouteChange)
|
||||
|
||||
// If the component is unmounted, unsubscribe
|
||||
// from the event with the `off` method:
|
||||
return () => {
|
||||
router.events.off('routeChangeStart', handleRouteChange)
|
||||
}
|
||||
}, [router])
|
||||
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
```
|
||||
|
||||
> We use a [Custom App](/docs/pages/building-your-application/routing/custom-app) (`pages/_app.js`) for this example to subscribe to the event because it's not unmounted on page navigations, but you can subscribe to router events on any component in your application.
|
||||
|
||||
Router events should be registered when a component mounts ([useEffect](https://react.dev/reference/react/useEffect) or [componentDidMount](https://react.dev/reference/react/Component#componentdidmount) / [componentWillUnmount](https://react.dev/reference/react/Component#componentwillunmount)) or imperatively when an event happens.
|
||||
|
||||
If a route load is cancelled (for example, by clicking two links rapidly in succession), `routeChangeError` will fire. And the passed `err` will contain a `cancelled` property set to `true`, as in the following example:
|
||||
|
||||
```jsx
|
||||
import { useEffect } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
export default function MyApp({ Component, pageProps }) {
|
||||
const router = useRouter()
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChangeError = (err, url) => {
|
||||
if (err.cancelled) {
|
||||
console.log(`Route to ${url} was cancelled!`)
|
||||
}
|
||||
}
|
||||
|
||||
router.events.on('routeChangeError', handleRouteChangeError)
|
||||
|
||||
// If the component is unmounted, unsubscribe
|
||||
// from the event with the `off` method:
|
||||
return () => {
|
||||
router.events.off('routeChangeError', handleRouteChangeError)
|
||||
}
|
||||
}, [router])
|
||||
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
```
|
||||
|
||||
## The `next/compat/router` export
|
||||
|
||||
This is the same `useRouter` hook, but can be used in both `app` and `pages` directories.
|
||||
|
||||
It differs from `next/router` in that it does not throw an error when the pages router is not mounted, and instead has a return type of `NextRouter | null`.
|
||||
This allows developers to convert components to support running in both `app` and `pages` as they transition to the `app` router.
|
||||
|
||||
A component that previously looked like this:
|
||||
|
||||
```jsx
|
||||
import { useRouter } from 'next/router'
|
||||
const MyComponent = () => {
|
||||
const { isReady, query } = useRouter()
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Will error when converted over to `next/compat/router`, as `null` cannot be destructured. Instead, developers will be able to take advantage of new hooks:
|
||||
|
||||
```jsx
|
||||
import { useEffect } from 'react'
|
||||
import { useRouter } from 'next/compat/router'
|
||||
import { useSearchParams } from 'next/navigation'
|
||||
const MyComponent = () => {
|
||||
const router = useRouter() // may be null or a NextRouter instance
|
||||
const searchParams = useSearchParams()
|
||||
useEffect(() => {
|
||||
if (router && !router.isReady) {
|
||||
return
|
||||
}
|
||||
// In `app/`, searchParams will be ready immediately with the values, in
|
||||
// `pages/` it will be available after the router is ready.
|
||||
const search = searchParams.get('search')
|
||||
// ...
|
||||
}, [router, searchParams])
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
This component will now work in both `pages` and `app` directories. When the component is no longer used in `pages`, you can remove the references to the compat router:
|
||||
|
||||
```jsx
|
||||
import { useSearchParams } from 'next/navigation'
|
||||
const MyComponent = () => {
|
||||
const searchParams = useSearchParams()
|
||||
// As this component is only used in `app/`, the compat router can be removed.
|
||||
const search = searchParams.get('search')
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Using `useRouter` outside of Next.js context in pages
|
||||
|
||||
Another specific use case is when rendering components outside of a Next.js application context, such as inside `getServerSideProps` on the `pages` directory. In this case, the compat router can be used to avoid errors:
|
||||
|
||||
```jsx
|
||||
import { renderToString } from 'react-dom/server'
|
||||
import { useRouter } from 'next/compat/router'
|
||||
const MyComponent = () => {
|
||||
const router = useRouter() // may be null or a NextRouter instance
|
||||
// ...
|
||||
}
|
||||
export async function getServerSideProps() {
|
||||
const renderedComponent = renderToString(<MyComponent />)
|
||||
return {
|
||||
props: {
|
||||
renderedComponent,
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Potential ESLint errors
|
||||
|
||||
Certain methods accessible on the `router` object return a Promise. If you have the ESLint rule, [no-floating-promises](https://typescript-eslint.io/rules/no-floating-promises) enabled, consider disabling it either globally, or for the affected line.
|
||||
|
||||
If your application needs this rule, you should either `void` the promise – or use an `async` function, `await` the Promise, then void the function call. **This is not applicable when the method is called from inside an `onClick` handler**.
|
||||
|
||||
The affected methods are:
|
||||
|
||||
- `router.push`
|
||||
- `router.replace`
|
||||
- `router.prefetch`
|
||||
|
||||
### Potential solutions
|
||||
|
||||
```jsx
|
||||
import { useEffect } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
// Here you would fetch and return the user
|
||||
const useUser = () => ({ user: null, loading: false })
|
||||
|
||||
export default function Page() {
|
||||
const { user, loading } = useUser()
|
||||
const router = useRouter()
|
||||
|
||||
useEffect(() => {
|
||||
// disable the linting on the next line - This is the cleanest solution
|
||||
// eslint-disable-next-line no-floating-promises
|
||||
router.push('/login')
|
||||
|
||||
// void the Promise returned by router.push
|
||||
if (!(user || loading)) {
|
||||
void router.push('/login')
|
||||
}
|
||||
// or use an async function, await the Promise, then void the function call
|
||||
async function handleRouteChange() {
|
||||
if (!(user || loading)) {
|
||||
await router.push('/login')
|
||||
}
|
||||
}
|
||||
void handleRouteChange()
|
||||
}, [user, loading])
|
||||
|
||||
return <p>Redirecting...</p>
|
||||
}
|
||||
```
|
||||
|
||||
## withRouter
|
||||
|
||||
If [`useRouter`](#router-object) is not the best fit for you, `withRouter` can also add the same [`router` object](#router-object) to any component.
|
||||
|
||||
### Usage
|
||||
|
||||
```jsx
|
||||
import { withRouter } from 'next/router'
|
||||
|
||||
function Page({ router }) {
|
||||
return <p>{router.pathname}</p>
|
||||
}
|
||||
|
||||
export default withRouter(Page)
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
|
||||
To use class components with `withRouter`, the component needs to accept a router prop:
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import { withRouter, NextRouter } from 'next/router'
|
||||
|
||||
interface WithRouterProps {
|
||||
router: NextRouter
|
||||
}
|
||||
|
||||
interface MyComponentProps extends WithRouterProps {}
|
||||
|
||||
class MyComponent extends React.Component<MyComponentProps> {
|
||||
render() {
|
||||
return <p>{this.props.router.pathname}</p>
|
||||
}
|
||||
}
|
||||
|
||||
export default withRouter(MyComponent)
|
||||
```
|
||||
318
node_modules/next/dist/docs/02-pages/04-api-reference/03-functions/use-search-params.md
generated
vendored
Normal file
318
node_modules/next/dist/docs/02-pages/04-api-reference/03-functions/use-search-params.md
generated
vendored
Normal file
@@ -0,0 +1,318 @@
|
||||
---
|
||||
title: useSearchParams
|
||||
description: API Reference for the useSearchParams hook in the Pages Router.
|
||||
---
|
||||
|
||||
`useSearchParams` is a hook that lets you read the current URL's **query string**.
|
||||
|
||||
`useSearchParams` returns a **read-only** version of the [`URLSearchParams`](https://developer.mozilla.org/docs/Web/API/URLSearchParams) interface.
|
||||
|
||||
```tsx filename="pages/dashboard.tsx" switcher
|
||||
import { useSearchParams } from 'next/navigation'
|
||||
|
||||
export default function Dashboard() {
|
||||
const searchParams = useSearchParams()
|
||||
|
||||
if (!searchParams) {
|
||||
// Render fallback UI while search params are not yet available
|
||||
return null
|
||||
}
|
||||
|
||||
const search = searchParams.get('search')
|
||||
|
||||
// URL -> `/dashboard?search=my-project`
|
||||
// `search` -> 'my-project'
|
||||
return <>Search: {search}</>
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/dashboard.js" switcher
|
||||
import { useSearchParams } from 'next/navigation'
|
||||
|
||||
export default function Dashboard() {
|
||||
const searchParams = useSearchParams()
|
||||
|
||||
if (!searchParams) {
|
||||
// Render fallback UI while search params are not yet available
|
||||
return null
|
||||
}
|
||||
|
||||
const search = searchParams.get('search')
|
||||
|
||||
// URL -> `/dashboard?search=my-project`
|
||||
// `search` -> 'my-project'
|
||||
return <>Search: {search}</>
|
||||
}
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
```tsx
|
||||
const searchParams = useSearchParams()
|
||||
```
|
||||
|
||||
`useSearchParams` does not take any parameters.
|
||||
|
||||
## Returns
|
||||
|
||||
`useSearchParams` returns a **read-only** version of the [`URLSearchParams`](https://developer.mozilla.org/docs/Web/API/URLSearchParams) interface, or `null` during [prerendering](#behavior-during-prerendering).
|
||||
|
||||
The interface includes utility methods for reading the URL's query string:
|
||||
|
||||
- [`URLSearchParams.get()`](https://developer.mozilla.org/docs/Web/API/URLSearchParams/get): Returns the first value associated with the search parameter. For example:
|
||||
|
||||
| URL | `searchParams.get("a")` |
|
||||
| -------------------- | --------------------------------------------------------------------------------------------------------------- |
|
||||
| `/dashboard?a=1` | `'1'` |
|
||||
| `/dashboard?a=` | `''` |
|
||||
| `/dashboard?b=3` | `null` |
|
||||
| `/dashboard?a=1&a=2` | `'1'` _- use [`getAll()`](https://developer.mozilla.org/docs/Web/API/URLSearchParams/getAll) to get all values_ |
|
||||
|
||||
- [`URLSearchParams.has()`](https://developer.mozilla.org/docs/Web/API/URLSearchParams/has): Returns a boolean value indicating if the given parameter exists. For example:
|
||||
|
||||
| URL | `searchParams.has("a")` |
|
||||
| ---------------- | ----------------------- |
|
||||
| `/dashboard?a=1` | `true` |
|
||||
| `/dashboard?b=3` | `false` |
|
||||
|
||||
- Learn more about other **read-only** methods of [`URLSearchParams`](https://developer.mozilla.org/docs/Web/API/URLSearchParams), including the [`getAll()`](https://developer.mozilla.org/docs/Web/API/URLSearchParams/getAll), [`keys()`](https://developer.mozilla.org/docs/Web/API/URLSearchParams/keys), [`values()`](https://developer.mozilla.org/docs/Web/API/URLSearchParams/values), [`entries()`](https://developer.mozilla.org/docs/Web/API/URLSearchParams/entries), [`forEach()`](https://developer.mozilla.org/docs/Web/API/URLSearchParams/forEach), and [`toString()`](https://developer.mozilla.org/docs/Web/API/URLSearchParams/toString).
|
||||
|
||||
> **Good to know**: `useSearchParams` is a [React Hook](https://react.dev/learn#using-hooks) and cannot be used with classes.
|
||||
|
||||
## Behavior
|
||||
|
||||
### Behavior during prerendering
|
||||
|
||||
For pages that are [statically optimized](/docs/pages/building-your-application/rendering/automatic-static-optimization) (not using `getServerSideProps`), `useSearchParams` will return `null` during prerendering. After hydration, the value will be updated to the actual search params.
|
||||
|
||||
This is because search params cannot be known during static generation as they depend on the request.
|
||||
|
||||
```tsx filename="pages/dashboard.tsx" switcher
|
||||
import { useSearchParams } from 'next/navigation'
|
||||
|
||||
export default function Dashboard() {
|
||||
const searchParams = useSearchParams()
|
||||
|
||||
if (!searchParams) {
|
||||
// Return a fallback UI while search params are loading
|
||||
// This prevents hydration mismatches
|
||||
return <DashboardSkeleton />
|
||||
}
|
||||
|
||||
const search = searchParams.get('search')
|
||||
|
||||
return <>Search: {search}</>
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/dashboard.js" switcher
|
||||
import { useSearchParams } from 'next/navigation'
|
||||
|
||||
export default function Dashboard() {
|
||||
const searchParams = useSearchParams()
|
||||
|
||||
if (!searchParams) {
|
||||
// Return a fallback UI while search params are loading
|
||||
// This prevents hydration mismatches
|
||||
return <DashboardSkeleton />
|
||||
}
|
||||
|
||||
const search = searchParams.get('search')
|
||||
|
||||
return <>Search: {search}</>
|
||||
}
|
||||
```
|
||||
|
||||
### Using with `getServerSideProps`
|
||||
|
||||
When using [`getServerSideProps`](/docs/pages/building-your-application/data-fetching/get-server-side-props), the page is server-rendered on each request and `useSearchParams` will return the actual search params immediately:
|
||||
|
||||
```tsx filename="pages/dashboard.tsx" switcher
|
||||
import { useSearchParams } from 'next/navigation'
|
||||
|
||||
export default function Dashboard() {
|
||||
const searchParams = useSearchParams()
|
||||
|
||||
// With getServerSideProps, this fallback is never rendered because
|
||||
// searchParams is always available on the server. However, keeping
|
||||
// the fallback allows this component to be reused on other pages
|
||||
// that may not use getServerSideProps.
|
||||
if (!searchParams) {
|
||||
return null
|
||||
}
|
||||
|
||||
const search = searchParams.get('search')
|
||||
|
||||
return <>Search: {search}</>
|
||||
}
|
||||
|
||||
export async function getServerSideProps() {
|
||||
return { props: {} }
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/dashboard.js" switcher
|
||||
import { useSearchParams } from 'next/navigation'
|
||||
|
||||
export default function Dashboard() {
|
||||
const searchParams = useSearchParams()
|
||||
|
||||
// With getServerSideProps, this fallback is never rendered because
|
||||
// searchParams is always available on the server. However, keeping
|
||||
// the fallback allows this component to be reused on other pages
|
||||
// that may not use getServerSideProps.
|
||||
if (!searchParams) {
|
||||
return null
|
||||
}
|
||||
|
||||
const search = searchParams.get('search')
|
||||
|
||||
return <>Search: {search}</>
|
||||
}
|
||||
|
||||
export async function getServerSideProps() {
|
||||
return { props: {} }
|
||||
}
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Updating search params
|
||||
|
||||
You can use the [`useRouter`](/docs/pages/api-reference/functions/use-router) hook to update search params:
|
||||
|
||||
```tsx filename="pages/dashboard.tsx" switcher
|
||||
import { useRouter } from 'next/router'
|
||||
import { useSearchParams } from 'next/navigation'
|
||||
import { useCallback } from 'react'
|
||||
|
||||
export default function Dashboard() {
|
||||
const router = useRouter()
|
||||
const searchParams = useSearchParams()
|
||||
|
||||
const createQueryString = useCallback(
|
||||
(name: string, value: string) => {
|
||||
const params = new URLSearchParams(searchParams?.toString())
|
||||
params.set(name, value)
|
||||
return params.toString()
|
||||
},
|
||||
[searchParams]
|
||||
)
|
||||
|
||||
if (!searchParams) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<p>Sort By</p>
|
||||
<button
|
||||
onClick={() => {
|
||||
router.push(router.pathname + '?' + createQueryString('sort', 'asc'))
|
||||
}}
|
||||
>
|
||||
ASC
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
router.push(router.pathname + '?' + createQueryString('sort', 'desc'))
|
||||
}}
|
||||
>
|
||||
DESC
|
||||
</button>
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="pages/dashboard.js" switcher
|
||||
import { useRouter } from 'next/router'
|
||||
import { useSearchParams } from 'next/navigation'
|
||||
import { useCallback } from 'react'
|
||||
|
||||
export default function Dashboard() {
|
||||
const router = useRouter()
|
||||
const searchParams = useSearchParams()
|
||||
|
||||
const createQueryString = useCallback(
|
||||
(name, value) => {
|
||||
const params = new URLSearchParams(searchParams?.toString())
|
||||
params.set(name, value)
|
||||
return params.toString()
|
||||
},
|
||||
[searchParams]
|
||||
)
|
||||
|
||||
if (!searchParams) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<p>Sort By</p>
|
||||
<button
|
||||
onClick={() => {
|
||||
router.push(router.pathname + '?' + createQueryString('sort', 'asc'))
|
||||
}}
|
||||
>
|
||||
ASC
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
router.push(router.pathname + '?' + createQueryString('sort', 'desc'))
|
||||
}}
|
||||
>
|
||||
DESC
|
||||
</button>
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Sharing components with App Router
|
||||
|
||||
`useSearchParams` from `next/navigation` works in both the Pages Router and App Router. This allows you to create shared components that work in either context:
|
||||
|
||||
```tsx filename="components/search-bar.tsx" switcher
|
||||
import { useSearchParams } from 'next/navigation'
|
||||
|
||||
// This component works in both pages/ and app/
|
||||
export function SearchBar() {
|
||||
const searchParams = useSearchParams()
|
||||
|
||||
if (!searchParams) {
|
||||
// Fallback for Pages Router during prerendering
|
||||
return <input defaultValue="" placeholder="Search..." />
|
||||
}
|
||||
|
||||
const search = searchParams.get('search') ?? ''
|
||||
|
||||
return <input defaultValue={search} placeholder="Search..." />
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="components/search-bar.js" switcher
|
||||
import { useSearchParams } from 'next/navigation'
|
||||
|
||||
// This component works in both pages/ and app/
|
||||
export function SearchBar() {
|
||||
const searchParams = useSearchParams()
|
||||
|
||||
if (!searchParams) {
|
||||
// Fallback for Pages Router during prerendering
|
||||
return <input defaultValue="" placeholder="Search..." />
|
||||
}
|
||||
|
||||
const search = searchParams.get('search') ?? ''
|
||||
|
||||
return <input defaultValue={search} placeholder="Search..." />
|
||||
}
|
||||
```
|
||||
|
||||
> **Good to know**: When using this component in the App Router, wrap it in a `<Suspense>` boundary for [prerendering](/docs/app/api-reference/functions/use-search-params#prerendering) support.
|
||||
|
||||
## Version History
|
||||
|
||||
| Version | Changes |
|
||||
| --------- | ----------------------------- |
|
||||
| `v13.0.0` | `useSearchParams` introduced. |
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user