Search code examples
reactjswebpackreact-routercode-splitting

Implement nested async route fetching in React


Is it possible to implement nested async route fetching with System.import so an application is only divided into several reasonable chunks, rather than many small chunks?

Background

I'm in the process of implementing bundle splitting in my React app. Initially I implemented bundle-loader (which I couldn't get to work in all cases) and then using System.import, which I found to behave much more predictably.

Problem

The code splitting is working just fine on a route by route basis, however, it produces many small bundles and the overhead of an additional bundle and get is unnecessary and wasteful.

As an example, I have this code which loads the bundle for Dashboard, Settings or Images when you navigate to their page:

    <Provider store={store}>
        <Router history={browserHistory}>
            <Route path='/' component={Container}>
            <IndexRedirect to="Login" />
            <Route path='Registration' component={RegistrationContainer} />
            <Route path='Login' component={LoginContainer} />
            <Route path='Route1' >
                <IndexRedirect to="Dashboard" />
                <Route path='Settings' 
                        getComponent={ (loc, cb)=> {System.import('./components/Route1/Settings')
                                              .then(loadRoute(cb))
                                              .catch(errorLoading); }}/>
                <Route path='Dashboard' 
                        getComponent={ (loc, cb)=> {System.import('./components/Route1/Dashboard')
                                              .then(loadRoute(cb))
                                              .catch(errorLoading); }}
                    />
                <Route path='Images' 
                        getComponent={ (loc, cb)=> {System.import('./components/Route1/Images')
                                              .then(loadRoute(cb))
                                              .catch(errorLoading); }}
                    />
        </Router>
    </Provider>

Is it possible to load the bundles for all three when first navigating to the Route1 path?

Many Thanks


Solution

  • I have played around and managed to find a solution which reduces the number of get requests to 2 for any given number of sub routes.

    The way I got this result was to introduce an index component to Route1

    <Route path='Patient' getComponent={ (loc, cb)=> {System.import('./components/Route1Index')
                .then(loadRoute(cb))
                .catch(errorLoading); }}>
    

    I then created the index component with imports for all the child routes like this:

    import React from 'react';
    
    // Child route components
      import Settings from './Settings';
      import Dashboard from './Dashboard';
      import Images from './Images';
    
    export default (props) =>(
      <div>
            {props.children}
      </div>
    )
    

    I also set minChunks:2 in the Webpack CommonsChunkPlugin

    Now when I navigate to any child route of Route1 there are only 2 bundles loaded: the Route1Index bundle and the bundle containing all of it's imports