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 ',},
name
Is 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.
chunkhash
Is 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.component
Change 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 abovechildRoutes
Inside, we require
Three 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.