Designing a PWA is very easy. Just add manifest file and you are done. But there are some pointers which you should know about before deciding whether to build a PWA app or a native app. As my hobby project, I decided to build a PWA called Chibaree. The app is for small kids to know the world by pictures. It is built in ReactJS. You can open it on your Chrome mobile browser and experience it. It is still in the development stage, but I thought it would be good to share my experience about the hurdles I faced.
Performance Score
You are well aware that Google ranks sites based on factors like mobile responsiveness and performance. Having both improves search results, which really matters when you want to increase the visibility when no one knows about your app.
You can check how well your app scores using Lighthouse. I insist on checking the score on PageSpeed Insights from Google and NOT on localhost. It uses Lighthouse behind the scenes, but it will use insights based on data from your actual users around the world and user’s experience. If it doesn’t have enough data (e.g., users have not started using your app) then it will use its default configuration. It is the same as testing on a browser with a live URL.
To test it using PageSpeed Insights, you need to host your site somewhere, like GitHub pages, which uses HTTPS protocol. In short, you will get a real score. If you test it on localhost then it might give the wrong performance score because of your machine’s configuration.
Even though my app is small and lightweight, the overall score is just 45. It’s bad and I am working on it to take it beyond 80. The real reason behind the poor score is LCP (Largest Contentful Paint). It is a metric that measures how much time it takes to paint the largest element on a page it loads. In my case, the largest element is an image. You can explore the importance of each metric with quick help from Google. Why is this metric so important? Because of its weightage in calculating performance scores. It is 25%. If you improve this score, then your other scores will also improve automatically. The last column in the below image represents the weightage of different metrics.
So, what should I do? Should I remove images from my page to improve the LCP score? Well, I cannot do that because my use-case doesn’t allow me to do so. Another question you might ask is what’s the matter with images. The short answer is that there is nothing wrong with images or their sizes or anything related to it.
The main problem is when it starts painting those images. This process happens after 4.5s, based on the test report. Then what consumes initial 4.5 seconds? This time is spent loading JS and CSS bundles from the server. Out of those 4.5 seconds, a good amount of time is spent in loading one big bundle and that is of third-party libraries I have used.
If all the bundles, including third-party packages, get loaded in 1 second, then my overall score would jump to more than 80. But how to reduce the loading time of bundles? Load them when needed. Of course, I have used the lazy loading feature of React Router to load feature modules when a user visits corresponding pages. I can lazy load what I have created and NOT what others have created. Here I mean to refer to third-party packages.
Recently, I have learnt that we can also lazy load third-party packages. Once I complete the implementation of it, I will discuss about the approach in another article.
Another way to improve scores is having less DOM. If your layouts are different for mobile and desktop, I recommend you to use the device-detect library. Through those load components based on devices. Do not use CSS properties to show/hide layouts. Earlier I was using this approach and my score was 28. Even though the content is not painted on the screen, the DOM still exists and it is considered in performance score calculation.