How to Make the Loading Bar Disappear: A Complete Guide to Code Splitting in React

An overview of Code Splitting in React.js and High Order Components (Loadable + Lazy)

Photo by Aziz Acharki on Unsplash


Why do we need bundles?

What does this mean for your imports?


The static structure of imports is enforced syntactically in two ways.

import module from './dir/module';
  1. The import declaration can only appear at the top level of a module.
  2. They only accept a string literal as the module specifier.

Code Splitting overview

Yup, this is exactly what we’re doing.

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

Code splitting is supported by the dynamic import(). The import() function-like form takes the module name as an argument and returns a Promise.

The proposed operator for loading modules dynamically works as follows:

const moduleSpecifier = './dir/someModule.js';
.then(someModule =>;

The operator is used like a function:

  • The parameter is a string similar to the import declarations most of us currently use. However, with dynamic import(), the parameter can be any expression whose result can be coerced to a string.
  • The result of the “function call” is a Promise. Therefore anything called within then can be executed once the module is completely loaded.

Use Cases

1) Loading code on demand

2) Conditional loading of modules

3) Computed module specifiers

High Order Components for Code Splitting


The React.lazy function lets you render a dynamic import as a regular component. This also handles router-centric code splitting.

There’s one main limitation you might notice above.

React.lazy currently only supports default exports.

You can find an easy enough workaround for that here. Additionally,

React.lazy and Suspense are not yet available for server-side rendering. If you want to do code-splitting in a server rendered app, Loadable Components is recommended

Well luckily for you…


Sometimes components load really quickly (<200ms) and the loading screen only quickly flashes on the screen.

A number of user studies have proven that this causes users to perceive things taking longer than they really have. If you don’t show anything, users perceive it as being faster.

Accordingly, there is a lot of extra functionality for modifying behavior based on set time intervals. Examples below.

Fun facts

  • If import() is used in a module, it can occur anywhere at any level, and is not hoisted.
  • import() accepts arbitrary strings (with runtime-determined template strings shown here), not just static string literals.
  • The presence of import() in the module does not establish a dependency which must be fetched and evaluated before the containing module is evaluated.
  • import() does not establish a dependency which can be statically analyzed. (However, implementations may still be able to perform speculative fetching in simpler cases like import("./foo.js").)