JSPM

  • Created
  • Published
  • Downloads 168759
  • Score
    100M100P100Q161743F
  • License MIT

Server utilities for loadable.

Package Exports

  • @loadable/server

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@loadable/server) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

@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 Required Required +

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 = {
  // ...
  plugins: [new LoadablePlugin()],
}

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. Install @loadable/webpack-plugin

webpack.config.js

const LoadablePlugin = require('@loadable/webpack-plugin')

module.exports = {
  // ...
  plugins: [new LoadablePlugin()],
}

3. 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();

4. 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() and loadableState.getScriptElements() can only be called after your element is rendered. As a result, components from loadableState.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 renderToString API. Since <link> must be added in the <head>, you can't do it using renderToNodeStream.

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