SoFunction
Updated on 2025-04-07

Detailed explanation of two methods of react-router4 asynchronous loading routing

Method 1: We need to use bundle-loader to achieve on-demand loading.

First, create a new file:

import React, { Component } from 'react'

export default class Bundle extends  {

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

  componentWillMount() {
    ()
  }

  componentWillReceiveProps(nextProps) {
    if ( !== ) {
      (nextProps)
    }
  }

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

  render() {
    if (!)
      return false
    return ()
  }
}

Then, use on-demand loading at the entrance:

// ...

// The bundle model is used to load components asynchronouslyimport Bundle from './';

// Introduce a single page (including nested subpages)// Synchronous introductionimport Index from './app/';
// Asynchronous introductionimport ListContainer from 'bundle-loader?lazy&name=app-[name]!./app/';

const List = () => (
  <Bundle load={ListContainer}>
    {(List) => <List />}
  </Bundle>
)

// ...

  <HashRouter>
    <Router basename="/">
      <div>
        <Route exact path="/" component={Index} />
        <Route path="/list" component={List} />
      </div>
    </Router>
  </HashRouter>

// ...


File configuration
output: {
  path: (__dirname, './output'),
  filename: '[name].[chunkhash:8].',
  chunkFilename: '[name]-[id].[chunkhash:8].',
},

Method 2: Use native

Webpack configuration

First add chunkFilename to the output of '

output: {
  path: (__dirname, '/../dist/assets'),
  filename: '',
  publicPath: ,
  // Add chunkFilename  chunkFilename: '[name].[chunkhash:5].',
},

name is the name specified for the chunk created in the code. If it is not specified in the code, webpack will assign id by default as name.

chunkhash is the hash code of the file, and only the first five digits are used here.

On the routing page

Here is an old route writing method that was not loaded as needed

(
 (
  <Router history={browserHistory}>
   {/* Home Page */}
   <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 redirects to 404 */}
    <Redirect from='*' to='/404' />
   </Route>
  </Router>
 ), ('app')
);

We need to make the route dynamically load components, and we need to replace component with getComponent

(
 (
  <Router history={browserHistory}>
   {/* Home Page */}
   <Route path="/" component={App}>
    {/* default */}
    <IndexRoute component={HomePage} />

    {/* baidu */}
    <Route path="/baidu"
getComponent(nextState, cb) 
{ ([], (require) => { cb(null, require('components/layer/HomePage')) }, 'HomePage')}>
     <Route path="result"   getComponent... />
     <Route path="frequency" getComponent... />
    </Route>
    {/* 404 */}
    <Route path='/404' getComponent... />
    {/* Other redirects to 404 */}
    <Redirect path='*' onEnter: (_, replaceState) => replaceState(null, "/404") />
   </Route>
  </Router>
 ), ('app')
);

getComponent

Correspond to the previous component attribute, but this method is asynchronous, that is, this method will be called when the route matches.

There is a method here

(dependencies, callback, chunkName)

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

If you need to return multiple subcomponents, use the getComponents method and return multiple components as attributes of one object through cb. This is also available in the official example, but we do not need it here, and the root component cannot return multiple subcomponents, so use getComponent.

After rewriting, we need to disassemble the redirected route separately, that is, * this route. We have created a redirect directory for it above. Here we use the onEnter method, then change the routing state in this method, adjust to another route, and implement redirect:

/redirect/

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

The root route must render a single element

Following the official example and the above code, the page may not be rendered, but instead reports the exception of The root route must render a single element. This is because it is different from the export default in ES6.

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

getComponent(nextState, cb) {
  ([], (require) => {
   // Add .default to the back   cb(null, require('components/layer/ReportPage')).default
  }, 'ReportPage')
}

If you use CommonJS writing, that is, exported through , then there is no need to add .default.

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.