diff --git a/docs/advanced-features/react-18.md b/docs/advanced-features/react-18.md deleted file mode 100644 index 1d82c82b71b47..0000000000000 --- a/docs/advanced-features/react-18.md +++ /dev/null @@ -1,154 +0,0 @@ -# React 18 - -[React 18](https://reactjs.org/blog/2021/06/08/the-plan-for-react-18.html) adds new features including, Suspense, automatic batching of updates, APIs like `startTransition`, and a new streaming API for server rendering with support for `React.lazy`. - -React 18 is in RC now. Read more about React 18's [release plan](https://github.com/reactwg/react-18/discussions) and discussions from the [working group](https://github.com/reactwg/react-18/discussions). - -### React 18 Usage in Next.js - -Ensure you have the `rc` npm tag of React installed: - -```jsx -npm install next@latest react@rc react-dom@rc -``` - -That's all! You can now start using React 18's new APIs like `startTransition` and `Suspense` in Next.js. - -### Enable SSR Streaming (Alpha) - -Concurrent features in React 18 include built-in support for server-side Suspense and SSR streaming support, allowing you to server-render pages using HTTP streaming. - -This is an experimental feature in Next.js 12, but once enabled, SSR will use the same [Edge Runtime](/docs/api-reference/edge-runtime.md) as [Middleware](/docs/middleware.md). - -To enable, use the experimental flag `concurrentFeatures: true`: - -```jsx -// next.config.js -module.exports = { - experimental: { - concurrentFeatures: true, - }, -} -``` - -Once enabled, you can use Suspense and SSR streaming for all pages. This also means that you can use Suspense-based data-fetching, `next/dynamic`, and React's built-in `React.lazy` with Suspense boundaries. - -```jsx -import dynamic from 'next/dynamic' -import { lazy, Suspense } from 'react' - -import Content from '../components/content' - -// These two ways are identical: -const Profile = dynamic(() => import('./profile'), { suspense: true }) -const Footer = lazy(() => import('./footer')) - -export default function Home() { - return ( -
- }> - {/* A component that uses Suspense-based */} - - - }> - - - }> -
- ) -} -``` - -## React Server Components - -React Server Components allow us to render everything, including the components themselves, on the server. This is fundamentally different from server-side rendering where you're pre-generating HTML on the server. With Server Components, there's **zero client-side JavaScript needed,** making page rendering faster. This improves the user experience of your application, pairing the best parts of server-rendering with client-side interactivity. - -### Enable React Server Components (Alpha) - -To use React Server Components, ensure you have React 18 installed. Then, turn on the `concurrentFeatures` and `serverComponents` options in `next.config.js`: - -```jsx -// next.config.js -module.exports = { - experimental: { - concurrentFeatures: true, - serverComponents: true, - }, -} -``` - -Next, if you already have customized `pages/_document` component, you need to remove the `getInitialProps` static method and the `getServerSideProps` export if there’s any, otherwise it won't work with server components. If no custom Document component is provided, Next.js will fallback to a default one like below. - -```jsx -// pages/_document.js -import { Html, Head, Main, NextScript } from 'next/document' - -export default function Document() { - return ( - - - -
- - - - ) -} -``` - -Then, you can start using React Server Components. [See our example](https://github.com/vercel/next-rsc-demo) for more information. - -### Server Components APIs (Alpha) - -To run a component on the server, append `.server.js` to the end of the filename. For example `./pages/home.server.js` is a Server Component. - -For client components, add `.client.js`. For example, `./components/avatar.client.js`. - -You can then import other server or client components from any server component. Note: a server component **can not** be imported by a client component. Components without "server/client" extensions will be treated as "universal component" and can be used and rendered by both sides, depending on where it is imported. For example: - -```jsx -// pages/home.server.js - -import { Suspense } from 'react' - -import Profile from '../components/profile.server' -import Content from '../components/content.client' - -export default function Home() { - return ( -
-

Welcome to React Server Components

