[React] Asynchronously Load webpack Bundles through Code-splitting and React Suspense

One approach to building high performance applications with webpack is to take advantage of code-splitting to only load the needed JavaScript on initial load and asynchronously load additional JavaScript bundles when needed. In this lesson, we'll create add some code-splitting to our placeholder application and configure our project to support the dynamic import() syntax.

 

Install:

npm i -D @babel/plugin-syntax-dynamic-import

 

Add plugin into webpack config:

plugins: [
      ...
      '@babel/plugin-syntax-dynamic-import'
]

 

What we want to do is lazy loading a Warning component, and also utilize the code spliting from webpack:

Here is the component we want to lazy load in:

import React from 'react'

export default () => <span className={'warning'}>Take it easy!</span>

 

App.js:

import React from 'react'
import {hot} from 'react-hot-loader'

const Warning = React.lazy(() => import('./Warning'))

class App extends React.Component {
  state = {
    count: 0
  }

  increment = () => {
    this.setState(state => ({count: state.count + 1}))
  }

  decrement = () => {
    this.setState(state => ({count: state.count - 1}))
  }

  render() {
    const {count} = this.state
    return (
      <div>
        <h1>Hello World.</h1>
        <h2 className={count > 10 ? 'warning' : null}>
          Count: {count}
        </h2>
        <button onClick={this.increment}>+</button>
        <button onClick={this.decrement}>-</button>
        {count > 10 ?
          <React.Suspense fallback={null}>
            <Warning />
          </React.Suspense>
          : null}
      </div>
    )
  }
}

export default hot(module)(App)

 

We use React.lazy + dynamic import syntax:

const Warning = React.lazy(() => import('./Warning'))

 

Then we use lazy loaded Warning component with React.Suspense:

<React.Suspense fallback={null}>
   <Warning />
</React.Suspense>

'fallback' take a jsx element which will be shown when doing the lazy loading. 

 

So what if the Warning component failed to load?

Here is where Error Boundries comes in to play:

class MyErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    // Update state so the next render will show the fallback UI.
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    // You can also log the error to an error reporting service
    logErrorToMyService(error, info);
  }

  render() {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children; 
  }
}

export defualt MyErrorBoundry;

 

Then wrap your Suspense component with boundry:

<MyErrorBoundary>
    <React.Suspense fallback={null}>
         <Warning />
     </React.Suspense>
</MyErrorBoundary>

 

Now we can get benifits from lazy loading and also safety from the boundry

 

More about Code splitting.

 

posted @ 2019-03-20 16:20  Zhentiw  阅读(288)  评论(0编辑  收藏  举报