React Lazy and Suspense

This is React’s official method. Let’s start with an example.

Example — Single Bundle

Assume our main.bundle.js has two components Header and Filter. HeaderComponent is rendered on every page but that’s not the case with FilterComponent. It renders only when isFilterOpen switch is enabled. Components like these are ripe for separating out from main bundle to their own conditionally loaded chunks. So, let’s split it.

Example — Bundle Splitting with React lazy and Suspense

React.lazy() expects a function that calls a dynamic import() as its argument. Dynamic imports are handled by Webpack. This import puts our FilterComponent in a separate chunk which reduces the size of our main.bundle by 50 KB, and returns a Promise. React Lazy resolves this Promise to a React component only when there is a demand for it which in our example is controlled by isFilterOpen.

When isFilterOpen becomes true, it may take some time for the separate chunk to load. For that time interval we need fallback content as the filler, something that is similar to a loading screen. Suspense comes in handy here. It takes a fallback prop that serves as the filler.

That's it! you have split your component but wait you may run into a “Page-flicker” issue.

React Lazy provides a nice interface for code-splitting but sadly it only has client-side support. If you use React lazy for a website that also does server-side rendering, you would see a flicker effect when the website loads. This is because React does not know about all the split chunks that are required for hydration, and hence it loses the context that’s created by the server-side rendering.

If the server can provide the information about split chunks that were used during server-side rendering, and if we can make the React hydration wait for all the chunks to load, then we could avoid this flicker issue. This is precisely what Loadable Components does for us.