React third-party component 1 (use of Router for routing management ⑤load on demand-next)

React third-party component 1 (use of Router for routing management ⑤load on demand-next)

This tutorial has a total of 6 articles, one updated daily, please follow us! You can enter the historical news to view the previous articles, and stay tuned for our new articles!

1. React third-party component 1 (use of Router for routing management ① simple to use) ---2018.01.22

2. React third-party component 1 (use of Router for routing management ②multi-level jump and redirection) ---2018.01.23

3. React third-party component 1 (Use of Router for routing management ③passing parameters) ---2018.01.24

4. React third-party component 1 (use of Router for routing management ④load on demand-top) ---2018.01.25

5. React third-party component 1 (use of Router for routing management ⑤load on demand-next) ---2018.01.26

Development environment: Windows 8, node v8.9.1, npm 5.5.1, WebStorm 2017.2.2

If we have more routes, such as a single-page application, there may be dozens of routes! So the first load to pull the entire js back is actually a bit wasteful, and it also affects the speed. All we have to achieve on-demand loading is to split the js package and get the js package of which route is requested!

So how to split it! This is what we are going to talk about today!

We have made some preparations for the last lesson. In this lesson, we need to separate demo1 and demo2 under the demo page!

We start to split the action!

1. Install dependencies first

npm i -D bundle-loader

2. Create a new Bundle.jsx

In app -> component -> common directory

import React, {Component} from'react'

class Bundle extends Component {
    state = {
       //short for "module" but that's a keyword in js, so "mod"
        mod: null
    }

    componentWillMount() {
        this.load(this.props)
    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.load !== this.props.load) {
            this.load(nextProps)
        }
    }

    load(props) {
        this.setState({
            mod: null
        })
        props.load((mod) => {
            this.setState({
               //handle both es imports and cjs
                mod: mod.default? mod.default: mod
            })
        })
    }

    render() {
        return this.state.mod? this.props.children(this.state.mod): null
    }
}

export default Bundle

We modify webpack.dev.conf.js

{
    test:/\.bundle\.jsx$/,
    use: {
        loader:'bundle-loader',
        options: {
            name:'[name]'
        }
    }
}

Respond also to modify the webpack.prod.conf.js file

The test regular expression here is to hit the file with budle.jsx

Then we need to modify the Index.jsx file under demo1 to Index.bundle.jsx

Then modify the Index.jsx file under the demo, the complete code is as follows

import React from'react';
import {HashRouter, Route, NavLink,Redirect} from'react-router-dom'
import Bundle from'../common/Bundle'
import Dome1 from'./demo1/Index.bundle'
import Dome2 from'../demo/demo2/Index'
import'../../public/css/demo.pcss'
const Index = () =>
    <HashRouter>
        <div className="content">
            <div className="nav">
                <NavLink to="/Dome1" activeClassName="selected" exact>demo1</NavLink>
                <NavLink to="/Dome2" activeClassName="selected">demo2</NavLink>
            </div>
            <Route exact path="/"
                   render={() => (<Redirect to="/Dome1"/>)}/>
            <Route path="/Dome1"
                   component={
                       () =>
                           <Bundle load={Dome1}>
                               {(Dome1) => <Dome1/>}
                           </Bundle>
                   }
           />
            <Route path="/Dome2" component={Dome2}/>
        </div>
    </HashRouter>
;

export default Index;

We execute

npm run dev

Look at the browser effect

It has been successfully split, but the name is not good. After splitting, it is Index.bundle-0.js

We need to change the name, the 0 behind is the id means this configuration is here:

Let's change the name

Look at the browser again

It has been changed!

Let's split demo2 below

Similarly, modify the file name of Index.jsx under demo2

Demo2.bundle.jsx

Then modify Index.jsx file under demo, complete code

import React from'react';
import {HashRouter, Route, NavLink,Redirect} from'react-router-dom'
import Bundle from'../common/Bundle'
import Dome1 from'./demo1/Demo1.bundle'
import Dome2 from'./demo2/Demo2.bundle'
import'../../public/css/demo.pcss'
const Index = () =>
    <HashRouter>
        <div className="content">
            <div className="nav">
                <NavLink to="/Dome1" activeClassName="selected" exact>demo1</NavLink>
                <NavLink to="/Dome2" activeClassName="selected">demo2</NavLink>
            </div>
            <Route exact path="/"
                   render={() => (<Redirect to="/Dome1"/>)}/>
            <Route path="/Dome1"
                   component={
                       () =>
                           <Bundle load={Dome1}>
                               {(Dome1) => <Dome1/>}
                           </Bundle>
                   }
           />
            <Route path="/Dome2"
                   component={
                       (props) =>
                           <Bundle load={Dome2}>
                               {(Dome2) => <Dome2 {...props}/>}
                           </Bundle>
                   }
           />
        </div>
    </HashRouter>
;

export default Index;

Then look at the browser effect

We see click on the demo demo

Jump to demo1 by default, and you can see that two js requests have occurred, Demo1.bundle.js,

demo2.bundle.js,

This is not what we want, we hope it is,

demo1 requests Demo1.bundle.js,

demo2 requests Demo2.bundle.js,

then what should we do?

After the split, the on-demand loading is actually lazy loading, we only need to configure it in webpack.

options: {
    lazy: true,
    name:'[name]'
}

We have to modify the same

webpack.pro.conf.js file

We re-execute

npm run dev

See the effect

Perfect realization of on-demand loading

demo1 requests Demo1.bundle.js,

demo2 requests Demo2.bundle.js,

Let's go back and optimize the code!

Modify Bundle.jsx

const BundleFun = (Component,props) =>
    <Bundle load={Component}>
        {(Component) => <Component {...props}/>}
    </Bundle>
;
export {
    Bundle, BundleFun
}

That's it!

Then modify Index.jsx under demo

<Route path="/Dome1" component={() => BundleFun(Dome1)}/>
<Route path="/Dome2" component={(props) => BundleFun(Dome2, props)}/>

Revise these two sentences!

If you have any questions, you can leave a message to us below!

Reference: https://cloud.tencent.com/developer/article/1092779 React third-party component 1 (Use of Router for routing management ⑤Load on demand-down)-Cloud + Community-Tencent Cloud