A case study of changes the YouTube Web team made to improve performance, increase their Core Web Vitals pass rates and lift key business metrics.
The Chrome team often talks about "building a
better
web", but what does that
mean? Web experiences should be
fast
,
accessible
, and use
device
capabilities
in the moment when users need it most.
Dogfooding
is part of Google's culture, so the Chrome team has partnered with
YouTube to share lessons learned along the way in a new series called, "Building
a better web". The first part of the series will dive into how YouTube built a
faster web experience.
Building a faster web
At YouTube,
performance
relates to how fast videos and other content?such as
recommendations and comments?load on web pages. Performance is also measured by how quickly YouTube
responds to user interactions such as search, player control, likes, and shares.
Growing developing markets, such as Brazil, India, and Indonesia are important
for YouTube mobile web. Because many users in these regions have slower devices
and limited network bandwidth, ensuring a fast and seamless experience is a
critical goal.
To provide an inclusive experience for all users, YouTube set out to improve
performance metrics such as
Core Web Vitals
through lazy-loading and code
modernization.
Improving Core Web Vitals
To identify areas of improvement, the YouTube team used the
Chrome User Experience Report (CrUX)
to see how real users were experiencing video watch and search result pages on
mobile in
the
field
. They
realized their Core Web Vitals metrics had a lot of room for improvement, with
their
Largest Contentful Paint (LCP)
metric clocking in
at 4-6 seconds in some cases. This was substantially higher than their target of
2.5 seconds.
To identify areas for improvement, they turned to
Lighthouse
to audit
the YouTube watch pages, revealing a low Lighthouse
(
lab
) score with a
First Contentful Paint (FCP) of 3.5 seconds and a LCP of 8.5 seconds.
To optimize FCP and LCP, the YouTube team dove into several experiments,
resulting in two big discoveries.
The first discovery was that they could improve performance by moving the HTML for the Video Player above the script that makes the Video Player interactive. Lab tests indicated that this could improve both FCP and LCP from 4.4 seconds to 1.1 seconds.
The second discovery was that LCP only
considers
<video>
element poster images and not frames from the video stream itself. YouTube has traditionally optimized for the fastest time until the video starts playing, so to improve LCP the team started also optimizing how quickly they could deliver their poster image. They experimented with a few variations of poster images and picked the one that scored the best in user testing. As a result of this work, both FCP and LCP showed marked improvement, with field LCP improving from 4.6 seconds to 2.0 seconds.
While these optimizations did improve LCP, the team felt that the current definition of the LCP metric wasn't fully capturing, from the user's perspective, when the "main content" of the page had loaded?which is the goal of LCP.
To address these concerns, members of the YouTube team partnered with members of the Chrome team to explore ways that the LCP metric could be improved to address their use case. After considering the feasibility and impact of a few options, the teams landed on a
proposal
to consider the paint time of the first frame of a video element as an LCP candidate.
Once this change lands in Chrome, the YouTube team is excited to continue their work optimizing for LCP. And the updated version of the metric will mean these optimizations will have a more direct impact on real-user experiences.
Modularization with lazy loading
YouTube pages contained many modules that were eagerly loaded. To optimize how
50+ components were rendered, the team built a component to JS module map that
would tell the client which modules to load. By marking components as lazy, the
JS modules would load later, reducing the initial load time of the page and the
amount of unused Javascript sent to the client.
However, after lazy loading was implemented, the team noticed a waterfall effect
that lazy loaded components and their dependencies would load at suboptimal
times.
To solve this problem, the team determined the minimal set of components needed
in a view and batched them in a single network request. The results were
improved page speed, reduced JavaScript parse time, and, ultimately, better
initial rendering times.
State-management across components
YouTube was experiencing performance issues due to its player controls,
especially on older devices. Code analysis showed that the player, which allows
users to control features such as playback speed and progress, had become
over-componentized over time.
Each progress bar touch-move event triggered two
extra style recalculations and took 21.17 ms during performance test runs in the lab. As new controls were added over time, the pattern of decentralized control would often cause circular dependencies and memory leaks, negatively impacting watch page performance.
To fix the issues due to decentralized control, the team updated the player UI
to synchronize all updates, essentially refactoring the player to one top-level
component that would pass down data to its children. This ensured only one UI
update (render) cycle for any state change, eliminating chained updates. The new
player progress bar touch-move event has no style recalculations during its
JavaScript execution and now only requires 25% the time of the old player.
This code modernization also resulted in additional performance improvements
such as improved watch load times on old devices, fewer abandoned playbacks, and
a reduced number of non-fatal errors.
Conclusion
As a result of YouTube's investment in performance, watch pages load much faster with 76% of YouTube's mobile website URLs now passing Core Web Vitals metric thresholds in the field. On desktop, lab LCP for the watch page was reduced from approximately 4.6 seconds to 1.6 seconds. Interaction and rendering performance of the site, especially on the YouTube video player, are seeing up to 75% less time spent in JavaScript execution than before.
Improvements to the performance of YouTube web over the last year have also improved business metrics, including watch time and daily active users. Based on the success of these efforts, we plan to continue exploring even more ways to optimize in the future.
In part two of this series, "Building an accessible web", you’ll read how YouTube made their website more accessible for screen-reader users.
With special thanks to Gilberto Cocchi, Lauren Usui, Benji Bear, Bo Aye, Bogdan Balas, Kenny Tran, Matthew Smith, Phil Harnish, Leena Sahoni, Jeremy Wagner, Philip Walton, Harleen Batra and both the YouTube and Chrome teams for their contributions to this work.