.
This commit is contained in:
Generated
Vendored
+32
@@ -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).
|
||||
Generated
Vendored
+183
@@ -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.
|
||||
Generated
Vendored
+48
@@ -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.
|
||||
Generated
Vendored
+71
@@ -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.
|
||||
Generated
Vendored
+21
@@ -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.
|
||||
Reference in New Issue
Block a user