Monday, 10 June 2019

ReactJS Router Lazy Loading Pages


When creating a single page app application with [[ReactJS|react]] router. Your bundle size can get quite big when having quite a few pages. Loading all this in one can hinder your performance.

Thankful with react lazy and Suspense this is supper simple. With just a few lines of code you can split each of your page views into chunks and let [[Webpack]] load in the code it needs for each page. First is a snippet of one of my pages. Its just a react functional component. I am using typescript but it not that much different to JavaScript.

import * as React from 'react';
import Layout from '../components/layout';

const About: React.FC = () => (
  <Layout>
    <h1 className="text-5xl text-center mt-5">About Page</h1>
  </Layout>
);

export default About;

As the above code shows there is nothing different with the page component it just a standard functional component. To tell Webpack to split the pages into chunks I will be using the import('/_ path _/'); syntax with React.lazy

const Index = React.lazy(() => import('./pages/index'));

Now I can use the standard BrowserRouter Switch wrapped in a React.Suspense to load in the page chunks as needed.

<BrowserRouter>
  <React.Suspense fallback={() => <Loader />}>
    <Switch>
      <Route exact path="/" component={Index} />
      <Route path="/about" component={About} />
    </Switch>
  </React.Suspense>
</BrowserRouter>

With not a lot of code we can let react and Webpack do loads of work for us. My favourite part of the whole process is that Webpack automatically loads in the chunks it needs to render the pages. This dynamical gives you a massive boost in load speed because we have fewer bytes going down the wire. To finish off I will show my full index.tsx

import React from 'react';
import ReactDOM from 'react-dom';
import {Switch, Route} from 'react-router';
import {BrowserRouter} from 'react-router-dom';

const Index = React.lazy(() => import('./pages/index'));
const About = React.lazy(() => import('./pages/about'));

function App() {
  return (
    <BrowserRouter>
      <React.Suspense fallback={() => <Loader />}>
        <Switch>
          <Route exact path="/" component={Index} />
          <Route path="/about" component={About} />
        </Switch>
      </React.Suspense>
    </BrowserRouter>
  );
}

ReactDOM.render(<App />, document.getElementById('root'));
serviceWorker.unregister();