Here’s an example of how to setup route-based code splitting into your app using libraries like React Router with React.lazy.

import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';

const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));

const App = () => (
  <Router>
    <Suspense fallback={<div>Loading...</div>}>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </Suspense>
  </Router>
);

Did you know that the import(...) function that we use on lazy is just a function that returns a Promise? Which basically means that you can chain it just like any other Promise.


function retry(fn, retriesLeft = 5, interval = 1000) {
  return new Promise((resolve, reject) => {
    fn()
      .then(resolve)
      .catch((error) => {
        setTimeout(() => {
          if (retriesLeft === 1) {
            // reject('maximum retries exceeded');
            reject(error);
            return;
          }

          // Passing on "reject" is the important part
          retry(fn, retriesLeft - 1, interval).then(resolve, reject);
        }, interval);
      });
  });
}

Referencing the React Docs on code splitting, the recommendation is to use Suspense with a defined fallback so you have something to render in place of the components when they haven't loaded.


// Direct paste from https://reactjs.org/docs/code-splitting.html

import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import React, { Suspense, lazy } from 'react';

const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));

const App = () => (
  <Router>
    <Suspense fallback={<div>Loading...</div>}>
      <Switch>
        <Route exact path="/" component={Home}/>
        <Route path="/about" component={About}/>
      </Switch>
    </Suspense>
  </Router>
);

According to docs maybe its better to move Suspense out of Route component, try this:


import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';

const Home = lazy(() => import('./routes/Home'));
const Component = React.lazy(() => import(/* webpackChunkName: "Analyze" */ "./components/Analyze"))

const App = () => (
  <Router>
    <Suspense fallback={<div>Loading...</div>}>
      <Switch>
        <Route exact path="/" component={Home}/>
        <Route path="/analyze" component={Component}/>
      </Switch>
    </Suspense>
  </Router>
);

This is all the code in my navmenu file that creates a pretty cool navigation component and works with react-router and browserHistory.


import React, { Component, PropTypes } from 'react'
import { Link, browserHistory } from 'react-router'

class Navmenu extends Component {
  constructor(props) {
    super(props)
    this.state = { currentView: '' }
    this.getClasses.bind(this)
  }

  // in case of url being manually set, figure out correct tab to highlight
  // add event listener to update the state whenever the back/forward buttons are used.
  componentWillMount() {
    this.changeLocation()
    window.addEventListener('popstate', this.changeLocation.bind(this))
  }

  componentWillUnmount() {
    window.removeEventListener('popstate', this.changeLocation.bind(this))
  }

  // update state based on the URL
  changeLocation() {
    const path = window.location.pathname.split('/')
    const currentView = path[path.length - 1]
    this.setState({ currentView })
  }

  // update state and update react-router route
  navigateToRoute(route) {
    this.setState({ currentView: route })
    browserHistory.push(`/options/${route}`)
  }

  // give correct tab the 'active' bootstrap class
  getClasses(link) {
    let classes = 'btn btn-primary-outline flex-button'
    if (this.state.currentView === link) {
      classes += ' active'
    }
    return classes
  }

  render() {
    return (
      <div className="btn-group flex-navbar" data-toggle="buttons">
        <label className={this.getClasses('option1')} onClick={() => this.navigateToRoute('option1')}>
          <input type="radio" name="options" id="option1" autoComplete="off" defaultChecked />option1
        </label>
        <label className={this.getClasses('option2')} onClick={() => this.navigateToRoute('option2')}>
          <input type="radio" name="options" id="option2" autoComplete="off" /> option2
        </label>
        <label className={this.getClasses('option3')} onClick={() => this.navigateToRoute('option3')}>
          <input type="radio" name="options" id="option2" autoComplete="off" /> option3
        </label>
      </div>
    )
  }
}

export default Navmenu

import React from "react";
import { useLocation } from "react-router-dom";

const SignupFaq = () => <p>Sign up questions</p>;
const ShopFaq = () => <p>Shop questions</p>;

const faqs = {
  signup: {
    component: <SignupFaq />
  },
  shop: {
    component: <ShopFaq />
  }
};

function FAQ() {
  const { pathname } = useLocation();

  const { component } = faqs[pathname.split("/")[1]];

  const [modal, showModal] = React.useState(false);

  return (
    <React.Fragment>
      <button onClick={() => showModal(!modal)}>FAQ</button>
      <div className="modal">{modal && <div>{component}</div>}</div>
    </React.Fragment>
  );
}

export default FAQ;

A simple js code that I use very often for SPAs (for the v1.0.0 webapp):


