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.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')
})
})
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.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