Detailed explanation of how react-router implements on-demand loading; detailed explanation of react-router

Source: Internet
Author: User

Detailed explanation of how react-router implements on-demand loading; detailed explanation of react-router

Note: The react-router version used in this article is 2.8.1.

React Router is an excellent routing solution and is easy to use. However, when the website grows larger, the first problem is that Javascript files become huge, which makes the homepage rendering time unbearable. In fact, the program should only load the JavaScript required for the current rendering page, that is, the "code split"-split all the code into multiple packets and load as needed during user browsing.

The result is:

This was the case in the past (23333, I did not mean it ..)

This is the case now:

In fact, a large javascript file is split into several chunk files.

Below is the transformation process

Webpack Configuration

Firstwebpack.config.js Ofoutput Add chunkFilename

Output: {path: path. join (_ dirname ,'/.. /dist/assets '), filename: 'app. js', publicPath: defaultSettings. publicPath, // Add chunkFilename: '[name]. [chunkhash: 5]. chunk. js ',},

nameIs the name specified for the chunk created in the Code. If the name is not specified in the Code, the id is assigned as the name by default for webpack.

chunkhashIs the file hash code. Only the first five digits are used here.

Add Homepage

In the past, your routing should be like this: (as a large application that needs to be loaded on demand, the routing must be quite complex. Here, I will only list some routing examples)

ReactDOM. render (<Router history = {browserHistory} >{/ * homepage */} <Route path = "/" component = {App }>{/ * default */} <IndexRoute component = {HomePage}/> {/* baidu */} <Route path = "/baidu" component = {BaiduPage}> <Route path = "result" component = {BaiduResultPage} /> <Route path = "frequency" component = {BaiduFrequencyPage}/> </Route> {/* 404 */} <Route path = '/404' component = {NotFoundPage} />{/ * Other redirection to 404 */} <Redirect from = '*' to = '/000000'/> </Route> </Router> ), document. getElementById ('app '));

After loading on demand, we need to allow the route to dynamically load components.componentChange getComponent. First, remove the route (it will be difficult to write it all together because of the large number of routes) and create a root route:

const rootRoute = { path: '/', indexRoute: {  getComponent(nextState, cb) {   require.ensure([], (require) => {    cb(null, require('components/layer/HomePage'))   }, 'HomePage')  }, }, getComponent(nextState, cb) {  require.ensure([], (require) => {   cb(null, require('components/Main'))  }, 'Main') }, childRoutes: [  require('./routes/baidu'),  require('./routes/404'),  require('./routes/redirect') ]}ReactDOM.render( (  <Router   history={browserHistory}   routes={rootRoute}   /> ), document.getElementById('app'));

History remains unchanged. Add the routes attribute to the Router to pass the created route.

There are four attributes:

Path

Match the route, that is, the previous path.

GetComponent

It corresponds to the previous component Attribute, but this method is asynchronous, that is, this method is called only when the route matches.

Here is a require. ensure method.

require.ensure(dependencies, callback, chunkName)

This is the method provided by webpack and the core method for loading as needed. The first parameter is the dependency, the second is the callback function, and the third is the chunkName mentioned above, which is used to specify the name of the chunk file.

To return multiple child components, use the getComponents method to return multiple components as the attributes of an object through cb. This is also available in official examples, but we do not need it here, and the root component cannot return multiple child components, so getComponent is used.

IndexRoute

Used to set the home page, corresponding to the previous <IndexRoute>。

Note that indexRoute is written here. This is an object, and getComponent is used in the object.

ChildRoutes

The sub-router configuration corresponds to the previous sub-routers. We split the previous/baidu,/404, and *, and then we will create route configurations for them respectively.

Route Control

The abovechildRoutesInside, we requireThree sub-routes are created in the directory routes Directory to place the three routes.

routes/├── 404│  └── index.js├── baidu│  ├── index.js│  └── routes│    ├── frequency│    │  └── index.js│    └── result│      └── index.js└── redirect  └── index.js

Similar to rootRoute, each index. js in it is a routing object:

/404/index. js

module.exports = { path: '404', getComponent(nextState, cb) {  require.ensure([], (require) => {   cb(null, require('components/layer/NotFoundPage'))  }, 'NotFoundPage') }}

/Baidu/index. js

module.exports = { path: 'baidu', getChildRoutes(partialNextState, cb) {  require.ensure([], (require) => {   cb(null, [    require('./routes/result'),    require('./routes/frequency')   ])  }) }, getComponent(nextState, cb) {  require.ensure([], (require) => {   cb(null, require('components/layer/BaiduPage'))  }, 'BaiduPage') }}

/Baidu/routes/frequency/index. js

module.exports = { path: 'frequency', getComponent(nextState, cb) {  require.ensure([], (require) => {   cb(null, require('components/layer/BaiduFrequencyPage'))  }, 'BaiduFrequencyPage') }}

Let's take a few examples. The rest are the same. A little special is redirect.

Set Redirect

Previously, we set redirection in the root route as follows:

<Router history = {browserHistory}> <Route path = "/" component = {App }>{/ * home */} <IndexRoute component = {HomePage}/> <Route path = "/baidu" component = {BaiduPage}> <Route path = "result" component = {BaiduResultPage}/> <Route path = "frequency" component = {BaiduFrequencyPage}/> </Route> <Route path = '/808080' component = {NotFoundPage}/> {/* if none of them match, redirect to 404 */} <Redirect from = '*' to = '/100'/> </Route> </Router>

After the rewrite, we need to split the redirection route separately, that is, * this route. We have created a redirect directory for it. Here the onEnter method is used, and then the Routing Status is changed in this method, and then adjusted to another route to implement redirect:

/Redirect/index. js

module.exports = { path: '*', onEnter: (_, replaceState) => replaceState(null, "/404")}

The root route must render a single element

After following The official example and The above Code, The page may not be rendered, but The root route must render a single element exception is reported. This is because module.exports And ES6 export default There are differences.

If you use es6, that is, your components are exported through export default, you need to add. default to the getComponent method.

GetComponent (nextState, cb) {require. ensure ([], (require) =>{// add. default cb (null, require ('components/layer/reportpage ')). default}, 'reportpage ')}

If you use CommonJS module.exports You do not need to add .default .

The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.