Browse Source
* Init Code-Splitting docs * Fix <Route path="/"> to use exact * Fix code splitting typos * Fix note formatting on the website * Minor tweaks De-emphasize webpack, mention Next and Gatsbymain
committed by
Dan Abramov
2 changed files with 194 additions and 1 deletions
@ -0,0 +1,191 @@ |
|||||
|
--- |
||||
|
id: code-splitting |
||||
|
title: Code-Splitting |
||||
|
permalink: docs/code-splitting.html |
||||
|
--- |
||||
|
|
||||
|
## Bundling |
||||
|
|
||||
|
Most React apps will have their files "bundled" using tools like |
||||
|
[Webpack](https://webpack.js.org/) or [Browserify](http://browserify.org/). |
||||
|
Bundling is the process of following imported files and merging them into a |
||||
|
single file: a "bundle". This bundle can then be included on a webpage to load |
||||
|
an entire app at once. |
||||
|
|
||||
|
#### Example |
||||
|
|
||||
|
**App:** |
||||
|
|
||||
|
```js |
||||
|
// app.js |
||||
|
import { add } from './math.js'; |
||||
|
|
||||
|
console.log(add(16, 26)); // 42 |
||||
|
``` |
||||
|
|
||||
|
```js |
||||
|
// math.js |
||||
|
export function add(a, b) { |
||||
|
return a + b; |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
**Bundle:** |
||||
|
|
||||
|
```js |
||||
|
function add(a, b) { |
||||
|
return a + b; |
||||
|
} |
||||
|
|
||||
|
console.log(add(16, 26)); // 42 |
||||
|
``` |
||||
|
|
||||
|
> Note: |
||||
|
> |
||||
|
> Your bundles will end up looking a lot different than this. |
||||
|
|
||||
|
If you're using [Create React App](https://github.com/facebookincubator/create-react-app), [Next.js](https://github.com/zeit/next.js/), [Gatsby](https://www.gatsbyjs.org/), or a similar tool you will have a Webpack setup out of the box to bundle your |
||||
|
app. |
||||
|
|
||||
|
If you aren't, you'll need to setup bundling yourself. For example, see the |
||||
|
[Installation](https://webpack.js.org/guides/installation/) and |
||||
|
[Getting Started](https://webpack.js.org/guides/getting-started/) guides on the |
||||
|
Webpack docs. |
||||
|
|
||||
|
## Code Splitting |
||||
|
|
||||
|
Bundling is great, but as your app grows, your bundle will grow too. Especially |
||||
|
if you are including large third-party libraries. You need to keep an eye on |
||||
|
the code you are including in your bundle so that you don't accidentally make |
||||
|
it so large that your app takes a long time to load. |
||||
|
|
||||
|
But if your app keeps growing, eventually you'll end up with a large bundle. So |
||||
|
it's good to get ahead of the problem and start "splitting" your bundle. |
||||
|
[Code-Splitting](https://webpack.js.org/guides/code-splitting/) is a feature |
||||
|
of bundlers like Webpack and Browserify (via |
||||
|
[factor-bundle](https://github.com/browserify/factor-bundle)) which can create |
||||
|
multiple bundles that can be dynamically loaded at runtime. |
||||
|
|
||||
|
Code-splitting your app can help you "lazy-load" just the things that are |
||||
|
currently needed by the user, which can dramatically improve the performance of |
||||
|
your app. Overall you haven't reduced the amount of code in your app, but |
||||
|
you've avoided loading code that the user may never need. |
||||
|
|
||||
|
## `import()` |
||||
|
|
||||
|
The best way to introduce code-splitting into your app is through the dynamic |
||||
|
`import()` syntax. |
||||
|
|
||||
|
**Before:** |
||||
|
|
||||
|
```js |
||||
|
import { add } from './math'; |
||||
|
|
||||
|
console.log(add(16, 26)); |
||||
|
``` |
||||
|
|
||||
|
**After:** |
||||
|
|
||||
|
```js |
||||
|
import("./math").then(math => { |
||||
|
console.log(math.add(16, 26)); |
||||
|
}); |
||||
|
``` |
||||
|
|
||||
|
> Note: |
||||
|
> |
||||
|
> The dynamic `import()` syntax is a ECMAScript (JavaScript) |
||||
|
> [proposal](https://github.com/tc39/proposal-dynamic-import) not currently |
||||
|
> accepted into the language standard. It is expected to be accepted within the |
||||
|
> near future. |
||||
|
|
||||
|
When Webpack comes across this syntax, it automatically start code-splitting |
||||
|
your app. If you're using Create React App, this is already configured for you |
||||
|
and you can [start using it](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#code-splitting) immediately. It's also supported |
||||
|
out of the box in [Next.js](https://github.com/zeit/next.js/#dynamic-import). |
||||
|
|
||||
|
If you're setting up Webpack yourself, you'll probably want to read Webpack's |
||||
|
[guide on code splitting](https://webpack.js.org/guides/code-splitting/). Your Webpack config should look vaguely [like this](https://gist.github.com/gaearon/ca6e803f5c604d37468b0091d9959269). |
||||
|
|
||||
|
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 Loadable |
||||
|
|
||||
|
[React Loadable](https://github.com/thejameskyle/react-loadable) provides you |
||||
|
with a nice API for introducing code splitting into your app wherever you |
||||
|
render a component. |
||||
|
|
||||
|
**Before:** |
||||
|
|
||||
|
```js |
||||
|
import OtherComponent from './OtherComponent'; |
||||
|
|
||||
|
const MyComponent = () => ( |
||||
|
<OtherComponent/> |
||||
|
); |
||||
|
``` |
||||
|
|
||||
|
**After:** |
||||
|
|
||||
|
```js |
||||
|
import Loadable from 'react-loadable'; |
||||
|
|
||||
|
const LoadableOtherComponent = Loadable({ |
||||
|
loader: () => import('./OtherComponent'), |
||||
|
loading: () => <div>Loading...</div>, |
||||
|
}); |
||||
|
|
||||
|
const MyComponent = () => ( |
||||
|
<LoadableOtherComponent/> |
||||
|
); |
||||
|
``` |
||||
|
|
||||
|
React Loadable helps you create |
||||
|
[loading states](https://github.com/thejameskyle/react-loadable#creating-a-great-loading-component), |
||||
|
[error states](https://github.com/thejameskyle/react-loadable#loading-error-states), |
||||
|
[timeouts](https://github.com/thejameskyle/react-loadable#timing-out-when-the-loader-is-taking-too-long), |
||||
|
[preloading](https://github.com/thejameskyle/react-loadable#preloading), and |
||||
|
more. It can even help you [server-side](https://github.com/thejameskyle/react-loadable#------------server-side-rendering) |
||||
|
render 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 |
||||
|
want to make sure you choose places that will split bundles evenly, but not be |
||||
|
terribly interuptive to the users of your app. |
||||
|
|
||||
|
A good place is to start is with routes. Most people on the web are used to |
||||
|
page transitions taking some amount of time to load. You also tend to be |
||||
|
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 |
||||
|
[React Loadable](https://github.com/thejameskyle/react-loadable). |
||||
|
|
||||
|
```js |
||||
|
import { BrowserRouter as Router, Route } from 'react-router-dom'; |
||||
|
import Loadable from 'react-loadable'; |
||||
|
|
||||
|
const Loading = () => <div>Loading...</div>; |
||||
|
|
||||
|
const Home = Loadable({ |
||||
|
loader: () => import('./routes/Home'), |
||||
|
loading: Loading, |
||||
|
}); |
||||
|
|
||||
|
const About = Loadable({ |
||||
|
loader: () => import('./routes/About'), |
||||
|
loading: Loading, |
||||
|
}); |
||||
|
|
||||
|
const App = () => ( |
||||
|
<Router> |
||||
|
<Route exact path="/" component={Home}/> |
||||
|
<Route path="/about" component={About}/> |
||||
|
</Router> |
||||
|
); |
||||
|
``` |
Loading…
Reference in new issue