Skip to content

Commit d333f27

Browse files
committed
Updates dependencies and documentation.
1 parent 9962ee7 commit d333f27

File tree

3 files changed

+213
-363
lines changed

3 files changed

+213
-363
lines changed

README.md

+76-68
Original file line numberDiff line numberDiff line change
@@ -1,134 +1,133 @@
1-
# react-async-component 😴
1+
# react-async-component 📬
22

3-
Create Components that resolve asynchronously, with support for server side rendering and code splitting.
3+
Resolve components asynchronously, with support for code splitting and advanced server side rendering use cases.
44

55
[![npm](https://img.shields.io/npm/v/react-async-component.svg?style=flat-square)](http://npm.im/react-async-component)
66
[![MIT License](https://img.shields.io/npm/l/react-async-component.svg?style=flat-square)](http://opensource.org/licenses/MIT)
77
[![Travis](https://img.shields.io/travis/ctrlplusb/react-async-component.svg?style=flat-square)](https://travis-ci.org/ctrlplusb/react-async-component)
88
[![Codecov](https://img.shields.io/codecov/c/github/ctrlplusb/react-async-component.svg?style=flat-square)](https://codecov.io/github/ctrlplusb/react-async-component)
99

1010
```jsx
11-
const AsyncProduct = createAsyncComponent({
12-
// 👇 Webpack 2 code splitting API
13-
resolve: () => import('./components/Product'))
11+
const Product = asyncComponent({
12+
resolve: () => System.import('./AsyncProduct'),
13+
LoadingComponent: ({ productId }) => <div>Loading {productId}</div>,
14+
ErrorComponent: ({ error }) => <div>{error.message}</div>
1415
});
1516

16-
<AsyncProduct productId={1} /> // 🚀
17+
<Product productId={1} /> // 🚀
1718
```
1819

1920
## TOCs
2021

2122
- [Introduction](#introduction)
23+
- [Features](#features)
2224
- [Examples](#examples)
23-
- [Browser Only Application](#browser-only-application)
24-
- [Server Side Rendering Application](#server-side-rendering-application)
25-
- [Using Loading Components](#using-loading-components)
25+
- [Standard Usage](#standard-usage)
26+
- [Using a LoadingComponent](#using-a-loadingcomponent)
27+
- [Using an ErrorComponent](#using-an-errorcomponent)
2628
- [Webpack 1/2 `require.ensure` Code Splitting](#webpack-12-requireensure-code-splitting)
2729
- [Webpack 2 `import` / `System.import` Code Splitting](#webpack-2-import--systemimport-code-splitting)
28-
- [Defer Loading to the Client/Browser](#defer-loading-to-the-clientbrowser)
2930
- [API](#api)
3031
- [createAsyncComponent(config)](#createasynccomponentconfig)
3132
- [withAsyncComponents(element)](#withasynccomponentselement)
32-
- [Important Information for using in Server Side Rendering Applications](#important-information-for-using-in-server-side-rendering-applications)
33+
- [Server Side Rendering](#server-side-rendering)
34+
- [Defer Loading to the Client/Browser](#defer-loading-to-the-clientbrowser)
35+
- [Important Information](#important-information)
3336
- [SSR AsyncComponent Resolution Process](#ssr-asynccomponent-resolution-process)
3437
- [SSR Performance Optimisation](#ssr-performance-optimisation)
3538
- [Warnings](#warnings)
3639
- [FAQs](#faqs)
3740

3841
## Introduction
3942

40-
This library is an evolution of [`code-split-component`](https://github.com/ctrlplusb/code-split-component). Unlike `code-split-component` this library does not require that you use either Webpack or Babel. Instead it provides you a pure Javascript/React API which has been adapted in a manner to make it generically useful for lazy-loaded Components, with support for modern code splitting APIs (e.g `import()`, `System.import`, `require.ensure`).
43+
This library does not require that you use either Webpack or Babel. Instead it provides you a generic and "pure" Javascript/React API which allows for the expression of lazy-loaded Components. It's `Promise`-based API naturally allows you to take advantage of modern code splitting APIs (e.g `import()`, `System.import`, `require.ensure`).
44+
45+
## Features
46+
47+
- Supports _any_ major code splitting API.
48+
- Show a `LoadingComponent` until your component is resolved.
49+
- Show an `ErrorComponent` if your component resolution fails.
50+
- Prevents flash-of-content by tracking already resolved Components.
51+
- Full server side rendering support, allowing client side state rehydration, and avoiding React checksum errors.
52+
- Uses the generalised [`react-async-bootstrapper`](https://github.com/ctrlplusb/react-async-bootstrapper) allowing you to optimally integrate with other async pre-loader libraries, such as [`react-jobs`](https://github.com/ctrlplusb/react-jobs) for your async data loading needs.
4153

4254
## Demo
4355

4456
You can see a "live" version [here](https://react-universally.now.sh/). This is a deployment of the "next" branch of ["React, Universally"](https://github.com/ctrlplusb/react-universally). Open the network tab and then click the menu items to see the asynchronous component resolving in action.
4557

4658
## Examples
4759

48-
The below examples show off a full workflow of using the `createAsyncComponent` and `withAsyncComponents` helpers.
60+
The examples below make use of the `System.import` API supported by Webpack v2 which provides us with code splitting on our asynchronous components.
4961

50-
In some of the examples below we are going to be making use of the `System.import` API supported by Webpack v2 which provides us with code splitting on our asynchronous components.
62+
### Standard Usage
5163

52-
### Browser Only Application
64+
This is how you would use `react-async-component` in a "standard" React application (i.e. browser side only).
5365

54-
This is how you would use `react-async-component` in a "browser only" React application.
55-
56-
Firsly you need to wrap the rendering of your application with our helper:
66+
Firsly you need to wrap the rendering of your application with the `AsyncComponentProvider`:
5767

5868
```jsx
5969
import React from 'react';
60-
import { render } from 'react-dom';
61-
import { withAsyncComponents } from 'react-async-component'; // 👈
70+
import ReactDOM from 'react-dom';
71+
import { AsyncComponentProvider } from 'react-async-component'; // 👈
6272
import MyApp from './components/MyApp';
6373

64-
const app = <MyApp />;
65-
66-
// 👇 run helper on your app.
67-
withAsyncComponents(app)
68-
// 👇 and you get back a result object.
69-
.then((result) => {
70-
const {
71-
// ❗️ The result includes a decorated version of your app
72-
// that will allow your application to use async components
73-
// in an efficient manner.
74-
appWithAsyncComponents
75-
} = result;
74+
const app = (
75+
// 👇
76+
<AsyncComponentProvider>
77+
<MyApp />
78+
</AsyncComponentProvider>
79+
);
7680

77-
// Now you can render the app.
78-
render(appWithAsyncComponents, document.getElementById('app'));
79-
});
81+
ReactDOM.render(app, document.getElementById('app'));
8082
```
8183

8284
Now, let's create an async `Product` component that will be used within your application. I recommend that you use the following folder/file for your components:
8385

8486
```
85-
|- AsyncProduct
87+
|- Product
8688
|- index.js
87-
|- Product.js
89+
|- AsyncProduct.js
8890
```
8991

90-
The `./AsyncProduct/Product.js` could have the following example contents:
92+
__`./Product/index.js`__:
9193

92-
```jsx
93-
import React from 'react';
94+
```js
95+
import { createAsyncComponent } from 'react-async-component';
9496

95-
export default function Product({ params }) {
96-
return <div>You are viewing product {params.productId}</div>;
97-
}
97+
// Create an async component 👇
98+
export default createAsyncComponent({
99+
resolve: () => System.import('./AsyncProduct')
100+
// That resolves to 👆
101+
});
98102
```
99103

100-
The `./AsyncProduct/index.js` could have then following contents:
101-
102-
```js
103-
import { createAsyncComponent } from 'react-async-component'; // 👈
104+
__`./Product/AsyncProduct.js`__
104105

105-
// 👇 create an async component
106-
const AsyncProduct = createAsyncComponent({
107-
resolve: () => System.import('./Product')
108-
                // 👆 Webpack's code splitting API
109-
});
106+
```jsx
107+
import React from 'react';
110108

111-
export default AsyncProduct;
109+
export default function Product({ productId }) {
110+
return <div>You are viewing product {productId}</div>;
111+
}
112112
```
113113

114-
Now, you can simply import `AsyncProduct` anywhere in your application and not have to worry about having to call `createAsyncComponent` again.
114+
Now, you can simply import `Product` anywhere in your application and not have to worry about having to call `createAsyncComponent` again.
115115

116-
For example, let's image the following implementation of your `MyApp` component, which uses the React Router v4 `Match` API.
116+
For example:
117117

118118
```jsx
119119
import React from 'react';
120-
import { Match } from 'react-router';
121-
import AsyncProduct from './AsyncProduct';
120+
import Product from './components/Product';
122121

123-
const Root = () => (
124-
<div className="container">
122+
const MyApp = () => (
123+
<div>
125124
<h1>Welcome to My App</h1>
126-
127-
<Match exactly pattern="/products/:productId" component={AsyncProduct} />
125+
// 👇 Use as "normal"
126+
<Product productId={1337} />
128127
</div>
129128
);
130129

131-
export default Root;
130+
export default MyApp;
132131
```
133132

134133
🚀
@@ -143,18 +142,27 @@ Let's imagine the following Express middleware (you could use any HTTP server of
143142

144143
```jsx
145144
import React from 'react';
146-
import { withAsyncComponents } from 'react-async-component'; // 👈
145+
import {
146+
asyncBootstrapper,
147+
AsyncComponentProvider,
148+
createContext
149+
} from 'react-async-component'; // 👈
147150
import { renderToString } from 'react-dom/server';
148151
import serialize from 'serialize-javascript';
149152
import MyApp from './shared/components/MyApp';
150153

151154
export default function expressMiddleware(req, res, next) {
152-
const app = <MyApp />;
155+
// Create an execution context for our provider, this grants
156+
// 👇 us the ability to tap into the state.
157+
const execContext = createExecContext();
158+
159+
// 👇 Ensure you wrap your application with the provider.
160+
const app = (
161+
<MyApp />
162+
);
153163

154-
// 👇 run helper on your app.
155-
withAsyncComponents(app)
156-
// 👇 and you get back a result object.
157-
.then((result) => {
164+
// 👇 This makes sure we first resolve any async components before the render
165+
asyncBootstrapper(app).then(() => {
158166
const {
159167
// ❗️ The result includes a decorated version of your app
160168
// that will have the async components initialised for

package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,14 @@
6565
"babel-core": "6.24.0",
6666
"babel-eslint": "7.1.1",
6767
"babel-jest": "19.0.0",
68-
"babel-loader": "6.4.0",
68+
"babel-loader": "6.4.1",
6969
"babel-polyfill": "6.23.0",
70-
"babel-preset-env": "1.2.1",
70+
"babel-preset-env": "1.2.2",
7171
"babel-preset-latest": "6.24.0",
7272
"babel-preset-react": "6.23.0",
7373
"babel-preset-stage-3": "6.22.0",
7474
"babel-register": "6.24.0",
75-
"codecov": "2.0.1",
75+
"codecov": "2.0.2",
7676
"cross-env": "3.2.4",
7777
"enzyme": "2.7.1",
7878
"enzyme-to-json": "1.5.0",

0 commit comments

Comments
 (0)