React Loadable 4.0

A few months ago I introduced React Loadable as a way to push a component-centric code splitting model. 2,300 GitHub stars later, several other ecosystems have adopted this model:

People have lots of different takes on API design, but from what I've heard the results have been great.

Using dynamic import()'s and a component-centric code splitting model, you can cut down the size of your app super quick.

I'm doing a lot of research right now on how we can take this model even further by automatically optimizing bundles. In order to do that, we'll have to first understand our imports a lot better. Especially timing information about our imports.

In addition to a number of other changes, React Loadable 4 includes some changes that are in preparation for further optimization.

The changes in React Loadable 4 should make it much more convienient to use. I hope you all like it.

New in 4.0

Loadable.Map

One thing that often caused people to trip up was how to load multiple resources in parallel. While it was possible before, React Loadable 4 adds a new API to help you out with this.

Loadable.Map accepts an object as a loader instead of a function. You then need to specify a render() method to stitch everything together.

Loadable.Map({
  loader: {
    Component: () => import('./my-component'),
    translations: () => fetch('./i18n/foo.json').then(...),
  },
  render(loaded, props) {
    let Component = loaded.Component.default;
    let i18n = loaded.translations;
    return <Component {...props} translations={i18n}/>;
  }
});

import-inspector

In previous versions of React Loadable there were special options (serverSideRequirePath and webpackRequireWeakId) to allow loadable components to render synchronously when the components were available on either the client or server.

This API turned out to be a real hassle to automate using a Babel plugin and didn't allow for a number of future experiments. So it has been replaced with a new library import-inspector. It looks like this:

import {report} from 'import-inspector';
import path from 'path';

Loadable({
  loader: () => report(import('./my-component'), {
    serverSideRequirePath: path.join(__dirname, './my-component'),
    webpackRequireWeakId: () => require.resolveWeak('./my-component')
  })
})

Instead of using this directly, you can automate the manual configuration using:

babel-plugin-import-inspector

The react-loadable/babel plugin has been replaced in favor of babel-plugin-import-inspector which is much more reliable and works everywhere.

Install

yarn add import-inspector
yarn add --dev babel-plugin-import-inspector

.babelrc

{
  "plugins": [
    ["import-inspector", {
      "serverSideRequirePath": true,
      "webpackRequireWeakId": true
    }]
  ]
}

Input

Loadable({
  loader: () => import('./my-component')
})

Output

import {report} from 'import-inspector';
import path from 'path';

Loadable({
  loader: () => report(import('./my-component'), {
    serverSideRequirePath: path.join(__dirname, './my-component'),
    webpackRequireWeakId: () => require.resolveWeak('./my-component')
  })
})

API Changes

opts.LoadingComponentopts.loading

LoadingComponent was unnecessarily verbose, loading is better.

opts.render

This replaces opts.resolveModule to give more control over the actual rendering of the component.

const LoadableComponent = Loadable({
  loader: () => import('./my-component'),
  loading: Loading,
  render(loaded, props) {
    let Component = loaded.namedExport;
    return <Component {...props}/>;
  }
});

opts.timeout

Vue.js added this in their implementation. I liked it so I stole it.

Your loading Component will now receive an additional prop timedOut which will be true after the set timeout expires.

function Loading(props) {
  if (props.timedOut) {
    return <div>Timed Out</div>;
  } else {
    return <div>Loading...</div>;
  }
}

const LoadableComponent = Loadable({
  // ...
  loading: Loading,
  timeout: 10000
});

flushServerSideRequirePaths and flushWebpackRequireWeakIds

This functionality is no longer necessary when using import-inspector. Instead you can use import-inspector to watch which imports are reported (example).


That about covers it. For a full change log, see the 4.0 pull request.

As always, be sure to give React Loadable a star on GitHub and be sure to download this shit:

yarn add react-loadable