Code Splitting in React: Load your bundles blazingly fast
1. Basics of React and it’s ecosystem like react-router and webpack.
2. ESNext syntax
What happens when we run npm run build in a react app?
It initiates a process called bundling which is done by webpack or browserify like tool.
Bundling is the process of following imported files and merging them into a single file: a “bundle”. This bundle can then be included on a webpage to load an entire app at once.
Problem 1: Now when the codebase expands, the bundle size goes on increasing and in some cases it may go beyond 10MBs. The problem with this single bundle file approach is that when a user visits your website for the first time, he/she has to wait until the whole 10MB bundle is downloaded. It has been observed that nearly 90% of users leave a site if it doesn’t load or respond within 10 seconds or less.
Problem 2: Most of the websites will first ask for Log-In and then only a user can browse other pages. Think now, just to open up the Log-In page, the entire bundle has to be loaded first and then only the user can Log-In, though rest of the pages are not required at the time of Log-In.
To get rid of this huge single bundle file, people came up with the idea of splitting the bundles into multiple tiny chunks which can be loaded only when it is required in the UI. This process of splitting into smaller chunks is what we call code-splitting which is really a buzz word in the world of front-end frameworks.
Code-Splitting is a feature supported by bundlers like Webpack and Browserify (via factor-bundle) which can create multiple bundles that can be dynamically loaded at runtime.
Let's address this problem with an easy solution which is built-in inside the webpack. It is going to be less theory more code. We will be creating a simple web-app with 3 pages: Home, About and ContactUs. What we want is to have specific chunks for specific pages so that it downloaded only when the user visits that page.
Root path: '/home'
About section: '/about'
ContactUs Section: '/contact'
All the above path has to be loaded in different chunks because we will be splitting up the code like that.
STEP 1: Creating a new app
Let's create a new app using CRA(create-react-app). Please note, I am using Node 10.15.3 and recommend you to use Node 10 or above.
// lets create the app my-splitted-app
npx create-react-app my-splitted-app
npm install && npm start
//that's it your new app is up and running with no charm at all.
STEP 2: Adding all 3 pages
Now that we have a scaffolded, we will add the 3 pages to our app. Let's go to src folder and add a new folder name components. We can find the files going into the below sandbox.
Please open this sandbox before proceeding with this article. Or you can clone this https://github.com/akhil-gautam/code-splitting-example-medium repo if you don’t want to write the entire code and run cd my-app && npm install && npm start
Each of the 3 files contains a component with some styling(though poor 😆).
Home component is the place where we have added Links to the About and ContactUs pages. Link is imported from ‘react-router-dom’ which will create a link to that react page or we can say to that specific chunk. Please note this method of splitting is better known as Route Level Splitting because our bundle will be split based on the route, a chunk for every unique route.
STEP 3: Import them in App.js
Here a lot of stuff has happened which I will explain in bits. Firstly, Suspense and Lazy are imported from react.
React.lazy() is a HOC which allows react to load components lazily as and when required.
Suspense is used to wrap one or more, lazy components and it has a fallback prop that accepts the react elements you want to render while the lazy component is being loaded.
The Home component is imported normally as we want it to be the root path of our application and the rest are imported lazily on hitting the routes.
Let's wait for a moment to understand the code below:
const About = lazy(() =>
import(/* webpackChunkName: "About" */ './Components/About'));
importis called as a function to dynamically import a module. When it is used this way, it returns a promise.
2. /* webpackChunkName: "About" */ is used to specify the name of the chunk or else it will be default numbered from 0 to number of lazy loaded components.
Now when the user clicks links to different pages, only then it’s corresponding chunk will get loaded.
That is it. It is so simple to split our giant single bundle into tiny chunks based on the routes. The user will have to load only those chunks which the current screen requires instead of pushing all at once.
To verify it, you can open up the developer console and check the network tab. You can watch the video below to see the above code in action.
Thanks, for reading this till the end. I will be happy if it helps you at any point in your development process. I will be glad to help if you need any help in React and Ruby on Rails.
Contact me at email@example.com .