A custom partial React SSR renderer for prefetching and suspense
npm install react-dry-renderer
react-dom/server does not have support for suspense yet.
react-ssr-prepass offers suspense on the server-side today, until it does. ✨
react-ssr-prepass is a partial server-side React renderer that does a prepass
renderToString or
renderToNodeStream.
react-dom/server does not support data fetching or suspense
react-ssr-prepass offers a solution by being a "prepass" function
renderToStaticMarkup repeatedly.
react-ssr-prepass on the other hand is a custom implementation
ReactPartialRenderer
react-is
react-ssr-prepass alongside react and react-dom:
sh
yarn add react-ssr-prepass
or
npm install --save react-ssr-prepass
`
In your SSR code you may now add it in front of your usual renderToString
or renderToNodeStream code:
`js
import { createElement } from 'react'
import { renderToString } from 'react-dom/server'
import ssrPrepass from 'react-ssr-prepass'
const renderApp = async App => {
const element = createElement(App)
await ssrPrepass(element)
return renderToString(element)
}
`
Additionally you can also pass a "visitor function" as your second argument.
This function is called for every React class or function element that is
encountered.
`js
ssrPrepass( , (element, instance) => {
if (element.type === SomeData) {
return fetchData()
} else if (instance && instance.fetchData) {
return instance.fetchData()
}
})
`
The first argument of the visitor is the React element. The second is
the instance of a class component or undefined. When you return
a promise from this function react-ssr-prepass will suspend before
rendering this element.
You should be aware that react-ssr-prepass does not handle any
data rehydration. In most cases it's fine to collect data from your cache
or store after running ssrPrepass, turn it into JSON, and send it
down in your HTML result.
Examples & Recipes
$3
Instead of using react-apollo's own getDataFromTree function, react-ssr-prepass
can be used instead. For this to work, we will have to write a visitor function
that knows how to suspend on react-apollo's Query component.
Luckily this is quite simple, since all we need to do is call the fetchData
method on the Query component's instance.
`js
ssrPrepass( , (_element, instance) => {
if (instance !== undefined && typeof instance.fetchData === 'function') {
return instance.fetchData()
}
})
`
Since we're now calling fetchData when it exists, which returns a Promise
already, ssrPrepass will suspend on components.
More information can be found in Apollo's own docs
Optional Dependencies
$3
react-ssr-prepass has an optional dependency on styled-components@>=4.0.0.
This optimization skips any styling logic and imitates the attributes and props
logic of styled-components otherwise.
It exists because styled-components may populate the ServerStyleSheet as
part of a react-ssr-prepass run, since it behaves like a normal React renderer.
This is dangerous if the element tree that is passed to react-ssr-prepass
is not wrapped in a ServerStyleSheet at all, since it will start accumulating
styles and cause a memory leak. In v4 it can also cause these styles to
become _global_ and be sent to every server-rendered page.
If you're not using styled-components however and are bundling your server-side
code you need to stub styled-components with an empty package or just install it.
Prior Art
This library is (luckily) not a reimplementation from scratch of
React's server-side rendering. Instead it's mostly based on
React's own server-side rendering logic that resides in its
ReactPartialRenderer.
The approach of doing an initial "data fetching pass" is inspired by:
- react-apollo's getDataFromTree
- react-tree-walker`