Supercharging Performance: 17 Ways How
By Keshav Sultania, Reynier Carlo A. Nebres and Naveen S.R
If your website has not yet loaded by the time you read the title of this blog, then you just lost 53% of your visitors. Also, half of them will tend to pass on their negative experience to others. It is not about seconds anymore. Your website performance is evaluated in milliseconds. Load times that differ by milliseconds have a greater impact on the revenue than you may think. They even impact your conversion rates, bounce rates, and customer retention.
Just imagine, if this blog page had taken more time to load then you would have dropped. That shows the importance of performance.
Note: Always create your site assuming that your customers fall into the 3G Mobile User Segment.
Here is our journey in taking optimizing our website from 32 to 75+ over lighthouse
Baseline Report:
Post The Performance Tuning:
Tips and tricks that have worked for us …
1. Third Party Scripts Load On Demand
Often we require third party scripts for telemetric capability or library for specific features.
Based on the requirement - let’s say Google Ads - load the script only when the user scrolls to that point. It is recommended to load the Google ad script if it’s not visible on the first view.
Third-party scripts are a predominant cause of performance slowdowns and are often caused by resources outside of your control.
There are multiple third-party scripts used on websites like GTM script for tracking, Datavisor for Security, Clevertap for Push Notifications, Google Ads, etc.
2. Javascript Don’ts
Most web applications rely on javascript to work. This includes calling APIs to communicate with the back-end or sometimes, applying design or animating elements that are hard to achieve with CSS. With these things in mind, listed below are some of the codes or approaches that need to avoid as they affect the page performance
(i) Use of setTimeout. We used setTimeout to execute code after a certain time or execute codes after another function is executed. This is fine when used once or twice, but to include many setTimeouts in the application is a big no-no. As an alternative, it’s better to use “Promise” to make chaining of codes efficiently.
(ii) Not clearing setInterval. setInterval is a function that executes repeatedly for every x number of milliseconds. Performance can degrade when using setInterval with short intervals thus, it is important to clear intervals after they fulfill their use.
(iii) Avoid using unnecessary third-party scripts. If a certain functionality can be easily replicated, avoid using third-party scripts. The reason behind this is to avoid using unnecessary codes that can increase the build size. If you create your own, you can minimize the code as much as possible with the same result.
3. Image Optimization
Some applications, especially e-commerce, need images to attract possible customers. However, adding images especially those that are high-resolution can have a big file size and can affect the page load. The recommended image file size should be a few KB’s.
Usually, a web application includes icons such as these to make the user experience and interface better.
Instead of creating png or jpegs for these, it’s better to use font icons as they are smaller in size. There are a lot of CSS frameworks available that offer font icons.
4. Code Splitting
A big application needs a big code base by which when loaded on a page, may take some time. As a result, users need to wait a little longer before they can see something on a page. This is where dynamic chunking comes into play.
Dynamic chunking is a way of splitting the code into various chunks or bundles that can be loaded on-demand or in parallel. Instead of loading a big chunk of code where some of it is unnecessary, developers can split the code and load them only when needed. The chunks will be smaller in terms of size and can be loaded fast by the browser.
5. Lazy Load Scripts and Images
An application is composed of features and most of the time, features are handled by scripts to work. There are times that the scripts are big and can consume page performance. These scripts can hinder a page’s first contentful paint or even delay the page render.
As a solution, we need to lazy load them so that scripts will only be mounted to the application when the user needs it. In this way, we can avoid unnecessary script execution on the page and it may can load the page faster.
6. DOM Tree Size
Creating a web application requires a user interface which we can achieve with HTML and CSS. Most of the time, we code things as per design requirements without thinking about the size of the DOM (Document Object Model). Sometimes, we create nested elements instead of just one element to fulfill the design requirements. These incidents cause the DOM to bloat and will be flagged as a cause of performance degradation.
As a standard, DOM size should not exceed 1500 nodes. Creating a page with more than the recommended number of nodes will affect the time of the page to load. In addition to this, a large number of nodes will affect runtime performance as the webpage recomputes the position and node styling whenever the user interacts with it.
There are several ways to solve this issue:
- Check redundant HTML codes. Optimize the HTML structure as much as possible, if you think a design can be achieved without nesting elements, please go ahead and remove the overheads.
- On page load, it’s better that the UI displayed to the user is the only DOM loaded on the page because it’s unnecessary to load a DOM that’s part of the last section of the page.
- Check for any 3rd party plugin that creates a large DOM Size, try to replace it with other plugins.
4. If you’re using a Javascript Framework, lazyload components/widgets only when needed.
6. Windowing
There may be times where you need to display a large table or list that contains many rows. Loading every single item on such a list can affect performance significantly.
List virtualization, or “windowing”, is the concept of only rendering what is visible to the user. The number of elements that are rendered at first is a very small subset of the entire list and the “window” of visible content moves when the user continues to scroll. This improves both the rendering and scrolling performance of the list.
DOM nodes that exit the “window” are recycled, or immediately replaced with newer elements as the user scrolls down the list. This keeps the number of all rendered elements specific to the size of the window.
Good Reference here
7. Assets Compression
Compression is a simple, effective way to save bandwidth and speed up your site.
The tricky part of this exchange is the browser and server knowing it’s ok to send a zipped file over. The agreement has two parts
The browser sends a header telling the server it accepts compressed content (gzip and deflate are two compression schemes): Accept-Encoding: gzip, deflate
The server sends a response if the content is compressed: Content-Encoding: gzip
If the server doesn’t send the content-encoding response header, it means the file is not compressed (the default on many servers). The “Accept-encoding” header is just a request by the browser, not a demand. If the server doesn’t want to send back compressed content, the browser has to make do with the heavy regular version.
Verify Your Compression
In Chrome, open the Developer Tools > Network Tab (Firefox/IE will be similar). Refresh your page, and click the network line for the page itself (i.e., www.airasia.com). The header “Content-encoding: gzip” means the contents were sent compressed.
8. Service Workers
Using Workbox, we implemented our service workers. It was too seamless to use this plugin.
Service workers essentially act as proxy servers that sit between web applications, the browser, and the network (when available). They are intended, among other things, to enable the creation of effective offline experiences, intercept network requests and take appropriate action based on whether the network is available, and update assets residing on the server. They will also allow access to push notifications and background sync APIs.
A service worker, written in JavaScript, is like a client-side proxy and puts you in control of the cache and how to respond to resource requests. By pre-caching key resources, you can eliminate the dependence on the network, ensuring an instant and reliable experience for your users.
Workbox lets you trade complexity for flexibility.
Well, I’m glad you asked. Workbox is a flexible well-defined PWA library that wraps the boilerplate code with methods that developers can use to implement service worker functionality. Out-of-box, it is production-ready with features such as precaching, runtime caching, caching strategies, request routing, etc. As you may know, implementing the service worker is the heart of a PWA. If implemented correctly, the web application could be faster and reliable; but if implemented incorrectly, it can potentially lead to a disaster. As is said, service workers come with great power, but with great power comes a cost and complexity.
Workbox is a set of libraries that can power a production-ready service worker for your Progressive Web App.
There are some caching strategies provided by workbox as follows:
- StaleWhileRevalidate
- CacheFirst
- NetworkFirst
- NetworkOnly
- CacheOnly
To learn more, please read here
9. If possible, stop Supporting IE
For the past couple of years, we supported IE even though the possible portion of users nowadays is very small. I guess you’ve only used IE to download modern browsers right? We’re not saying IE is very bad, but in reality, people tend to use browsers that are faster like Google Chrome, Firefox, and Safari.
It’s a challenge for us especially in the design part to make the design as close as possible from the modern browsers. Some javascript functions also don’t work in IE, thus, we’ve used polyfills. The small snippet of codes and polyfills somehow impacts the file size of the build. It’s not that big, but still, an additional byte or kilobytes can affect page performance.
10. Server Side Rendering
Server Side Rendering means that the app or page would be rendered on the server.
- Faster initial page load time — This provides a good user experience.
- Better SEO — Due to the faster initial load time, search engine bots can crawl and index pages better.
- Optimal for users with a slow internet connection — They can see the rendered HTML while the JS is processing.
11. Pure Components in React
Pure Components in React are the components that do not re-renders when the value of state and props has been updated with the same values. If the value of the previous state or props and the new state or props is the same, the component is not re-rendered. Pure Components restricts the re-rendering ensuring the higher performance of the Component
Features of React Pure Components
- Prevents re-rendering of Component if props or state is the same
- Takes care of “shouldComponentUpdate” implicitly
- State and Props are Shallow Compared
- Pure Components are more performant in certain cases
12. LightHouse vs Page speed insights
LightHouse
Google PageSpeed
It uses lab data (only) to measure your website’s performance, but also its SEO performance, PWA, and other best practices.
Google PageSpeed will use both real-world data available in the Chrome User Experience report and lab data.
Lighthouse is an open source tool that will help you measure the performance of your site as well as to identify the factors affecting it. In addition to this, it will also give you recommendations on how to improve your website performance. Below is a screenshot of a lighthouse report
You can also click each summary to view the full details just like this
Lighthouse report is consists of different information such as the following
- Performance
- Metrics to measure page performance
- Opportunities for improvement
- Diagnostics that provides more information about the application’s performance
- Accessibility
- Measures the accessibility feature of the page
- Best Practices
- Checks if your page adheres to industry standards as well as recommendations on how to follow such standards
- SEO
- Check if your application is optimized for search engines results ranking.
- Lists down steps to make your website SEO friendly
- PWA (Progressive Web Application)
- Tests your application for PWA capabilities
All of the information can be used to check the application’s weakness and bottlenecks and let the developers enhance it for a better and faster website.
13. CDN Usage
You can use content delivery network (CDN) to deliver content to users from the nodes that are nearest to them, accelerating the response to user requests and increasing the response rate. CDN also resolves the delivery latency problem that is usually caused by distribution, bandwidth, and server performance issues. CDN has been applied in multiple scenarios, including site acceleration, on-demand streaming, and live streaming.
14. Memoization
Another approach to make things faster for an application is memoization. It is a technique wherein it stores the results of an “expensive function call” and eventually throws the cached results back when the same input is used to that function call. An expensive function call that has been mentioned is a function that spends huge time and memory in the application.
In the React world, we have what we call React.memo that checks for prop changes and eventually skips rendering and reuses the last rendered result when no changes are to be found. Beware though, don’t use React.memo to prevent rendering of components as it will lead to bugs.
In the above example, both Card and MemoizedCard throws the same result. However, MemoizedCard reuses the memoized content as long as the properties suite and number are not changing. With this, react will not perform virtual DOM difference checks which eventually leads to a performance boost of the application.
15. Async and Defer
Loading javascript as some of us know, can block HTML rendering and parsing, thus, making First Contentful Paint much longer. As soon as the browser runs into a script tag, it will halt HTML parsing until such time that the javascript is loaded and executed. Of course, we’re not in control of how fast the javascript will load as many factors will come into play such as network speed and javascript file size among others.
A simple trick we can use is by adding async and defer attributes to the script tag.
Putting the async attribute into the script tag will make the script be downloaded asynchronously. Meaning, it will not block the HTML parsing and continue its fetching in the background. HTML parsing will only be paused after the script is downloaded and start executing.
In the same manner, defer will also download the script in the background; however, it will only execute after HTML parsing is completed.
Both this approach will help you make HTML parsing faster hence, will shorten the time the user sees a blank screen while your page is loading.
16. Production Mode
Another way to make the application run at its best is by making sure you’ve built it in production mode. Production mode is a build where code is being uglified, minified, and tree shook. It’s a way to make sure only the necessary codes are included in the build which eventually makes the file size smaller.
When running development mode in React, it includes plenty of warnings which are useful in development, however, it makes the application bigger and slower. These things can be removed when using the production build.
If you’re uncertain about how your application is built, you can use the React Developer tools for Chrome. Once installed, you can visit your application and check for the following
Icon with dark background indicates that the application is running in production mode, otherwise, you’ll see an icon with red background just like this
17. Understand your technology
Lastly, try to learn and understand deeply the technology you’re using. Let’s say you’ve followed all the tips that we’ve mentioned in this article, but if you’re not knowledgeable enough about the framework, programming language, or technology you’re using, then you will still end up having performance issues. Understanding the technology fully will help you utilize the functionalities that it can offer, the process of how it works, and even possible methods or techniques that can make your development easier. As of now, most programming languages or frameworks have their way to optimize things and make the application faster; so take your time, read the documentation or even watch tutorial videos that can help you create a faster and reliable application.