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.