How Overloop sped up The Orchards’ Web App by 85%

Context

The Orchard is a large music distributor with 1000s of labels and concurrent users on their main SaaS application, Workstation. The codebase is and has been growing for over 20 years.


The Problem

As mentioned above, The Orchard has a huge catalogue. This has led to their homepage of their client-facing application Workstation taking around 10-20 seconds to load, depending on the location of the user. These pain points were not restricted to just the homepage. Navigating to other pages in Workstation also took 7-15 seconds, depending on where the user went next.


Analysis

We worked out that the page was served up by PHP. The PHP loaded some data to display in the original HTML. Additionally, when the page was loaded in the browser, it included 4 separate react components, all of which needed to initialise and load in the user data, the user’s feature flags and then load additional data.

The webpack bundles for the 4 react components were built separately and each bundle included the same shared libraries, resulting in 10+ MB of javascript being downloaded. As the user moved from the home page to other pages, each new page would start with a new request to a different PHP controller, which would take at least 2-3 seconds to serve up even a minimal page. 

We then used Chrome performance tools to analyze the contents of the Javascript and CSS bundles and ascertain which percentage of those bundles was actually used. This indicated that most of Javascript were never executed and that less than 90% of the CSS was used. This included around 1 MB of the localization logic for the moment.js and react-intl libraries and other such large chunks of library code.

Many of the pages in Workstation had already been moved to react, by building dedicated react components that could slot in between the navbar at the top and the footer at the bottom of the page. All these react components required a common initialization process that passed in a session token to then talk to the various microservices.


 
Analysis of performance

Analysis of performance

 

Solution

We proceeded to work with Orchard engineers to start the process of moving Workstation to a single-page application.

Starting by trimming the PHP controller down to the absolute minimum to serve up a page with no HTML on it. This could now return an empty page in 1.5 seconds. This page would load the common dependencies (moment, react, react-bootstrap, shared CSS etc). We then built a react application that could render the entire page, including the navbar and the footer. This allowed us to reuse the existing Orchard react components, so we would not need to rebuild those elements.

To fill in the HTML between the navbar and the footer we worked with Orchard engineers to come up with an approach to have different paths in the single-page app load the different react components. This way, as the user moves around the site, the relevant code for each page is loaded as it is needed.

For the homepage, we replaced the 6 PHP components and 4 separate react components with one react component that would render the entire homepage. Because we no longer needed to wait for PHP to load data like the most recently edited projects, the entire page could load much faster.

 
Webpack Analysis of bundled app

Webpack Analysis of bundled app

 

Once we had all the React components being loaded from one React Application, two problems that became apparent after analyzing the bundle with webpack-bundle-analyzer. The image above shows the analysis of the bundled app.


Problem 1:

The pre-existing React components were being imported from other repositories as dependencies. Due to those repositories using the same common dependencies (i.e. react, react-intl, moment, react-bootstrap, bluebird) but not declaring them as external dependencies, they would end up being loaded multiple times.

Solution:

Refactor those repositories’ webpack configurations to avoid bundling those dependencies and load them once from the newly created React Application.

Problem 2:

For libraries that include locales, namely moment and react-intl,  all of the locales were being bundled, despite the app providing options for a much smaller subset of those.

Solution:

Configure webpack to include a specific list of locales, which would drastically reduce the bundle size.

Further steps

After we got the homepage loading times from 10-20 seconds to under 3 seconds, we laid out a plan to get other pages within Workstation to migrate from stand-alone PHP-rendered pages into the new single page application.



Alex - Engineer at Overloop