Preface
This article describes how to implement dynamic loading components and uses this to explain the adapter mode.
1. Ordinary routing examples
import Center from 'page/center'; import Data from 'page/data'; function App(){ return ( <Router> <Switch> <Route exact path="/" render={() => (<Redirect to="/center" />)} /> <Route path="/data" component={Data} /> <Route path="/center" component={Center} /> <Route render={() => <h1 style={{ textAlign: 'center', marginTop: '160px', color:'rgba(255, 255, 255, 0.7)' }}>The page is gone</h1>} /> </Switch> </Router> ); }
The above are the most common React routers. In a simple single page application, writing this is OK. Because the packaged single js file is only about 200k, after gzip, it does not have much impact on loading performance.
However, after the product undergoes multiple iterations, the added pages continue to increase in size. At this time, optimization becomes necessary.
2. How to optimize
An important concept of optimization use is to load on demand.
It can be understood in combination with examples: only the components that need to be used on the current page are loaded.
For example, the current access to the /center page, then you only need to load the Center component. No need to load the Data component.
The industry currently implements the following solutions:
• React-router's dynamic routing getComponent method (router4 is no longer supported)
•Use react-loadable widget library
•Custom advanced components for on-demand loading
The common point of these solutions is to use webpack's code splitting function (used by webpack1, webpack2/webpack3 using import) to split the code.
Next, we will introduce how to use custom advanced components to achieve on-demand loading.
3. Customize advanced components
3.1 webpack import method
webpack treats import() as a split point and packages its requested module into a separate chunk. import() takes the module name as the parameter name and returns a Promise object.
Because import() returns a Promise object, it cannot be used directly for <Router/>.
3.2 Use adapter mode to encapsulate import()
Adapter mode: converts an interface of one class into another interface that the customer wants. Adapter mode allows classes that could not work together due to incompatibility of interfaces.
In the current scenario, what needs to be solved is how to hand over the loaded component to React for update after loading the component asynchronously using import().
The method is also very easy, it is to use state. After the component is loaded asynchronously, call the setState method and you can notify it.
Then, according to this idea, create a new advanced component and use the adapter mode to encapsulate import().
3.3 Implement the asynchronous loading method asyncComponent
import React from 'react'; export const asyncComponent = loadComponent => ( class AsyncComponent extends { constructor(...args){ super(...args); = { Component: null, }; = (this); } componentWillMount() { if(()){ return; } loadComponent() .then(module => ? : module) .then(Component => { ({ Component }); }) .catch(error => { /*eslint-disable*/ ('cannot load Component in <AsyncComponent>'); /*eslint-enable*/ throw error; }) } hasLoadedComponent() { return !== null; } render(){ const { Component } = ; return (Component) ? <Component {...} /> : null; } } ); //How to useconst Center = asyncComponent(()=>import(/* webpackChunkName: 'pageCenter' */'page/center'));
As shown in the example, create a new asyncComponent method to receive the Promise object returned by import().
When componentWillMount (the server rendering also has this lifecycle method), execute import(), and set the asynchronously loaded component into the state to trigger the component to re-render.
3.4 Resolve doubts
•initialization
= { Component: null, };
The null here is mainly used to determine whether the asynchronous component has been loaded.
• ? : module
This is to be compatible with the two export writing methods of name and default.
•return (Component) ? <Component {...} /> : null;
The null here can actually be replaced by <LoadingComponent />. The function is: when the asynchronous component has not been loaded well, it plays a placeholder role.
It is passed through the AsyncComponent component to the asynchronous component.
3.5 Modify webpack build
output: { path: , filename: ('js/[name].[chunkhash].js'), chunkFilename: ('js/[id].[chunkhash].js') }
In the output item, just add chunkFilename.
4. Summary
The advantage of customizing advanced components is that you can optimize existing old projects with minimal changes.
Like the example above, you only need to change the way the import component is. You can improve page performance by spending the least cost.
In fact, react-loadable is also implemented according to this idea, but it only adds many auxiliary functional points.
The above is the application of the adapter mode of the dynamic loading component of the React router introduced to you. I hope it will be helpful to you. If you have any questions, please leave me a message and the editor will reply to you in time. Thank you very much for your support for my website!