* Document React.lazy
Suspense is documented here since it's the only built-in way so far to
use it. In the future it'll likely be documented on its own more like
Error boundaries.
This hoists React.lazy as the primary way to do code splitting. However,
before getting into it we keep the recommendation to use react-loadable
for server-side rendered apps since Suspense is not yet ready for the
server.
* Tweaks
* Tweaks
* nits
@ -111,46 +111,107 @@ If you're setting up Webpack yourself, you'll probably want to read Webpack's
When using [Babel](http://babeljs.io/), you'll need to make sure that Babel can
parse the dynamic import syntax but is not transforming it. For that you will need [babel-plugin-syntax-dynamic-import](https://yarnpkg.com/en/package/babel-plugin-syntax-dynamic-import).
## Libraries
## `React.lazy`
### React Loadable
> Note:
>
> `React.lazy` and Suspense is not yet available for server-side rendering. If you want to do code-splitting in a server rendered app, we still recommend [React Loadable](https://github.com/thejameskyle/react-loadable). It has a nice [guide for bundle splitting with server-side rendering](https://github.com/thejameskyle/react-loadable#------------server-side-rendering).
This will automatically load the bundle containing the `OtherComponent` when this component gets rendered.
`React.lazy` takes a function that must call a dynamic `import()`. This must return a `Promise` which resolves to a module with a `default` export containing a React component.
### Suspense
If the module containing the `OtherComponent` is not yet loaded by the time `MyComponent` renders, we must show some fallback content while we're waiting for it to load - such as a loading indicator. This is done using the `Suspense` component.
The `fallback` prop accepts any React elements that you want to render while waiting for the component to load. You can place the `Suspense` component anywhere above the lazy component. You can even wrap multiple lazy components with a single `Suspense` component.
If the other module fails to load (for example, due to network failure), it will trigger an error. You can handle these errors to show a nice user experience and manage recovery with [Error Boundaries](/docs/error-boundaries.html). Once you've created your Error Boundary, you can use it anywhere above your lazy components to display an error state when there's a network error.
[preloading](https://github.com/thejameskyle/react-loadable#preloading), and
more. It can even help you [server-side render](https://github.com/thejameskyle/react-loadable#------------server-side-rendering) an app with lots of code-splitting.
## Route-based code splitting
Deciding where in your app to introduce code splitting can be a bit tricky. You
@ -163,31 +224,44 @@ re-rendering the entire page at once so your users are unlikely to be
interacting with other elements on the page at the same time.
Here's an example of how to setup route-based code splitting into your app using
libraries like [React Router](https://reacttraining.com/react-router/) and
libraries like [React Router](https://reacttraining.com/react-router/) with `React.lazy`.
```js
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Loadable from 'react-loadable';
import React, { Suspense, lazy } from 'react';
const Loading = () => <div>Loading...</div>;
const Home = Loadable({
loader: () => import('./routes/Home'),
loading: Loading,
});
const About = Loadable({
loader: () => import('./routes/About'),
loading: Loading,
});
const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));
const App = () => (
<Router>
<Switch>
<Routeexactpath="/"component={Home}/>
<Routepath="/about"component={About}/>
</Switch>
<Suspensefallback={<div>Loading...</div>}>
<Switch>
<Routeexactpath="/"component={Home}/>
<Routepath="/about"component={About}/>
</Switch>
</Suspense>
</Router>
);
```
## Named Exports
`React.lazy` currently only supports default exports. If the module you want to import uses named exports, you can create an intermediate module that reexports it as the default. This ensures that treeshaking keeps working and that you don't pull in unused components.
```js
// ManyComponents.js
export const MyComponent = /* ... */;
export const MyUnusedComponent = /* ... */;
```
```js
// MyComponent.js
export { MyComponent as default } from "./ManyComponents.js";