Improving Google PageSpeed Score using Code-Splitting
Have you ever wondered, why your app is loading slowly? or Why google page speeds score is very low even after you followed the web standards properly? [Disclaimer they do have extremely clear reports for the reasons].
I faced a similar issue while working on https://ecologi.com where even after following proper web standards our site was scoring poorly mere 22. So I started looking into the google page speeds reports and found that our Time To Load First Byte [TTFB] is extremely poor and one of the major areas to be improved.
NOTE: If you check the scores for ecologi now, they might not be good as lots of devops changes have been made recently.
I got to know about this awesome technique called Code-splitting - This feature allows you to split your code into various bundles which can then be loaded on-demand or in parallel [ webpack official docs ]. In other simple words, you get more fine control over the files which you want to serve and which you don’t.
Code splitting types
Now there are 2 techniques to do code-splitting:-
1. At component level: To split your component's code into multiple bundles. Sometimes your entire page/view’s code is quite big and complex to be delivered in 1 big chunk so you could cut it short into multiple bundles.
Though using this technique is a bit risky in itself as we have to take care of the number of network requests we are making to fetch bundles. So there needs to be a balance.
2. At Route level: To split your entire bundle into multiple small bundles based on the routes. This is generally a common optimization technique followed. But depending upon the needs you could use both as well.
Route level splitting using react-navi
Let's see how to achieve the route level splitting. At ecologi, luckily we were using react-navi, which has inherent support to do this on route level. I am pretty sure that other popular router libraries also do have it. All the details I am about to share are react-navi specific but bear with me as it will be helpful to understand the core idea behind it, so you can use it for other libraries/your own custom routing solutions as well.
So adding it in react-navi is very simple in fact. All you have to do is dynamically import your module and wrap it within lazy call as shown in the example.
But just a slight catch here, lazy returns a matcher object. In nutshell, a matcher is an object that creates a bridge between routes and the content/view/data, etc.
But for some reason ( not going into that details ) in our case, we were getting the dynamic data already and we just need the way to get the view. Adding a small snippet to how I achieved it is without using a call to lazy is. Also, note I am using async/await for making the code look nicer, the same things can be achieved using the promised version.
getView accepts a promise and dynamic imports return a promise.
Notice in my case, pages/Leaderboard are default exported component as shown below:-
export { default } from "./components/Landing";
Now in case, you have a component which is a named export. You need to change the code for your route as I did on line 9.
Tada, you have quickly added code-splitting to your project. Without much sweat, gained a huge performance boost & better scores on google page speeds :).
Bonus Content
Now in order to verify whether you have truly achieved the code-splitting or not you could use a source-map-analyzer to check if bundles are being properly being generated. Follow the instructions on their npm page for installation and as you can see for me, it’s showing Leaderboard chunk [7.38kb] as below
Do share how you find this article. If you like my work kindly do show love to it and follow me out on my github handle, as I am working on some cool stuff always.