Frontend Performance Optimization: React Code Splitting and Bundle Size
Frontend performance is important. Not only is this good for your users, but it is crucial if run an ecommerce and you want to improve ecommerce SEO, and is actually really important for our planet as well. Use code-splitting and reduce the size of your bundles. Measure and optimize our frontend performance continuously.
Let's go millisecond hunting.
Let’s check out our own site as an example, where we start on the Crystallize front page and make two navigations afterward.
- / - 36 req, 860kb
- /blog - 16 req. 160kb
- /blog/frontend-performance-measuring-kpis - 22 req, 577kb
- /blog/seo-for-react-ecommerce-spa - 19 req, 688kb
- Total: 93 req. 2285 kb
- / - 13 req, 308kb
- /blog - 11 req. 53kb
- /blog/frontend-performance-measuring-kpis - 16 req, 398kb
- /blog/seo-for-react-ecommerce-spa - 16 req. 674kb
- Total: 56 req. 1433 kb
You are also visiting the server every time, so if the server has a lot to do, the speed would slow down. With JS turned on you would (on our site) just query the GraphQL PIM API once, and it is usually a super fast API.
In some cases, not shipping our JS bundles to the user is just fine. If it benefits the user and you still are satisfied with their experience on your site. Do it.
We have established that the JS bundles on your site have a massive impact on the downloaded bytes. But let’s be honest, most of us will still end up shipping JS to our users. Let’s make sure we do it the right way.
Get an overview of what you are shipping to your users. If you are using source maps, you can get a very detailed overview of your bundle contents by using source-maps-explorer.
Get rid of anything that takes up too much space. See if there are more lightweight alternatives for the libraries you are using. Using moment.js? Try out date-fns. Using lodash? Make sure you import only the individual parts that you actually use:
You want to make sure that the users are getting the JS that they need for the page they are on, and nothing else. No reason to fetch JS for all the possible pages and components on the page right away. This can be deferred until they are actually needed. This is called code splitting and is an essential part of frontend performance.
React.Lazy works by not downloading the JS a component needs before it is mounted on the page. It is a perfect solution when you want to take parts of your application out of your bundle and defer the loading to when it actually needs to happen. This is essentially how you do it (taken from the React code-splitting guide)
React.Suspense is also used here to display a fallback message that will be visible during the download and execution of “BigComponent”.
Beware: React.Lazy does not currently work on the server, so if you want to have this on a server-side rendered application, which we highly recommend, you should try out Next.js (which comes with code-splitting on route level out-of-the-box), or react-loadable.