7.7 KiB
@loadable/server
Install
npm install @loadable/server
Modes
Loadable supports two modes, a static mode and a dynamic mode.
The static mode insert required chunks directly in the page whereas the dynamic mode loads them from your main bundle.
This table compares the two modes.
| Mode | @loadable/babel-plugin |
@loadable/webpack-plugin |
loadComponents() |
Perf |
|---|---|---|---|---|
| Static | Required | Required | Not required | ++ |
| Dynamic | Required | No required | Required | + |
Static Mode (recommended)
1. Install @loadable/babel-plugin
.babelrc
{
"plugins": ["@loadable/babel-plugin"]
}
2. Install @loadable/webpack-plugin
webpack.config.js
const LoadablePlugin = require('@loadable/webpack-plugin')
module.exports = {
/* Your webpack config... */
plugins: [new HtmlWebpackPlugin()],
}
3. Setup LoadableState server-side (with manifest)
import path from 'path'
import { LoadableState } from '@loadable/server'
// This is the manifest generated by webpack
import manifest from '../dist/loadable-manifest.json'
const loadableState = new LoadableState(manifest)
const html = renderToString(
<LoadableStateManager state={loadableState}>
<YourApp />
</LoadableStateManager>,
)
const scriptTags = loadableState.getScriptTags() // or loadableState.getScriptElements();
Dynamic mode
1. Install @loadable/babel-plugin
.babelrc
{
"plugins": ["@loadable/babel-plugin"]
}
2. Setup LoadableState server-side (without manifest)
import path from 'path'
import { LoadableState } from '@loadable/server'
const loadableState = new LoadableState()
const html = renderToString(
<LoadableStateManager state={loadableState}>
<YourApp />
</LoadableStateManager>,
)
const scriptTags = loadableState.getScriptTags() // or loadableState.getScriptElements();
3. Use loadComponents() client-side
import { hydrate } from 'react-dom'
import { loadComponents } from '@loadable/component'
// Call `loadComponents()` before rendering your application
loadComponents().then(() => {
hydrate(<YourApp />, root)
})
Collecting chunks
The basic API goes as follows:
import { renderToString } from 'react-dom/server'
import { LoadableState } from '@loadable/server'
const loadableState = new LoadableState()
// or new LoadableState(manifest), see modes documentation
const html = renderToString(loadableState.collectChunks(<YourApp />))
const scriptTags = loadableState.getScriptTags() // or loadableState.getScriptElements();
The collectChunks method wraps your element in a provider. Optionally you can use the LoadableStateManager provider directly, instead of this method. Just make sure not to use it on the client-side.
import { renderToString } from 'react-dom/server'
import { LoadableState, LoadableStateManager } from 'styled-components'
const loadableState = new LoadableState()
const html = renderToString(
<LoadableStateManager state={loadableState}>
<YourApp />
</LoadableStateManager>,
)
const scriptTags = loadableState.getScriptTags() // or loadableState.getScriptElements();
The loadableState.getScriptTags() returns a string of multiple <script> tags. You must include them before your main bundle.
Alternatively the LoadableState also has a getScriptElements() method that returns an array of React elements.
loadableState.getScriptTags()andloadableState.getScriptElements()can only be called after your element is rendered. As a result, components fromloadableState.getScriptElements()cannot be combined with<YourApp />into a larger component.
Streaming rendering
Loadable is compatible with streaming rendering, if you use it you have to include script when the stream is complete.
import { renderToNodeStream } from 'react-dom/server'
import { LoadableState } from '@loadable/server'
// if you're using express.js, you'd have access to the response object "res"
// typically you'd want to write some preliminary HTML, since React doesn't handle this
res.write('<html><head><title>Test</title></head><body>')
const loadableState = new LoadableState()
// or new LoadableState(manifest), see modes documentation
const jsx = loadableState.collectChunks(<YourApp />)
const stream = renderToNodeStream(jsx)
// you'd then pipe the stream into the response object until it's done
stream.pipe(
res,
{ end: false },
)
// and finalize the response with closing HTML
stream.on('end', () =>
res.end(`${loadableState.getScriptTags()}</body></html>`),
)
Streaming rendering is not compatible with prefetch
<link>tags.
Prefetching
To improve performance, you can include <link ref="preload"> in the head of your HTML page. If you use Prefetch feature of @loadable/component, you can insert them server-side.
import path from 'path'
import { LoadableState } from '@loadable/server'
// This is the manifest generated by webpack
import manifest from '../dist/loadable-manifest.json'
const loadableState = new LoadableState(manifest)
const html = renderToString(
<LoadableStateManager state={loadableState}>
<YourApp />
</LoadableStateManager>,
)
const prefetchTags = loadableState.getPrefetchTags() // or loadableState.getPrefetchElements();
const html = `<html>
<head>${prefetchTags}</head>
<body>
<div id="root">${html}</div>
</body>
</html>`
It only works with
renderToStringAPI. Since<link>must be added in the<head>, you can't do it usingrenderToNodeStream.
API
LoadableState
Used to collect chunks server-side and get them as script tags or script elements.
| Arguments | Description |
|---|---|
manifest |
Optional manifest file path generated using @loadable/webpack-plugin. |
import { LoadableState } from '@loadable/server'
const loadableState = new LoadableState()
// or using manifest
const loadableState = new LoadableState(manifest)
loadableState.collectChunks
Wrap your application in a LoadableManager.
| Arguments | Description |
|---|---|
element |
JSX element that will be wrapped in LoadableManager. |
const app = loadableState.collectChunks(<YourApp />)
loadableState.getScriptTags
Get scripts as a string of <script> tags.
const body = `<body><div id="root">${html}</div>${loadableState.getScriptTags()}</body>`
loadableState.getScriptElements
Get scripts as an array of React <script> elements.
const body = renderToString(
<body>
<div id="root" dangerouslySetInnerHtml={{ __html: html }} />
{loadableState.getScriptElements()}
</body>,
)
loadableState.getPrefetchTags
Get prefetch links as a string of <link> tags.
const head = `<head>${loadableState.getPrefetchTags()}</head>`
loadableState.getPrefetchElements
Get prefetch links as an array of React <link> elements.
const head = renderToString(<head>{loadableState.getPrefetchElements()}</head>)
LoadableManager
Used to inject a LoadableState in the context of your application.
import { LoadableState, LoadableManager } from '@loadable/server'
const loadableState = new LoadableState()
const app = (
<LoadableManager state={loadableState}>
<YourApp />
</LoadableManager>
)
License
MIT