exports.handler = async (event) => {
   const request = event.Records[0].cf.request;
   const hasType = request.uri.split(/\#|\?/)[0].split('.').length >= 2;
   if (hasType) return request; // simply forward to the S3 object as it is an asset
   request.uri = '/v1.0.0/index.html'; // handle all react routes
   return request;
};

That said, to keep my structure simple, I like to keep main directories lowercase:


├── dist // compiled application files to be served
|   ├── css
|   |   ├── main.[contenthash:8].css
|   |   └── main.[contenthash:8].css.map
|   ├── js
|   |   ├── main.[hash].js // depending on app size, this may contain multiple js files for code splitting
|   |   └── main.[hash].js.map
|   ├── media
|   |   └── [hash].[ext] // static assets like fonts and images
|   └── favicon.ico
|   └── index.html
|
├── config // supporting "webpackdevserver" configuration files
|   ├── devServer.js
|   ├── envs.js
|   ├── optimization.js
|   ├── output.js
|   ├── paths.js
|   ├── plugins.js
|   └── rules.js
|
├── public
|   ├── favicon.ico
|   └── index.html
|
├── src
|   ├── actions // redux actions
|   ├── components // stateful and stateless reusable components that just display "stuff" -- stateful components change and manipulate the UI
|   ├── containers // stateful components that utilize the reusable "components" to CRUD data and/or are connected to redux
|   ├── images
|   ├── pages // utilize components/containers to display something when visiting a "/route"
|   ├── reducers // redux reducers
|   ├── root // aka "<App />" that combines "routes", redux and other top-level supporting files into one place
|   ├── routes // assigns "pages" to a "/route"
|   ├── styles // shared and/or global styles used by all "components"
|   ├── types // redux types
|   ├── utils // supporting app files: like test setup, custom polyfills, axios configurations, ...etc
|   └── index.js // a simple file that "ReactDOM.render"s the "App"
|
├── server.js // express setup to serve the "dist" folder
└── webpack.config.js

Recommend

Code-Splitting React.lazy Error boundaries

Code-Splitting React.lazy

React Code-Splitting import()

React Code-Splitting Bundling Example

React Test Utilities Other Utilities Simulate

React Test Utilities Reference renderIntoDocument()

React Test Utilities Reference findRenderedComponentWithType()

React Test Utilities Reference scryRenderedComponentsWithType()

React Test Utilities Reference findRenderedDOMComponentWithTag()

React Test Utilities Reference scryRenderedDOMComponentsWithTag()

React Test Utilities Reference findRenderedDOMComponentWithClass()

React Test Utilities Reference scryRenderedDOMComponentsWithClass()

React Test Utilities Reference findAllInRenderedTree()

React Test Utilities Reference isCompositeComponentWithType()

React Test Utilities Reference isCompositeComponent()

React Test Utilities Reference isDOMComponent()

React Test Utilities Reference isElementOfType()

React Test Utilities Reference isElement()

React Test Utilities Reference mockComponent()

React Test Utilities Reference act()

React Test Utilities

React Profiler API onRender Callback

React Profiler API Usage

React AJAX and APIs Example: Using AJAX results to set local state

React.Component Class Properties defaultProps

React.Component Other APIs forceUpdate()

React.Component Other APIs setState()

React.Component Reference UNSAFE_componentWillUpdate()

React.Component Reference UNSAFE_componentWillReceiveProps()

React.Component Reference UNSAFE_componentWillMount()

React.Component Reference componentDidCatch()

React.Component Reference static getDerivedStateFromError()

React.Component Reference getSnapshotBeforeUpdate()

React.Component Reference static getDerivedStateFromProps()

React.Component Reference shouldComponentUpdate()

React.Component Reference componentWillUnmount()

React.Component Reference componentDidUpdate()

React.Component Reference componentDidMount()

React.Component Reference constructor()

React.Component Reference render()

React.Component Overview

Render Props Caveats Be careful when using Render Props with React.PureComponent

React Render Props Using Props Other Than render

React Render Props Use Render Props for Cross-Cutting Concerns

React Render Props

React Hooks FAQ Performance Optimizations How to read an often-changing value from useCallback?

React Hooks FAQ Performance Optimizations How to avoid passing callbacks down?

React Hooks FAQ Performance Optimizations Are Hooks slow because of creating functions in render?

React Hooks FAQ Performance Optimizations How to create expensive objects lazily?

React Hooks FAQ Performance Optimizations How to memoize calculations?

React Hooks FAQ Performance Optimizations How do I implement shouldComponentUpdate?

React Hooks FAQ Performance Optimizations What can I do if my effect dependencies change too often?

React Hooks FAQ Performance Optimizations Is it safe to omit functions from the list of dependencies?