- - - - -
- ) -} -``` - -The `` and `` components will always be server-side rendered and streamed to the client, and will not be included by the client runtime. However `` will still be hydrated on the client-side, like normal React components. - -To see a full example, check out [link to the demo and repository](https://github.com/vercel/next-rsc-demo). - -## **Supported Next.js APIs** - -- `next/link` / `next/image` -- `next/document` / `next/app` -- Dynamic routing - -## **Unsupported Next.js APIs** - -While RSC and SSR streaming is still in the alpha stage, not all Next.js APIs are supported. The following Next.js APIs have limited functionality inside Server Components: - -- React internals: Most of React hooks such as `useContext`, `useState`, `useReducer`, `useEffect` and `useLayoutEffect` are not supported as of today since Server Components are executed per requests and aren't stateful. -- `next/head` -- Partial: Note that Inside `.client.js` components `useRouter` is supported -- Styled JSX -- CSS Modules -- Next.js I18n -- `getInitialProps`, `getStaticProps` and `getStaticPaths` - -React 18 without SSR streaming isn't affected. diff --git a/docs/advanced-features/react-18/overview.md b/docs/advanced-features/react-18/overview.md new file mode 100644 index 0000000000000..2df4aa92b3b0b --- /dev/null +++ b/docs/advanced-features/react-18/overview.md @@ -0,0 +1,28 @@ +# React 18 + +[React 18](https://reactjs.org/blog/2021/06/08/the-plan-for-react-18.html) adds new features including Suspense, automatic batching of updates, APIs like `startTransition`, and a new streaming API for server rendering with support for `React.lazy`. +Next.js also provides streaming related APIs, please checkout [next/streaming](/docs/api-reference/next/streaming.md) for details. + +React 18 is now in Release Candidate (RC). Read more about React 18's [release plan](https://reactjs.org/blog/2021/06/08/the-plan-for-react-18.html) and discussions from the [working group](https://github.com/reactwg/react-18/discussions). + +## Using React 18 with Next.js + +Install the RC version of React 18: + +```jsx +npm install next@latest react@rc react-dom@rc +``` + +You can now start using React 18's new APIs like `startTransition` and `Suspense` in Next.js. + +## Streaming SSR (Alpha) + +Streaming server-rendering (SSR) is an experimental feature in Next.js 12. When enabled, SSR will use the same [Edge Runtime](/docs/api-reference/edge-runtime.md) as [Middleware](/docs/middleware.md). + +[Learn how to enable streaming in Next.js.](/docs/react-18/streaming.md) + +## React Server Components (Alpha) + +Server Components are a new feature in React that let you reduce your JavaScript bundle size by separating server and client-side code. Server Components allow developers to build apps that span the server and client, combining the rich interactivity of client-side apps with the improved performance of traditional server rendering. + +Server Components are still in research and development. [Learn how to try Server Components](/docs/react-18/server-components.md) as an experimental feature in Next.js. diff --git a/docs/advanced-features/react-18/server-components.md b/docs/advanced-features/react-18/server-components.md new file mode 100644 index 0000000000000..940c0c4755fb3 --- /dev/null +++ b/docs/advanced-features/react-18/server-components.md @@ -0,0 +1,132 @@ +# React Server Components (Alpha) + +Server Components allow us to render React components on the server. This is fundamentally different from server-side rendering (SSR) where you're pre-generating HTML on the server. With Server Components, there's **zero client-side JavaScript needed,** making page rendering faster. This improves the user experience of your application, pairing the best parts of server-rendering with client-side interactivity. + +### Enable React Server Components + +To use React Server Components, ensure you have React 18 installed: + +```jsx +npm install next@latest react@rc react-dom@rc +``` + +Then, update your `next.config.js`: + +```jsx +// next.config.js +module.exports = { + experimental: { + runtime: 'nodejs', + serverComponents: true, + }, +} +``` + +Using `runtime` also enables [Streaming SSR](/docs/advanced-features/react-18/streaming). When setting `runtime` to `'edge'`, the server will be running entirely in the [Edge Runtime](https://nextjs.org/docs/api-reference/edge-runtime). + +Now, you can start using React Server Components in Next.js. [See our example](https://github.com/vercel/next-rsc-demo) for more information. + +### Server Components Conventions + +To run a component on the server, append `.server.js` to the end of the filename. For example, `./pages/home.server.js` will be treated as a Server Component. + +For client components, append `.client.js` to the filename. For example, `./components/avatar.client.js`. + +You can then import other server or client components from any server component. Note: a server component **can not** be imported by a client component. Components without "server/client" extensions will be treated as shared components and can be used and rendered by both sides, depending on where it is imported. For example: + +```jsx +// pages/home.server.js + +import { Suspense } from 'react' + +import Profile from '../components/profile.server' +import Content from '../components/content.client' + +export default function Home() { + return ( +
+

Welcome to React Server Components

