Asset Loading Performance

When developing a Single Page Application (SPA), all the application logic will be run only on the browser. As Application grows over time, so the size of assets (js, css, images).

As mentioned in this blog post even today, lots of famous apps loads more asset to perform main action. It is always crucial to optimise the amount of asset required to render page of an application.

💡
This post mainly focuses on optimizations steps with respect to SPA context

Let's see different options available to improve the page loading speed

  1. Reducing the number of assets itself

  2. Deprioritising assets which are not required at the moment

  3. Loading assets only when required

  4. Effective caching

Reducing the number of assets itself

What do I mean by that, when the page requires more number of asserts to display the content, the number of request to the server to fetch asserts increases. As the number of requests increases the network latency piles up. This all adds up the delay to see the content of page.

Here is where webpack chunk grouping plugin comes handy.

We can group chunks based on following factors

  1. File size

  2. File path

  3. Purpose

we can group all vendor modules into one chunk based on file size.
Or We can create a group per module. Eg: We can create group for SignIn Module and another one for Profile Module.

Here is the webpack chunk splitting configuration to split based on the modules and vendor files.

Deprioritising assets which are not required at the moment

In this step we will categorise the resources based on the priority. You need to basically get Yes response to following question.
"Does this resource really contributes to the information that user currently seeing?"

If not, we can deprioritize it using one of below ways.

  1. In HTML we have got loading attribute to inform when to load images and iframe.
<img loading="lazy" src="image.jpg" alt="..." />
<iframe loading="lazy" src="video-player.html" title="..."></iframe>

This will load resource only when the resource comes into view. refer here for detailed explaination.

Loading assets only when required

We can leverage the dynamic module loading of javascript to defer loading resources until it is needed. Here small example loading profile details only when user hover over the profile picture. This will make the profile component to not to participate in initial chunk loading.

import { lazy } from 'react';

const ProfileComponent = lazy(() => import('./ProfileComponent.js'));

function HomeComponent() {
    return (
        ...
        { isProfileHovered && <ProfileComponent /> }
        ...
    )
}

We can also leverage the resource hint feature that insists the browser to load the files in parallel to the actual src files. here is the detailed article to refer on that aspect. This will reduce the time to load the resource.

Effective Caching

The first step before implementing caching is that we have to decide what to cache.

We need to split the resources in a way that we can differentiate less frequently changing resource with resource that will change more frequently so that we can effectively utilise the both long term and short term caching.

In the above example of chunk splitting code, we demonstrated we moved all the less frequently changing resource like vendor modules and design system into separate chunk so we can cache them longer duration. On the other hand all the application level code which we will change on a daily basis we moved it out for short term cache.

Choosing what to move into long term cache and what to move inside short term cache is purely use case driver.