React + WebPack is already a popular package for React development. I haven’t used any of the other parcels or rollups or other build frameworks. I’ve heard that github on React has over 10,000 stars in a short period of time. But that’s not the point of this article, hehe. This article focuses on the asynchronous loading of modules, and I won’t talk about anything else except load on demand optimization. Use webpack build, we will beat public resources to the vendor file, so as to make our business documents thin body, but we may have big quantum business, may be some business in some users there will never be used, in this case, if we put all the business code of disposable load down, Ensure () is a function that webpack provides. However, this optimization method is not within the scope of our discussion. In this article, we will introduce the react asynchronous loading component in my mind. Even if you don’t like it, it’s a great thing to learn. Page1 and page2 will be merged into a business file. If I never enter /buy route, I will not waste loading. Page2 should be async.

<Route path="/" component={App}>
		<IndexRoute component={page1}/>
		<Route path="/buy" component={page2}/>
	</Route>
Copy the code

Well, it is an asynchronous component, isn’t it very simple, isn’t it like the following line:

let page2 = ()=>{
    let page2Comp = import('lazyComp');
    return {
        <div>
            <page2Comp />
        </div>
    }
}
Copy the code

Oh, this IQ is also the te high, think oneself more corrupt ah, a few lines to achieve an asynchronous component, naive! Unfortunately, the report is wrong. Don’t know why? Let’s see what import() returns. It’s a promise object, so we should at least deal with it first. This is just like if you invite someone to your home for a banquet, you should at least arrange a seat first, take a chair to occupy a pit, wait until someone comes to think of moving the stool, no one is happy, turn around and leave. How do you make a hole? In fact, very simple truth, we must be very familiar with it, look at the following a small chestnut.

class MyComp extends React.Component{
    constructor() {return {
            isLoaded:false}}render() {let { isLoaded, data } = this.state;
        if(! isLoaded){return null;
        }
        return <Wrapper data={data} />
    }
    componentDidMount(){
        http.getData({}).then((results)=>{
            this.setState({
                data:results.data,
                isLoaded:true}}})})Copy the code

You’re familiar with this code, you don’t render until the data is returned, and you don’t render until the data is returned. The difference with asynchronous components is that the data retrieved is the component itself. What can be done before the component is retrieved? Easy, use an empty element in the ones place is OK. Let’s take a look at an asynchronous component from webpack:

class LazilyLoad extends React.Component {

	constructor() { super(... arguments); this.state = { isLoaded:false}; }componentDidMount() {
		this._isMounted = true;
		this.load();
	}

	componentDidUpdate(previous) {
		if (this.props.modules === previous.modules) return null;
		this.load();
	}

	componentWillUnmount() {
		this._isMounted = false;
	}

	load() {
		this.setState({
			isLoaded: false}); const { modules } = this.props; const keys = Object.keys(modules); Promise.all(keys.map((key) => modules[key]())) .then((values) => (keys.reduce((agg, key, index) => { agg[key] = values[index];return agg;
			}, {})))
			.then((result) => {
				if(! this._isMounted)return null;
				this.setState({ modules: result, isLoaded: true });
			});
	}

	render() {
		if(! this.state.isLoaded)return <div className="toast toast-show">
			<Loading/>
		</div>;
		console.log("modules:",this.state.modules);
		returnReact.Children.only(this.props.children(this.state.modules)); }}Copy the code

Do you feel very related to the above asynchronously loading data chestnut? Return reace.children. Only (this.props. Children (this.state.modules)); This line of code, this rendering method is called callback rendering. To give you a little analysis, let’s take a look at sample code for calling the above components:

const LazilyLoadFactory = (Component, modules) => {
	console.log("LazilyLoadFactory");
	return(props) => ( <LazilyLoad modules={modules}> {(mods) => <Component {... mods} {... props} />} </LazilyLoad> ); };Copy the code

Return react.children. Only (this.props. Children (this.state.modules)); Break down a few elements of this code:

  • This.props. Children: this is a reference to the child element of the calling component, for example(mods) => <Component {... mods} {... props} />This function
  • This.state. modules: This is the function’s modules variable passed to the LazilyLoad component that is treated as state
  • React.children. Only: I don’t have to say it

If you look at our Stateless component, LazilyLoadFactory, the LazilyLoad component, Render the parameter Component (modules) as an argument to the props, so it’s obvious that the parameter Component is the prop for this asynchronous Component. Let’s look at the code for the Component passed as an argument:

class WrapLazyComp extends React.Component{
	render(){
		const Comp = this.props.Comp;
		return<div> <Comp /> </div>; }}Copy the code

Okay, and then we have our general caller

LazilyLoadFactory(WrapLazyComp,{
	Comp: () => import('Real Business module')});Copy the code

So far, our asynchronous component is complete, mainly using import() to achieve asynchronous loading of modules, some students may be a little fuzzy about callback rendering, unfamiliar may need to understand a little. Of course, there are methods like require.ensure and so on. The specific optimization method depends on personal preference and the specific situation of the project, and it cannot be generalized. Ok, thank you, if there are any mistakes, please advise.