From 615c660245ea0b2c95b76c3ef8ffec70bed88ad3 Mon Sep 17 00:00:00 2001 From: James Kyle Date: Fri, 5 Jan 2018 08:09:29 +1100 Subject: [PATCH] Init Code-Splitting docs (#348) * Init Code-Splitting docs * Fix to use exact * Fix code splitting typos * Fix note formatting on the website * Minor tweaks De-emphasize webpack, mention Next and Gatsby --- content/docs/code-splitting.md | 191 +++++++++++++++++++++++++++++++++ content/docs/nav.yml | 4 +- 2 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 content/docs/code-splitting.md diff --git a/content/docs/code-splitting.md b/content/docs/code-splitting.md new file mode 100644 index 00000000..6472dfdd --- /dev/null +++ b/content/docs/code-splitting.md @@ -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 = () => ( + +); +``` + +**After:** + +```js +import Loadable from 'react-loadable'; + +const LoadableOtherComponent = Loadable({ + loader: () => import('./OtherComponent'), + loading: () =>
Loading...
, +}); + +const MyComponent = () => ( + +); +``` + +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 = () =>
Loading...
; + +const Home = Loadable({ + loader: () => import('./routes/Home'), + loading: Loading, +}); + +const About = Loadable({ + loader: () => import('./routes/About'), + loading: Loading, +}); + +const App = () => ( + + + + +); +``` diff --git a/content/docs/nav.yml b/content/docs/nav.yml index c10bf60d..d1fdd5b3 100644 --- a/content/docs/nav.yml +++ b/content/docs/nav.yml @@ -70,6 +70,8 @@ title: Integrating with Other Libraries - id: accessibility title: Accessibility + - id: code-splitting + title: Code-Splitting - title: Reference items: - id: react-api @@ -120,4 +122,4 @@ - id: faq-structure title: File Structure - id: faq-internals - title: Virtual DOM and Internals \ No newline at end of file + title: Virtual DOM and Internals