+ + + + +
+ ) +} +``` + +The `` and `` components will always be server-side rendered and streamed to the client, and will not be included by the client-side JavaScript. However, `` will still be hydrated on the client-side, like normal React components. + +> Make sure you're using default imports and exports for server components (`.server.js`). The support of named exports are a work in progress! + +To see a full example, check out the [hello world example](https://github.com/vercel/next.js/tree/canary/examples/react-server-components) or the larger [vercel/next-rsc-demo demo](https://github.com/vercel/next-rsc-demo). + +## Supported Next.js APIs + +### `next/link` and `next/image` + +You can use `next/link` and `next/image` like before and they will be treated as client components to keep the interaction on client side. + +### `next/document` + +If you have a custom `_document`, you have to change your `_document` to a functional component like below to use server components. If you don't have one, Next.js will use the default `_document` component for you. + +```jsx +// pages/_document.js +import { Html, Head, Main, NextScript } from 'next/document' + +export default function Document() { + return ( + + + +
+ + + + ) +} +``` + +### `next/app` + +If you're using `_app.js`, the usage is the same as [Custom App](/docs/advanced-features/custom-app). +If you're using `_app.server.js` as a server component, see the example below where it only receives the `children` prop as React elements. You can wrap any other client or server components around `children` to customize the layout of your app. + +```js +// pages/_app.server.js +export default function App({ children }) { + return children +} +``` + +### Routing + +Both basic routes with path and queries and dynamic routes are supported. If you need to access the router in server components(`.server.js`), they will receive `router` instance as a prop so that you can directly access them without using the `useRouter()` hook. + +```jsx +// pages/index.server.js + +export default function Index({ router }) { + // You can access routing information by `router.pathname`, etc. + return 'hello' +} +``` + +### Unsupported Next.js APIs + +While RSC and SSR streaming are still in the alpha stage, not all Next.js APIs are supported. The following Next.js APIs have limited functionality within Server Components. React 18 use without SSR streaming is not affected. + +#### React internals + +Most React hooks, such as `useContext`, `useState`, `useReducer`, `useEffect` and `useLayoutEffect`, are not supported as of today since server components are executed per request and aren't stateful. + +#### Data Fetching & Styling + +Like streaming SSR, styling and data fetching within `Suspense` on the server side are not well supported. We're still working on them. + +Page level exported methods like `getInitialProps`, `getStaticProps` and `getStaticPaths` are not supported. + +#### `next/head` and I18n + +We are still working on support for these features. diff --git a/docs/advanced-features/react-18/streaming.md b/docs/advanced-features/react-18/streaming.md new file mode 100644 index 0000000000000..544759b3daa66 --- /dev/null +++ b/docs/advanced-features/react-18/streaming.md @@ -0,0 +1,71 @@ +# Streaming SSR (Alpha) + +React 18 will include architectural improvements to React server-side rendering (SSR) performance. This means you can use `Suspense` in your React components in streaming SSR mode and React will render them on the server and send them through HTTP streams. +It's worth noting that another experimental feature, React Server Components, is based on streaming. You can read more about server components related streaming APIs in [`next/streaming`](docs/api-reference/next/streaming.md). However, this guide focuses on basic React 18 streaming. + +## Enable Streaming SSR + +Enabling streaming SSR means React renders your components into streams and the client continues receiving updates from these streams even after the initial SSR response is sent. In other words, when any suspended components resolve down the line, they are rendered on the server and streamed to the client. With this strategy, the app can start emitting HTML even before all the data is ready, improving your app's loading performance. As an added bonus, in streaming SSR mode, the client will also use selective hydration strategy to prioritize component hydration which based on user interaction. + +To enable streaming SSR, set the experimental option `runtime` to either `'nodejs'` or `'edge'`: + +```jsx +// next.config.js +module.exports = { + experimental: { + runtime: 'nodejs', + }, +} +``` + +This option determines the environment in which streaming SSR will be happening. When setting to `'edge'`, the server will be running entirely in the [Edge Runtime](https://nextjs.org/docs/api-reference/edge-runtime). + +## Streaming Features + +### next/dynamic + +Dynamic imports through `React.lazy` have better support in React 18. Previously, Next.js supported dynamic imports internally without requiring `Suspense` or `React.lazy`. Now to embrace the official APIs on the React side, we provide you with `options.suspense` in `next/dynamic`. + +```jsx +import dynamic from 'next/dynamic' +import { lazy, Suspense } from 'react' + +import Content from '../components/content' + +// These two ways are identical: +const Profile = dynamic(() => import('./profile'), { suspense: true }) +const Footer = lazy(() => import('./footer')) + +export default function Home() { + return ( +
+ }> + {/* A component that uses Suspense */} + + + }> + + + }> +
+ +
+ ) +} +``` + +Check out [`next/streaming`](/docs/api-reference/next/streaming.md) for more details on building Next.js apps in streaming SSR mode. + +## Important Notes + +#### `next/head` and `next/script` + +Using resource tags (e.g. scripts or stylesheets) in `next/head` won't work as intended with streaming, as the loading order and timing of `next/head` tags can no longer be guaranteed once you add Suspense boundaries. We suggest moving resource tags to `next/script` with the `afterInteractive` or `lazyOnload` strategy, or to `_document`. For similar reasons, we also suggest migrating `next/script` instances with the `beforeInteractive` strategy to `_document`. + +#### Data Fetching + +Currently, data fetching within `Suspense` boundaries on the server side is not fully supported, which could lead to mismatching between server and client. In the short-term, please don't try data fetching within `Suspense`. + +#### Styling + +The Next.js team is working on support for `styled-jsx` and CSS modules in streaming SSR. Stay tuned for updates. diff --git a/docs/api-reference/next/streaming.md b/docs/api-reference/next/streaming.md new file mode 100644 index 0000000000000..210b18c48df36 --- /dev/null +++ b/docs/api-reference/next/streaming.md @@ -0,0 +1,95 @@ +--- +description: Streaming related APIs to build Next.js apps in streaming SSR or with React Server Components. +--- + +# next/streaming + +The experimental `next/streaming` module provides streaming related APIs to port the existing functionality of Next.js apps to streaming scenarios and facilitate the usage of React Server Components. + +## unstable_useWebVitalsReport + +Next.js provides an `_app` component-level function, [`reportWebVitals`](docs/advanced-features/measuring-performance), for tracking performance metrics. With Server Components, you may have a pure server-side custom `_app` component (which doesn't run client effects) so the existing API won't work. + +With the new `unstable_useWebVitalsReport` API, you're able to track [Core Web Vitals](https://nextjs.org/learn/seo/web-performance) in client components: + +```jsx +// pages/_app.js +import { unstable_useWebVitalsReport } from 'next/streaming' + +export default function Home() { + unstable_useWebVitalsReport((data) => { + console.log(data) + }) + + return
Home Page
+} +``` + +This method could also be used to replace statically exported `reportWebVitals` functions in your existing `_app`: + +```jsx +// pages/_app.server.js +import Layout from '../components/layout.client.js' + +export default function App({ children }) { + return {children} +} +``` + +```jsx +// components/layout.client.js +import { unstable_useWebVitalsReport } from 'next/streaming' + +export default function Layout() { + unstable_useWebVitalsReport((data) => { + console.log(data) + }) + + return ( +
+

