Technology

Performance is a Marathon: Successful tactics for web page performance

September 13, 2018

This blog post was co-authored by Rob Walker, Anatolii Gorovyi and Bilal Khan. 

In our post last week we discussed what it takes from an organizational and team perspective to consistently improve performance site wide. Today we’ll walk through our tactics, the results we’ve achieved so far and what the future holds for our team’s ongoing quest to optimize web page performance and improve our customer’s experience. 

Step 1: Research 

We began with Google Lighthouse - it has been and continues to be the key tool throughout our entire journey, outlining opportunities for us to improve our performance. There is a large volume of documentation through Google, with posts and articles that explain the work that needs to be done to address specific issues. 

Lighthouse was the stepping stone that provided information and opportunities for us to prioritize. We worked with another TELUS Digital team that had already run a number of tests and were able to prioritize their recommendations as well as our own ideas. This team also updated our Lighthouse settings in order to customize it for our specific goals.

When it came to outside documentation, there is no end to the excellent content being constantly created around performance. We continue to read use-cases, blog posts and other documentation along with helpful videos. 

List of useful articles and videos:

Twitter also became a useful place to see discussions happening in real time around the issue of performance. Long, detailed conversations around performance are continually happening and became resources that provided both helpful context and links to more documentation and articles.

Developers to follow: 

@addyosmani, @paul_irish, @igrigorik, @DasSurma, @malchata, @dan_abramov. Also, any developer or maintainer of Open Source Software your team is using are using very likely sharing a lot of valuable information on Twitter.

Step 2: The Work

As mentioned in part one, we approach performance optimization through the lens of incremental innovation. This includes a series of phases where we break down the various approaches and prioritize them based on Lighthouse suggestions that would have the most significant impact on performance score.

But before we could go through performance implementations, there was some foundational work that had to be done:

  1. We upgraded the version of React library from 15 to 16 as its core was rewritten with React Fiber that allowed the library to become more performant in its future iterations.

  2. We upgraded Node.js from version 6 to version 8.

  3. We upgraded Webpack from version 2 to version 4 which made code-splitting easier.

These changes were required before we could start working on any performance optimizations. 

Phase 1: Lazy load all images

The component that allowed this refactoring was developed internally at TELUS Digital - we then had to upgrade the version of this component and ensure all images are lazy-loaded.

Performance gain: 5-8 points.

Phase 2: Web Fonts

This was an almost hidden opportunity in the Lighthouse report, appearing at the bottom of the report and also collapsed. It turned out that web fonts were drastically impacting our performance across all of telus.com. We implemented a “font-display: swap” css feature that swaps a font for a system font until the web font is downloaded.

Performance gain: Over a second gained on First Meaningful Paint ~ 5 points.

Phase 3: Adobe Launch

The analytics team upgraded Adobe DTM scripts to Adobe Launch - this allowed us to load analytics scripts asynchronously in order to prevent render blocking and get to First Meaningful Paint faster.

Performance gain: Improved First Meaningful Paint by 1 second. ~ 5 points.

Phase 4: Component-Based Code Splitting

This is the phase that required the most amount of time for research and experimentation. The general idea of code splitting is to reduce the amount of JavaScript loaded on each page and only load what is required. JavaScript happens to be the most expensive resource when it comes to performance. This was highlighted in almost every article or video we went through.

First, we wanted to find out how much JavaScript we ship for each page and how the initial code-splitting was set up. The most useful tool in this research without a doubt was Webpack Bundle Analyzer. It showed all the mistakes that were previously made on how we were splitting vendor code (open source libraries) from our main bundle (code that we wrote). With a few tweaks in Webpack configuration, this problem was resolved but we still needed to split our main bundle into smaller chunks. That’s where we decided to use component-based code-splitting strategy.

We have a full library of React Components combinations which vary from page to page. Currently, there are about 55 components in our library and this number grows with new requirements, making our main JavaScript bundle larger. With Webpack 4, dynamic imports, and react-loadable library we were able to implement component-based code-splitting. Now we are loading only the JavaScript that is required by a web page.

Results: Total JavaScript shipped for each page ~ 220 KB vs 458 KB (before code-splitting).

Performance gain: Reduced the Time to Interactive between 2 - 3 seconds ~ 5 points.

Phase 5: Inline CSS

The latest phase in our performance journey was inlining CSS that was also split per component. Inlining CSS gave us an ability to improve our critical rendering path by avoiding extra server requests to CSS files.

Performance gain: First Meaningful Paint was reduced to 1.2 seconds on average! ~ 8-10 points.

We also paired with the Site Builder team which manages almost 500 TELUS web pages in order to help them implement font swapping and inline CSS. That had an enormous impact on the overall average Performance Score. Each Site Builder web page benefitted from extra 10 Performance Lighthouse points on average.

The Results

Here’s where we started:

Here’s where we are at today:

What’s Next

Page specific

All these Phases are not the end of our performance work and there are still some opportunities for improvements. As we’ve said before, this is an ongoing journey of research, testing and optimization for the entire TELUS digital team. 

Next we’ll be investigating which pages are performing worse than others and analyze what can be improved. Sometimes it’s not only the code that makes the websites faster - sometimes we need to analyze the quality and amount of our content, as well.

Follow us on Twitter, Instagram, and LinkedIn to stay up-to-date on the latest TELUS Digital news.


About the authors:

Anatolii Gorovyi is a Senior Full Stack JavaScript Developer at TELUS Digital. He is passionate about Front End Development, never stops learning and cares a lot about making better user experiences for everyone.

Rob Walker is a Senior Content Strategist at TELUS Digital. He spends his time understanding how the Internet works in order to make it a better experience for everybody else.

Bilal Khan is a Senior Product Manager at TELUS Digital. He is excited about enabling his teammates for success, solving problems, and delivering value to our customers.

Anatolii