diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index d553f10c..8a868a6c 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -50,6 +50,7 @@ const preview: Preview = { storySort: { order: [ 'Welcome', + 'Guides', 'Migration Guides', 'Form Elements', 'Content Presentation', diff --git a/README.md b/README.md index 5d239140..aaa813fb 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,16 @@ import { Button, DateInput, Form } from 'nhsuk-react-components'; ; ``` +## Server-side rendering + +Version 6.0.0 and later support server-side rendering (SSR) and React Server Components +(RSC). Components render HTML on the server, then components that need JavaScript are +enhanced after hydration. + +Read the [server-side rendering guide](docs/server-side-rendering.md) for the required +NHS.UK frontend styles, browser feature detection, React Server Component imports and +progressive enhancement checks. + ## Development To run this project locally, set up Yarn using [Node.js corepack](https://github.com/nodejs/corepack#readme) diff --git a/docs/server-side-rendering.md b/docs/server-side-rendering.md new file mode 100644 index 00000000..a30f774b --- /dev/null +++ b/docs/server-side-rendering.md @@ -0,0 +1,146 @@ +# Server-side rendering + +Version 6.0.0 and later of `nhsuk-react-components` support server-side rendering (SSR) +and React Server Components (RSC). + +The components render HTML on the server. Components that need JavaScript preserve their +[`'use client'` boundaries](https://react.dev/reference/rsc/use-client) and load the +matching NHS.UK frontend module after hydration. You do not need to opt the components +out of SSR. + +SSR helps deliver usable HTML before JavaScript loads, but it does not guarantee +progressive enhancement by itself. Make sure users can still access content and complete +their task when JavaScript is unavailable. + +## Load NHS.UK frontend styles + +The styles are provided by the `nhsuk-frontend` peer dependency. Install it alongside +`nhsuk-react-components` if it is not already a dependency: + +```bash +npm install nhsuk-frontend +``` + +Load the NHS.UK frontend styles once in your application layout. You can serve the +precompiled stylesheet from: + +```text +node_modules/nhsuk-frontend/dist/nhsuk/nhsuk-frontend.min.css +``` + +and reference it in your page: + +```html + +``` + +Alternatively, include NHS.UK frontend in your Sass entry point: + +```scss +@forward 'nhsuk-frontend/dist/nhsuk'; +``` + +See the NHS.UK frontend guidance for [other CSS and asset setup +options](https://github.com/nhsuk/nhsuk-frontend/blob/main/docs/installation/installing-with-npm.md). + +## Add browser feature detection + +Add the NHS.UK frontend feature-detection script at the start of the `
`, before the +rendered page content: + +```html + + + + +``` + +In a JSX layout, set `suppressHydrationWarning` on the `` because the script changes +its class before React hydrates the page: + +```jsx +{children} +``` + +## Render components on the server + +Use the components normally in a route or page that your React framework renders on the +server: + +```jsx +import { Button, Form, TextInput } from 'nhsuk-react-components'; + +export default function SignInPage() { + return ( + + ); +} +``` + +JavaScript-enhanced components initialise their own NHS.UK frontend module after +hydration. Do not also call `initAll()` for components rendered by this package, because +that would initialise them twice. If the page also contains non-React NHS.UK markup, +scope its initialisation to a container that does not include components rendered by +this package. + +If you manage rendering without a framework, use [React's server rendering and hydration +APIs](https://react.dev/reference/react-dom/server). React recommends streaming APIs such +as `renderToPipeableStream` for Node.js and `renderToReadableStream` for web streams. + +## Use React Server Components + +The package preserves client boundaries for interactive components, so compatible RSC +frameworks can import them from Server Components. A component marked with `'use client'` +can still be pre-rendered to HTML on the server and hydrated in the browser. + +For multipart components, prefer the named child exports instead of dot notation across +an RSC boundary: + +```jsx +import { Breadcrumb, BreadcrumbItem } from 'nhsuk-react-components'; + +export default function PageBreadcrumb() { + return ( +