Phase 2: Frontend Frameworks

Code splitting with React.lazy & Suspense

Intermediate ~3 min read
Think of it this way A friendly analogy. Read this if the technical version feels dense. Show Hide

Imagine you’re going to a giant library that has every single book in the world – storybooks, science books, history books, everything! If you wanted to read just one comic book, it would be crazy to have to carry the entire library home with you every time, right? It would be super heavy, take forever to get, and most of it you wouldn't even need! That's kind of like how some computer programs work. When you visit a website or use an app, it often has to download all its instructions and pictures at once, even if you're only looking at one small part of it. This can make websites feel really slow when they first open up, which isn't much fun.

So, what if the library worked differently? What if you only picked up the exact book you wanted to read, when you wanted to read it? That's the main idea behind something called "code splitting" in programming. Instead of one giant instruction book for the whole website, we break it into smaller, separate instruction books. Each page or section of the website gets its own mini instruction book. When you click on a new part of the website, like going from the "About Us" page to the "Contact" page, the computer just quickly grabs the instruction book for that specific page, not the whole collection.

In the world of React (which is a popular tool for building websites), there are special tricks to do this. One trick is like telling the library, "Hey, I might want to read the 'Science Adventures' book later, but don't bring it to me until I ask for it." This is what something called React.lazy helps us do. It means a part of your website only gets its instructions loaded just before you need to see it. While the computer is quickly fetching that "Science Adventures" book for you, the screen might show a little loading message or a spinning wheel. This "showing a loading message while waiting" part is handled by something called Suspense. It lets you show something friendly to the user so they know something is happening, instead of just a blank screen.

So, when you're building your own cool websites, especially ones with lots of different pages or complicated parts, this idea helps you make them much faster and smoother for people to use. You can make sure that when someone visits your amazing online art gallery, they only download the instructions for the "paintings" section when they click on it, and not also the instructions for the "sculptures" section or the "about the artist" page until they actually want to see those. This means your website feels zippier and more fun, because it's only doing the work it absolutely needs to do, right when it needs to.

As your React applications grow, especially with multiple routes and complex features, the JavaScript bundle size can become quite large. This large bundle needs to be downloaded by the user's browser before your application can even render, leading to slower initial page loads and a poor user experience. Code splitting is a technique that addresses this by breaking your application's code into smaller chunks, which can then be loaded on demand. When dealing with routing and navigation, it's particularly effective to split your code by route, meaning a user only downloads the code for the specific page they are currently viewing, not the entire application.

React provides a built-in solution for code splitting called React.lazy and Suspense. React.lazy is a function that lets you render a dynamic import as a regular component. It takes a function that must return a Promise, which resolves to a module with a default export containing a React component. In simpler terms, you tell React to only load a certain component's code when it's actually needed. When the component wrapped with React.lazy is being loaded, React doesn't know what to render yet. This is where Suspense comes in: it's a component that lets you specify a fallback UI (like a loading spinner or a simple message) to display while the lazy component's code is being fetched and loaded.

The practical application of React.lazy and Suspense often involves route-based code splitting. Instead of bundling all your route components together, you can lazily load each route's component. This significantly reduces the initial payload your users download, leading to a much faster 'time to interactive' for your application. By deferring the loading of less critical or frequently accessed parts of your app, you ensure a smoother and more responsive experience right from the start, a crucial aspect for any full-stack application.

Key Takeaways

  • Reduces initial JavaScript bundle size for faster page loads.
  • React.lazy enables dynamic loading of components on demand.
  • Suspense provides a fallback UI (e.g., loading indicator) while lazy components load.
  • Ideal for route-based code splitting to improve user experience.

Code Example

javascript
Preview

How this code works

This code demonstrates "code splitting," a technique to improve web application performance by only loading the necessary parts of the application when they are needed. Instead of bundling all page code together and sending it to the user upfront, this setup ensures that the code for AboutPage and ContactPage is only fetched from the server and loaded into the browser when a user actually navigates to the /about or /contact routes. This results in a faster initial load time for the main application.

The core of this functionality relies on lazy and Suspense from React, combined with react-router-dom. Components like AboutPage are defined using lazy(() => import('./pages/AboutPage')). This tells React to load the AboutPage module dynamically only when it's first needed. The Suspense component is then wrapped around the entire Routes block. This is a subtle but important detail: Suspense provides a fallback prop (like "Loading page...") which is displayed while any of its child lazy components are still downloading their code. A single Suspense component can manage the loading states for multiple lazy components nested within it, providing a unified loading experience without needing to wrap each Route individually.