React ~ Router ~ Code Splitting - rohit120582sharma/Documentation GitHub Wiki

Instead of downloading the entire app before users can use it, code splitting allows you to split your code into small chunks which you can then load on demand.

It is also referred as lazy loading. So lazy loading is a great way to optimize your site, and it does that by splitting your code at logical breakpoints, and then loading it once the user has done something that requires, or will require, a new block of code. This speeds up the initial load of the application and lightens its overall weight as some blocks may never even be loaded.

There are two main ways to go about code splitting your app?

  • Route level splitting
  • Component level splitting

References



Dynamic import

If you’re familiar with ES modules, you know that they’re completely static. What that means is that you must specify what you’re importing and exporting at compile time, not run time. This also means that you can’t dynamically import a module based on some condition. import needs to be declared at the top of your file or it’ll throw an error.

But, here’s the good news that dynamic import does exist and it’s supported by Create React App. The difference is that instead of using import as you typically would, you use it like a function that returns you a promise that resolves with the module once the module is completely loaded.

We have 2 options for loading components with dynamic imports:

  • loadable-components - It is a library for loading components with dynamic imports. It handles all sorts of edge cases automatically and makes code splitting simple!
  • React.lazy() & Suspense

Set up

To accomplish this we’ll use webpack, and @babel/plugin-syntax-dynamic-import.

Webpack has built-in support for dynamic imports; however, if you are using Babel (e.g., to compile JSX to JavaScript) then you will need to use the @babel/plugin-syntax-dynamic-import plugin. This is a syntax-only plugin, meaning Babel won’t do any additional transformations. The plugin simply allows Babel to parse dynamic imports so webpack can bundle them as a code split.

Your .babelrc should look something like this:

{
    "presets": ["@babel/preset-react"],
    "plugins": ["@babel/plugin-syntax-dynamic-import"]
}

Now the project setup supports code splitting via dynamic import. The import() function-like form takes the module name as an argument and returns a Promise which always resolves to the namespace object of the module.

if(editPost === true) {
    import('./editpost')
        .then((module) => module.showEditor())
        .catch((e) => )
}

React.lazy() & Suspense

We formerly used @loadable/components to achieve this but now we have React.lazy() in react core. If you need SSR (Server Side Rendering) or Library splitting, then @loadable/component is the solution.

React.lazy()

  • The React.lazy is a new function in react that lets you load react components lazily through code splitting without help from any additional libraries.
  • It provides a built-in way to separate components in an application into separate chunks of JavaScript with very little legwork. You can then take care of loading states when you couple it with the Suspense component.

Suspense

  • Suspense is a component required by the lazy function basically used to wrap lazy components. Multiple lazy components can be wrapped with the suspense component. It takes a fallback prop that accepts the react elements you want to render as the lazy component is being loaded.
  • It is like an error catcher, which allows us to define fallback JSX if part of the content it is wrapping has not loaded. If you think of a try catch block, the catch block is our Suspense fallback, and everything within <Suspense></Suspense> is our try block.
import React from 'react';
import {
    BrowserRouter as Router,
    Route,
    Switch
} from 'react-router-dom';

const Home = React.lazy(() => import('./Home'));
const Topics = React.lazy(() => import('./Topics'));
const Settings = React.lazy(() => import('./Settings'));

const Loading = () => <p>Loading</p>;

const App = () => (
    <Router>
        <div>
            <ul>
                <li><Link to='/'>Home</Link></li>
                <li><Link to='/topics'>Topics</Link></li>
                <li><Link to='/settings'>Settings</Link></li>
            </ul>

            <hr />

            <React.Suspense fallback={<Loading />}>
                <Route exact path='/' component={Home} />
                <Route path='/topics' component={Topics} />
                <Route path='/settings' component={Settings} />
            </React.Suspense>
        </div>
    </Router>
)

⚠️ **GitHub.com Fallback** ⚠️