Let's modify our routing application—even if it's quite small!—to try out code splitting.
First, let's see what our main code will look like:
// Source file: src/App.splitting.js
/* @flow */
/* eslint-disable */
import React, { Component } from "react";
import { BrowserRouter, Switch, Route, Link } from "react-router-dom";
import {
AsyncAlpha,
AsyncBravo,
AsyncCharlie,
AsyncZulu,
AsyncHelp
} from "./splittingApp";
const Home = () => <h1>Home Sweet Home</h1>;
const Error404 = () => <h1>404 Error!</h1>;
class App extends Component<{}> {
render() {
return (
<BrowserRouter>
<div>
<header>
<nav>
<Link to="/">Home</Link>
<Link to="/alpha">Alpha...</Link>
<Link to="/bravo">Bravo...</Link>
<Link to="/charlie">Charlie...</Link>
<Link to="/wrong">...Wrong...</Link>
<Link to="/zulu">Zulu</Link>
<Link to="/help">Help</Link>
</nav>
</header>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/help" component={AsyncHelp} />
<Route path="/alpha" component={AsyncAlpha} />
<Route path="/bravo" component={AsyncBravo} />
<Route path="/charlie" component={AsyncCharlie}
/>
<Route path="/zulu" component={AsyncZulu} />
<Route component={Error404} />
</Switch>
</div>
</BrowserRouter>
);
}
}
export default App;
We have separated the Alpha, Bravo, and other components so that we can load them dynamically. Seeing the code for one of them will be enough:
// Source file: src/splittingApp/alpha.component.js
/* @flow */
import React from "react";
const Alpha = () => <h1>Alpha</h1>;
export default Alpha;
But what about AsyncAlpha, AsyncBravo, and the rest? These components are dynamically loaded versions of their normal counterparts, which we can get using react-loadable:
// Source file: src/splittingApp/alpha.loadable.js
/* @flow */
import Loadable from "react-loadable";
import { LoadingStatus } from "./loadingStatus.component";
export const AsyncAlpha = Loadable({
loader: () => import("./alpha.component"),
loading: LoadingStatus
});
The AsyncAlpha component can be loaded dynamically, and while it's being loaded, its contents will be provided by the LoadingStatus component; you can make it as fancy as you want but I went with a very simple thing:
// Source file: src/splittingApp/loadingStatus.component.js
/* @flow */
import React from "react";
import PropTypes from "prop-types";
export class LoadingStatus extends React.Component<{
isLoading: boolean,
error: boolean
}> {
static propTypes = {
isLoading: PropTypes.bool,
error: PropTypes.bool
};
render() {
if (this.props.isLoading) {
return <div>Loading...</div>;
} else if (this.props.error) {
return <div>ERROR: the component could not be loaded.</div>;
} else {
return null;
}
}
}
So, now that we know how we can get any component to load dynamically, let's see how it works.