🌏 Create React App companion for universal app. No eject, zero config, Streaming SSR with Suspense. React 18 ready
App.defaultProps = { streaming: true }
(false
by default)App
must be the top-most element being rendered, if possible, put all your providers inside the AppuniversalRender: (req, res) => <App streaming />
partdefaultProps
is not suited for this), please use custom server and set the streaming
prop as you likebabel-preset-cra-universal
react-scripts@5
renderToPipeableStream
by default)
import stringRenderer from '@cra-express/universal-loader/lib/renderer/string-renderer';
...
createReactAppExpress({
handleRender: stringRenderer,
})
hydrateRoot
changesexpress@4
is now a peerDependency, please install it as dependencies
on your appPatch:
For the new major (v4.0.0) release, there'll be some breaking changes:
Babel 7 update
env
-> @babel/preset-env
, react
-> @babel/preset-react
, transform-object-rest-spread
-> @babel/plugin-proposal-object-rest-spread
)module.exports
is readonly now (if used together with import
syntax), please update your code accordingly (Babel 7 related)The default of handleRender
will be stringRenderer
, due many node stream limitation and 3rd party lib support
New API for universalRender
callback. It will only accept return value of:
// before: you still call rTS explicitly despite having stringRenderer declared...
{
handleRender: stringRenderer,
universalRender: (req, res) => renderToString(<App />)
}
// after: just return React element! (or Promise of React element)
{
universalRender: (req, res) => <App />
}
// Need to do Nodestream render? Just pass streamRenderer to `handleRender`
import { streamRenderer } from '@cra-express/universal-loader'
{
universalRender: (req, res) => <App />,
handleRender: streamRenderer
}
// Want to custom handleRender yourself? Possible now!
function customRenderer(req, res, reactEl, htmlData, options) { ... }
handleUniversalRender
helper on @cra-express/core
is removed, since it won't be compatible with new API.
// before
universalRender: handleUniversalRender(<App />)
// after
universalRender: () => <App />
universalRender
APINODE_PATH
support