react-loadable

A higher order component for loading components with promises.

README

React Loadable

A higher order component for loading components with dynamic imports.


Install


  1. ```sh
  2. yarn add react-loadable
  3. ```

Example


  1. ``` js
  2. import Loadable from 'react-loadable';
  3. import Loading from './my-loading-component';

  4. const LoadableComponent = Loadable({
  5.   loader: () => import('./my-component'),
  6.   loading: Loading,
  7. });

  8. export default class App extends React.Component {
  9.   render() {
  10.     return <LoadableComponent/>;
  11.   }
  12. }
  13. ```

Happy Customers:



Users


- Wxb

_If your company or project is using React Loadable, please open a PR and add

yourself to this list (in alphabetical order please)_


Also See:


- [react-loadable-visibility](https://github.com/stratiformltd/react-loadable-visibility) - Building on top of and keeping the same API as react-loadable, this library enables you to load content that is visible on the screen.

- [react-loadable-ssr-addon](https://github.com/themgoncalves/react-loadable-ssr-addon) - Server Side Render add-on for react-loadable. Discover & load automatically dynamically all files dependencies, e.g. splitted chunks, css, etc.



GUIDE

Guide


So you've got your React app, you're bundling it with Webpack, and things are
going smooth. But then one day you notice your app's bundle is getting so big
that it's slowing things down.

It's time to start code-splitting your app!

A single giant bundle vs multiple smaller bundles

Code-splitting is the process of taking one large bundle containing your entire
app, and splitting them up into multiple smaller bundles which contain separate
parts of your app.

This might seem difficult to do, but tools like Webpack have this built in, and
React Loadable is designed to make it super simple.

Route-based splitting vs. Component-based splitting


A common piece of advice you will see is to break your app into separate routes
and load each one asynchronously. This seems to work well enough for many apps–
as a user, clicking a link and waiting for a page to load is a familiar
experience on the web.

But we can do better than that.

Using most routing tools for React, a route is simply a component. There's
nothing particularly special about them (Sorry Ryan and Michael– you're what's
special). So what if we optimized for splitting around components instead of
routes? What would that get us?

Route vs. component centric code splitting

As it turns out: Quite a lot. There are many more places than just routes where
you can pretty easily split apart your app. Modals, tabs, and many more UI
components hide content until the user has done something to reveal it.

Example: Maybe your app has a map buried inside of a tab component. Why

would you load a massive mapping library for the parent route every time when

the user may never go to that tab?


Not to mention all the places where you can defer loading content until higher
priority content is finished loading. That component at the bottom of your page
which loads a bunch of libraries: Why should that be loaded at the same time as
the content at the top?

And because routes are just components, we can still easily code-split at the
route level.

Introducing new code-splitting points in your app should be so easy that you
don't think twice about it. It should be a matter of changing a few lines of
code and everything else should be automated.

Introducing React Loadable


React Loadable is a small library that makes component-centric code splitting
incredibly easy in React.

Loadable is a higher-order component (a function that creates a component)
which lets you dynamically load any module before rendering it into your app.

Let's imagine two components, one that imports and renders another.

  1. ``` js
  2. import Bar from './components/Bar';

  3. class Foo extends React.Component {
  4.   render() {
  5.     return <Bar/>;
  6.   }
  7. }
  8. ```

Right now we're depending on Bar being imported synchronously via import,
but we don't need it until we go to render it. So why don't we just defer that?

Using a dynamic import (a tc39 proposal currently at Stage 3)
we can modify our component to load Bar asynchronously.

  1. ``` js
  2. class MyComponent extends React.Component {
  3.   state = {
  4.     Bar: null
  5.   };

  6.   componentWillMount() {
  7.     import('./components/Bar').then(Bar => {
  8.       this.setState({ Bar: Bar.default });
  9.     });
  10.   }

  11.   render() {
  12.     let {Bar} = this.state;
  13.     if (!Bar) {
  14.       return <div>Loading...</div>;
  15.     } else {
  16.       return <Bar/>;
  17.     };
  18.   }
  19. }
  20. ```

But that's a whole bunch of work, and it doesn't even handle a bunch of cases.
What about when import() fails? What about server-side rendering?

Instead you can use Loadable to abstract away the problem.

  1. ``` js
  2. import Loadable from 'react-loadable';

  3. const LoadableBar = Loadable({
  4.   loader: () => import('./components/Bar'),
  5.   loading() {
  6.     return <div>Loading...</div>
  7.   }
  8. });

  9. class MyComponent extends React.Component {
  10.   render() {
  11.     return <LoadableBar/>;
  12.   }
  13. }
  14. ```

Automatic code-splitting on import()


When you use import() with Webpack 2+, it will
you with no additional configuration.

This means that you can easily experiment with new code splitting points just
by switching to import() and using React Loadable. Figure out what performs
best for your app.

Creating a great "Loading..." Component


Rendering a static "Loading..." doesn't communicate enough to the user. You
also need to think about error states, timeouts, and making it a nice
experience.

  1. ``` js
  2. function Loading() {
  3.   return <div>Loading...</div>;
  4. }

  5. Loadable({
  6.   loader: () => import('./WillFailToLoad'), // oh no!
  7.   loading: Loading,
  8. });
  9. ```

To make this all nice, your loading component receives a
couple different props.

Loading error states


When your [loader](optsloader) fails, your loading component
will receive an [error](propserror) prop which will be an Error object (otherwise it
will be null).

  1. ``` js
  2. function Loading(props) {
  3.   if (props.error) {
  4.     return <div>Error! <button onClick={ props.retry }>Retry</button>div>;
  5.   } else {
  6.     return <div>Loading...</div>;
  7.   }
  8. }
  9. ```

Avoiding _Flash Of Loading Component_


Sometimes components load really quickly (<200ms) and the loading screen only
quickly flashes on the screen.

A number of user studies have proven that this causes users to perceive things
taking longer than they really have. If you don't show anything, users perceive
it as being faster.

So your loading component will also get a [pastDelay prop](#propspastdelay)
which will only be true once the component has taken longer to load than a set

  1. ``` js
  2. function Loading(props) {
  3.   if (props.error) {
  4.     return <div>Error! <button onClick={ props.retry }>Retry</button>div>;
  5.   } else if (props.pastDelay) {
  6.     return <div>Loading...</div>;
  7.   } else {
  8.     return null;
  9.   }
  10. }
  11. ```

This delay defaults to 200ms but you can also customize the
delay inLoadable.

  1. ``` js
  2. Loadable({
  3.   loader: () => import('./components/Bar'),
  4.   loading: Loading,
  5.   delay: 300, // 0.3 seconds
  6. });
  7. ```

Timing out when the loader is taking too long


Sometimes network connections suck and never resolve or fail, they just hang
there forever. This sucks for the user because they won't know if it should
always take this long, or if they should try refreshing.

The loading component will receive a
[timedOut prop](#propstimedout) which will be set to true when the
[loader](#optsloader) has timed out.

  1. ``` js
  2. function Loading(props) {
  3.   if (props.error) {
  4.     return <div>Error! <button onClick={ props.retry }>Retry</button>div>;
  5.   } else if (props.timedOut) {
  6.     return <div>Taking a long time... <button onClick={ props.retry }>Retry</button>div>;
  7.   } else if (props.pastDelay) {
  8.     return <div>Loading...</div>;
  9.   } else {
  10.     return null;
  11.   }
  12. }
  13. ```

However, this feature is disabled by default. To turn it on, you can pass a
[timeout option](#optstimeout) to Loadable.

  1. ``` js
  2. Loadable({
  3.   loader: () => import('./components/Bar'),
  4.   loading: Loading,
  5.   timeout: 10000, // 10 seconds
  6. });
  7. ```

Customizing rendering


By default Loadable will render the default export of the returned module.
If you want to customize this behavior you can use the
[render option](#optsrender).

  1. ``` js
  2. Loadable({
  3.   loader: () => import('./my-component'),
  4.   render(loaded, props) {
  5.     let Component = loaded.namedExport;
  6.     return <Component {...props}/>;
  7.   }
  8. });
  9. ```

Loading multiple resources


Technically you can do whatever you want within loader() as long as it
returns a promise and you're able to render something.
But writing it out can be a bit annoying.

To make it easier to load multiple resources in parallel, you can use
[Loadable.Map](#loadablemap).

  1. ``` js
  2. Loadable.Map({
  3.   loader: {
  4.     Bar: () => import('./Bar'),
  5.     i18n: () => fetch('./i18n/bar.json').then(res => res.json()),
  6.   },
  7.   render(loaded, props) {
  8.     let Bar = loaded.Bar.default;
  9.     let i18n = loaded.i18n;
  10.     return <Bar {...props} i18n={i18n}/>;
  11.   },
  12. });
  13. ```

When using Loadable.Map the [render() method](#optsrender) is required. It
will be passed a loaded param which will be an object matching the shape of
your loader.

Preloading


As an optimization, you can also decide to preload a component before it gets
rendered.

For example, if you need to load a new component when a button gets pressed,
you could start preloading the component when the user hovers over the button.

The component created by Loadable exposes a
[static preload method](#loadablecomponentpreload) which does exactly this.

  1. ``` js
  2. const LoadableBar = Loadable({
  3.   loader: () => import('./Bar'),
  4.   loading: Loading,
  5. });

  6. class MyComponent extends React.Component {
  7.   state = { showBar: false };

  8.   onClick = () => {
  9.     this.setState({ showBar: true });
  10.   };

  11.   onMouseOver = () => {
  12.     LoadableBar.preload();
  13.   };

  14.   render() {
  15.     return (
  16.       <div>
  17.         <button
  18.           onClick={this.onClick}
  19.           onMouseOver={this.onMouseOver}>
  20.           Show Bar
  21.         </button>
  22.         {this.state.showBar && <LoadableBar/>}
  23.       </div>
  24.     )
  25.   }
  26. }
  27. ```



SERVER SIDE RENDERING

Server-Side Rendering


When you go to render all these dynamically loaded components, what you'll get
is a whole bunch of loading screens.

This really sucks, but the good news is that React Loadable is designed to
make server-side rendering work as if nothing is being loaded dynamically.

Here's our starting server using Express.

  1. ``` js
  2. import express from 'express';
  3. import React from 'react';
  4. import ReactDOMServer from 'react-dom/server';
  5. import App from './components/App';

  6. const app = express();

  7. app.get('/', (req, res) => {
  8.   res.send(`
  9.     doctype html>
  10.     <html lang="en">
  11.       <head>...</head>
  12.       <body>
  13.         <div id="app">${ReactDOMServer.renderToString(<App/>)}div>
  14.         <script src="/dist/main.js"></script>
  15.       </body>
  16.     </html>
  17.   `);
  18. });

  19. app.listen(3000, () => {
  20.   console.log('Running on http://localhost:3000/');
  21. });
  22. ```

Preloading all your loadable components on the server


The first step to rendering the correct content from the server is to make sure
that all of your loadable components are already loaded when you go to render
them.

To do this, you can use the [Loadable.preloadAll](#loadablepreloadall)
method. It returns a promise that will resolve when all your loadable
components are ready.

  1. ``` js
  2. Loadable.preloadAll().then(() => {
  3.   app.listen(3000, () => {
  4.     console.log('Running on http://localhost:3000/');
  5.   });
  6. });
  7. ```

Picking up a server-side rendered app on the client


This is where things get a little bit tricky. So let's prepare ourselves
little bit.

In order for us to pick up what was rendered from the server we need to have
all the same code that was used to render on the server.

To do this, we first need our loadable components telling us which modules they
are rendering.

Declaring which modules are being loaded


There are two options in [Loadable](#loadable) and
[Loadable.Map](#loadablemap) which are used to tell us which modules our
component is trying to load: [opts.modules](#optsmodules) and
[opts.webpack](#optswebpack).

  1. ``` js
  2. Loadable({
  3.   loader: () => import('./Bar'),
  4.   modules: ['./Bar'],
  5.   webpack: () => [require.resolveWeak('./Bar')],
  6. });
  7. ```

But don't worry too much about these options. React Loadable includes a
Babel plugin to add them for you.

Just add the react-loadable/babel plugin to your Babel config:

  1. ``` json
  2. {
  3.   "plugins": [
  4.     "react-loadable/babel"
  5.   ]
  6. }
  7. ```

Now these options will automatically be provided.

For typescript you can use react-loadable-ts-transformer which is a ts analog of react-loadable/babel plugin.

Finding out which dynamic modules were rendered


Next we need to find out which modules were actually rendered when a request
comes in.

For this, there is [Loadable.Capture](#loadablecapture) component which can
be used to collect all the modules that were rendered.

  1. ``` js
  2. import Loadable from 'react-loadable';

  3. app.get('/', (req, res) => {
  4.   let modules = [];

  5.   let html = ReactDOMServer.renderToString(
  6.     <Loadable.Capture report={moduleName => modules.push(moduleName)}>
  7.       <App/>
  8.     </Loadable.Capture>
  9.   );

  10.   console.log(modules);

  11.   res.send(`...${html}...`);
  12. });
  13. ```

Mapping loaded modules to bundles


In order to make sure that the client loads all the modules that were rendered
server-side, we'll need to map them to the bundles that Webpack created.

This comes in two parts.

First we need Webpack to tell us which bundles each module lives inside. For

Import the ReactLoadablePlugin from react-loadable/webpack and include it
in your webpack config. Pass it a filename for where to store the JSON data
about our bundles.

  1. ``` js
  2. // webpack.config.js
  3. import { ReactLoadablePlugin } from 'react-loadable/webpack';

  4. export default {
  5.   plugins: [
  6.     new ReactLoadablePlugin({
  7.       filename: './dist/react-loadable.json',
  8.     }),
  9.   ],
  10. };
  11. ```

Then we'll go back to our server and use this data to convert our modules to
bundles.

To convert from modules to bundles, import the [getBundles](#getbundles)
method from react-loadable/webpack and the data from Webpack.

  1. ``` js
  2. import Loadable from 'react-loadable';
  3. import { getBundles } from 'react-loadable/webpack'
  4. import stats from './dist/react-loadable.json';

  5. app.get('/', (req, res) => {
  6.   let modules = [];

  7.   let html = ReactDOMServer.renderToString(
  8.     <Loadable.Capture report={moduleName => modules.push(moduleName)}>
  9.       <App/>
  10.     </Loadable.Capture>
  11.   );

  12.   let bundles = getBundles(stats, modules);

  13.   // ...
  14. });
  15. ```

We can then render these bundles into ``
  •       }).join('\n')}
  •       <script>window.main();</script>
  •     </body>
  •   </html>
  • `);
  • ```

  • Preloading ready loadable components on the client


    We can use the [Loadable.preloadReady()](#loadablepreloadready) method on the
    client to preload the loadable components that were included on the page.

    Like [Loadable.preloadAll()](#loadablepreloadall), it returns a promise,
    which on resolution means that we can hydrate our app.

    1. ``` js
    2. // src/entry.js
    3. import React from 'react';
    4. import ReactDOM from 'react-dom';
    5. import Loadable from 'react-loadable';
    6. import App from './components/App';

    7. window.main = () => {
    8.   Loadable.preloadReady().then(() => {
    9.     ReactDOM.hydrate(<App/>, document.getElementById('app'));
    10.   });
    11. };

    12. ```

      Now server-side rendering should work perfectly!



    API DOCS

    API Docs


    Loadable


    A higher-order component for dynamically loading a module before
    rendering it, a loading component is rendered
    while the module is unavailable.

    1. ``` js
    2. const LoadableComponent = Loadable({
    3.   loader: () => import('./Bar'),
    4.   loading: Loading,
    5.   delay: 200,
    6.   timeout: 10000,
    7. });
    8. ```

    This returns a LoadableComponent.

    Loadable.Map


    A higher-order component that allows you to load multiple resources in parallel.

    Loadable.Map's [opts.loader](#optsloader) accepts an object of functions, and
    needs a [opts.render](#optsrender) method.

    1. ``` js
    2. Loadable.Map({
    3.   loader: {
    4.     Bar: () => import('./Bar'),
    5.     i18n: () => fetch('./i18n/bar.json').then(res => res.json()),
    6.   },
    7.   render(loaded, props) {
    8.     let Bar = loaded.Bar.default;
    9.     let i18n = loaded.i18n;
    10.     return <Bar {...props} i18n={i18n}/>;
    11.   }
    12. });
    13. ```

    When using Loadable.Map the render() method's loaded param will be an
    object with the same shape as your loader.

    Loadable and Loadable.Map Options


    opts.loader


    A function returning a promise that loads your module.

    1. ``` js
    2. Loadable({
    3.   loader: () => import('./Bar'),
    4. });
    5. ```

    When using with [Loadable.Map](#loadablemap) this accepts an object of these
    types of functions.

    1. ``` js
    2. Loadable.Map({
    3.   loader: {
    4.     Bar: () => import('./Bar'),
    5.     i18n: () => fetch('./i18n/bar.json').then(res => res.json()),
    6.   },
    7. });
    8. ```

    When using with Loadable.Map you'll also need to pass a
    [opts.render](#optsrender) function.

    opts.loading


    A [LoadingComponent](#loadingcomponent) that renders while a module is
    loading or when it errors.

    1. ``` js
    2. Loadable({
    3.   loading: LoadingComponent,
    4. });
    5. ```

    This option is required, if you don't want to render anything, return null.

    1. ``` js
    2. Loadable({
    3.   loading: () => null,
    4. });
    5. ```

    opts.delay


    Time to wait (in milliseconds) before passing
    [props.pastDelay](#propspastdelay) to your [loading](#optsloading)
    component. This defaults to 200.

    1. ``` js
    2. Loadable({
    3.   delay: 200
    4. });
    5. ```


    opts.timeout


    Time to wait (in milliseconds) before passing
    [props.timedOut](#propstimedout) to your [loading](#optsloading) component.
    This is turned off by default.

    1. ``` js
    2. Loadable({
    3.   timeout: 10000
    4. });
    5. ```


    opts.render


    A function to customize the rendering of loaded modules.

    Receives loaded which is the resolved value of [opts.loader](#optsloader)
    and props which are the props passed to the
    [LoadableComponent](#loadablecomponent).

    1. ``` js
    2. Loadable({
    3.   render(loaded, props) {
    4.     let Component = loaded.default;
    5.     return <Component {...props}/>;
    6.   }
    7. });
    8. ```

    opts.webpack


    An optional function which returns an array of Webpack module ids which you can
    get with require.resolveWeak.

    1. ``` js
    2. Loadable({
    3.   loader: () => import('./Foo'),
    4.   webpack: () => [require.resolveWeak('./Foo')],
    5. });
    6. ```

    This option can be automated with the Babel Plugin.

    opts.modules


    An optional array with module paths for your imports.

    1. ``` js
    2. Loadable({
    3.   loader: () => import('./my-component'),
    4.   modules: ['./my-component'],
    5. });
    6. ```

    This option can be automated with the Babel Plugin.

    LoadableComponent


    This is the component returned by Loadable and Loadable.Map.

    1. ``` js
    2. const LoadableComponent = Loadable({
    3.   // ...
    4. });
    5. ```

    Props passed to this component will be passed straight through to the
    dynamically loaded component via [opts.render](#optsrender).

    LoadableComponent.preload()


    This is a static method on [LoadableComponent](#loadablecomponent) which can
    be used to load the component ahead of time.

    1. ``` js
    2. const LoadableComponent = Loadable({...});

    3. LoadableComponent.preload();
    4. ```

    This returns a promise, but you should avoid waiting for that promise to
    resolve to update your UI. In most cases it creates a bad user experience.


    LoadingComponent


    This is the component you pass to [opts.loading](#optsloading).

    1. ``` js
    2. function LoadingComponent(props) {
    3.   if (props.error) {
    4.     // When the loader has errored
    5.     return <div>Error! <button onClick={ props.retry }>Retry</button>div>;
    6.   } else if (props.timedOut) {
    7.     // When the loader has taken longer than the timeout
    8.     return <div>Taking a long time... <button onClick={ props.retry }>Retry</button>div>;
    9.   } else if (props.pastDelay) {
    10.     // When the loader has taken longer than the delay
    11.     return <div>Loading...</div>;
    12.   } else {
    13.     // When the loader has just started
    14.     return null;
    15.   }
    16. }

    17. Loadable({
    18.   loading: LoadingComponent,
    19. });
    20. ```


    props.error


    An Error object passed to [LoadingComponent](#loadingcomponent) when the
    [loader](#optsloader) has failed. When there is no error, null is
    passed.

    1. ``` js
    2. function LoadingComponent(props) {
    3.   if (props.error) {
    4.     return <div>Error!</div>;
    5.   } else {
    6.     return <div>Loading...</div>;
    7.   }
    8. }
    9. ```


    props.retry


    A function prop passed to [LoadingComponent](#loadingcomponent) when the
    [loader](#optsloader) has failed, used to retry loading the component.

    1. ``` js
    2. function LoadingComponent(props) {
    3.   if (props.error) {
    4.     return <div>Error! <button onClick={ props.retry }>Retry</button>div>;
    5.   } else {
    6.     return <div>Loading...</div>;
    7.   }
    8. }
    9. ```


    props.timedOut


    A boolean prop passed to [LoadingComponent](#loadingcomponent) after a set
    [timeout](#optstimeout).

    1. ``` js
    2. function LoadingComponent(props) {
    3.   if (props.timedOut) {
    4.     return <div>Taking a long time...</div>;
    5.   } else {
    6.     return <div>Loading...</div>;
    7.   }
    8. }
    9. ```


    props.pastDelay


    A boolean prop passed to [LoadingComponent](#loadingcomponent) after a set
    [delay](#optsdelay).

    1. ``` js
    2. function LoadingComponent(props) {
    3.   if (props.pastDelay) {
    4.     return <div>Loading...</div>;
    5.   } else {
    6.     return null;
    7.   }
    8. }
    9. ```


    Loadable.preloadAll()


    This will call all of the
    [LoadableComponent.preload](#loadablecomponentpreload) methods recursively
    until they are all resolved. Allowing you to preload all of your dynamic
    modules in environments like the server.

    1. ``` js
    2. Loadable.preloadAll().then(() => {
    3.   app.listen(3000, () => {
    4.     console.log('Running on http://localhost:3000/');
    5.   });
    6. });
    7. ```

    It's important to note that this requires that you declare all of your loadable
    components when modules are initialized rather than when your app is being
    rendered.

    Good:

    1. ``` js
    2. // During module initialization...
    3. const LoadableComponent = Loadable({...});

    4. class MyComponent extends React.Component {
    5.   componentDidMount() {
    6.     // ...
    7.   }
    8. }
    9. ```

    Bad:

    1. ``` js
    2. // ...

    3. class MyComponent extends React.Component {
    4.   componentDidMount() {
    5.     // During app render...
    6.     const LoadableComponent = Loadable({...});
    7.   }
    8. }
    9. ```

    Note: Loadable.preloadAll() will not work if you have more than one

    copy of react-loadable in your app.



    Loadable.preloadReady()


    Check for modules that are already loaded in the browser and call the matching
    [LoadableComponent.preload](#loadablecomponentpreload) methods.

    1. ``` js
    2. Loadable.preloadReady().then(() => {
    3.   ReactDOM.hydrate(<App/>, document.getElementById('app'));
    4. });
    5. ```


    Loadable.Capture


    A component for reporting which modules were rendered.

    Accepts a report prop which is called for every moduleName that is
    rendered via React Loadable.

    1. ``` js
    2. let modules = [];

    3. let html = ReactDOMServer.renderToString(
    4.   <Loadable.Capture report={moduleName => modules.push(moduleName)}>
    5.     <App/>
    6.   </Loadable.Capture>
    7. );

    8. console.log(modules);
    9. ```


    Babel Plugin


    Providing [opts.webpack](#optswebpack) and [opts.modules](#optsmodules) for
    every loadable component is a lot of manual work to remember to do.

    Instead you can add the Babel plugin to your config and it will automate it for
    you:

    1. ``` json
    2. {
    3.   "plugins": ["react-loadable/babel"]
    4. }
    5. ```

    Input

    1. ``` js
    2. import Loadable from 'react-loadable';

    3. const LoadableMyComponent = Loadable({
    4.   loader: () => import('./MyComponent'),
    5. });

    6. const LoadableComponents = Loadable.Map({
    7.   loader: {
    8.     One: () => import('./One'),
    9.     Two: () => import('./Two'),
    10.   },
    11. });
    12. ```

    Output

    1. ``` js
    2. import Loadable from 'react-loadable';
    3. import path from 'path';

    4. const LoadableMyComponent = Loadable({
    5.   loader: () => import('./MyComponent'),
    6.   webpack: () => [require.resolveWeak('./MyComponent')],
    7.   modules: [path.join(__dirname, './MyComponent')],
    8. });

    9. const LoadableComponents = Loadable.Map({
    10.   loader: {
    11.     One: () => import('./One'),
    12.     Two: () => import('./Two'),
    13.   },
    14.   webpack: () => [require.resolveWeak('./One'), require.resolveWeak('./Two')],
    15.   modules: [path.join(__dirname, './One'), path.join(__dirname, './Two')],
    16. });
    17. ```


    Webpack Plugin


    when rendering server-side, you'll need the React Loadable Webpack plugin 
    to provide you with a mapping of modules to bundles.

    1. ``` js
    2. // webpack.config.js
    3. import { ReactLoadablePlugin } from 'react-loadable/webpack';

    4. export default {
    5.   plugins: [
    6.     new ReactLoadablePlugin({
    7.       filename: './dist/react-loadable.json',
    8.     }),
    9.   ],
    10. };
    11. ```

    This will create a file (opts.filename) which you can import to map modules
    to bundles.


    getBundles


    A method exported by react-loadable/webpack for converting modules to
    bundles.

    1. ``` js
    2. import { getBundles } from 'react-loadable/webpack';

    3. let bundles = getBundles(stats, modules);
    4. ```




    FAQ

    FAQ


    How do I avoid repetition?


    Specifying the same loading component or delay every time you use
    Loadable() gets repetitive fast. Instead you can wrap Loadable with your
    own Higher-Order Component (HOC) to set default options.

    1. ``` js
    2. import Loadable from 'react-loadable';
    3. import Loading from './my-loading-component';

    4. export default function MyLoadable(opts) {
    5.   return Loadable(Object.assign({
    6.     loading: Loading,
    7.     delay: 200,
    8.     timeout: 10000,
    9.   }, opts));
    10. };
    11. ```

    Then you can just specify a loader when you go to use it.

    1. ``` js
    2. import MyLoadable from './MyLoadable';

    3. const LoadableMyComponent = MyLoadable({
    4.   loader: () => import('./MyComponent'),
    5. });

    6. export default class App extends React.Component {
    7.   render() {
    8.     return <LoadableMyComponent/>;
    9.   }
    10. }
    11. ```

    Unfortunately at the moment using wrapped Loadable breaks react-loadable/babel so in such case you have to add required properties (modules, webpack) manually.

    1. ``` js
    2. import MyLoadable from './MyLoadable';

    3. const LoadableMyComponent = MyLoadable({
    4.   loader: () => import('./MyComponent'),
    5.   modules: ['./MyComponent'],
    6.   webpack: () => [require.resolveWeak('./MyComponent')],
    7. });

    8. export default class App extends React.Component {
    9.   render() {
    10.     return <LoadableMyComponent/>;
    11.   }
    12. }
    13. ```

    How do I handle other styles .css or sourcemaps .map with server-side rendering?


    When you call [getBundles](#getbundles), it may return file types other than
    JavaScript depending on your Webpack configuration.

    To handle this, you should manually filter down to the file extensions that
    you care about:

    1. ``` js
    2. let bundles = getBundles(stats, modules);

    3. let styles = bundles.filter(bundle => bundle.file.endsWith('.css'));
    4. let scripts = bundles.filter(bundle => bundle.file.endsWith('.js'));

    5. res.send(`
    6.   doctype html>
    7.   <html lang="en">
    8.     <head>
    9.       ...
    10.       ${styles.map(style => {
    11.         return `<link href="/dist/${style.file}" rel="stylesheet"/>`
    12.       }).join('\n')}
    13.     </head>
    14.     <body>
    15.       <div id="app">${html}</div>
    16.       <script src="/dist/main.js"></script>
    17.       ${scripts.map(script => {
    18.         return `<script src="/dist/${script.file}"></script>`
    19.       }).join('\n')}
    20.     </body>
    21.   </html>
    22. `);
    23. ```