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.
- "I'm obsessed with this right now: CRA with React Router v4 and react-loadable. Free code splitting, this is so easy."
- "Webpack 2 upgrade & react-loadable; initial load from 1.1mb to 529kb in under 2 hours. Immense."
- "Oh hey - using loadable component I knocked 13K off my initial load. Easy win!"
- "Had a look and its awesome. shaved like 50kb off our main bundle."
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.
Loadable.MapOne 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')
})
})
opts.LoadingComponent → opts.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.timeoutVue.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 flushWebpackRequireWeakIdsThis 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