Hello

+
{children}
+
+ ) +} +``` + +## unstable_useRefreshRoot + +Since Server Components are rendered on the server-side, in some cases you might need to partially refresh content from the server. + +For example, a search bar (client component) which displays search results as server components. You'd want to update the search results while typing and rerender the results list with a certain frequency (e.g. with each keystroke or on a debounce). + +The `unstable_useRefreshRoot` hook returns a `refresh` API to let you re-render the React tree smoothly without flickering. This is only allowed for use on the client-side and will only affect Server Components at the moment. + +```jsx +// pages/index.server.js +import Search from '../components/search.client.js' +import SearchResults from '../components/search-results.server.js' + +function Home() { + return ( +
+ + +
+ ) +} +``` + +```jsx +// components/search.client.js +import { unstable_useRefreshRoot as useRefreshRoot } from 'next/streaming' + +export default function Search() { + const refresh = useRefreshRoot() + + return ( + { + refresh() + }} + /> + ) +} +``` diff --git a/docs/manifest.json b/docs/manifest.json index 95e970bcb51b0..208cbe9f906f3 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -289,7 +289,26 @@ }, { "title": "React 18", - "path": "/docs/advanced-features/react-18.md" + "routes": [ + { + "path": "/docs/advanced-features/react-18", + "redirect": { + "destination": "/docs/advanced-features/react-18/overview" + } + }, + { + "title": "Overview", + "path": "/docs/advanced-features/react-18/overview.md" + }, + { + "title": "Streaming SSR", + "path": "/docs/advanced-features/react-18/streaming.md" + }, + { + "title": "React Server Components", + "path": "/docs/advanced-features/react-18/server-components.md" + } + ] } ] }, @@ -358,6 +377,10 @@ "title": "next/server", "path": "/docs/api-reference/next/server.md" }, + { + "title": "next/streaming", + "path": "/docs/api-reference/next/streaming.md" + }, { "title": "Edge Runtime", "path": "/docs/api-reference/edge-runtime.md"