Where Everything Began - First Act
"Knowledge is like money: to be of value it must circulate, and in circulating it can increase in quantity and, hopefully, in value." ~ Louis L'Amour
In February, I had a task to improve the performance of an NFT marketplace. I had surface knowledge of web performance at the time. I spent an insane amount of time researching and watching tech talks on videos. I decided to write this article to make the journey easier for you.
The Portal π¨πΏπ»
Aimlessly looking for answers with a gazillion tabs open, my PC freezes with no solution in sight. I decide to shut down my PC and then go out for a walk to clear my thoughts.
I return 30 minutes later to find a strange blue light emitting from my room. It was coming from my PC which was still on but frozen. I try long pressing the power button but I end up getting sucked into the screen.
The Giant Robot π€
I wake up in a weird-looking room then I immediately get approached by a giant robot with the letters HTML
on its chest.
π€ Robot: Hi, I'm HTML5
. I'm glad you woke up, welcome to Renderland!
π¦πΏ Me: Where am I?
π€ Robot: You're in Renderland
.
π¦πΏ Me: Render what???
What is Renderland? π€
Renderland is the planet on which Rendering
takes place. It's the closest planet to the screen
and it's what users see and interact with. It's located in the Browser's Solar System
which is also under the The Web Galaxy
.
This diagram shows how a typical request
travels through the internet where it finally reaches a server
which sends back a response
to the client.
The response manifests different entities such as Styles
, Markup
, Scripts
, Fonts
, and other files
. They represent the different life forms on Renderland. They live together to make up the content that you see and interact with.
The Citizens of Renderland πͺ
HTML, the planet's elder summoned us all for a meeting under the Sacred Tree
.
π€ Robot 1 I'm HTML
, you've probably met my grandson, HTLM5
. We're both from the Markup
tribe and we make up the content of pages on the web.
π€ Robot 2 I'm CSS
from the Styles
tribe, and we give web pages looks and style
.
π€ Robot 3 I'm JavaScript
but you can call me JS
, I'm from the Scripts
tribe- no relation, and we practice making web pages interactive.
π€ HTML A prophecy spoke of a FullSnack Engineer
with a mechanical keyboard and an E mark who'd save Renderland. The Engineer spoke an ancient language called Code
.
π€ JS We believe you're the chosen one.
Renderland's History π°
Long ago, the robots lived in a faraway land known as ServerLand
where they served a group of entities called clients
. The clients lived in ClientLand
and they all had different shapes and sizes.
A Serverland
native is referred to as server
and a Clientland
native is referred to as client
.
The request-response-cycle
is a model that describes how clients and servers communicate over a network via a protocol
such as HTTP
or Web Sockets
.
Rendering
Rendering is the process of turning a web page's assets (HTML, CSS, JSS, and other static assets) into interactive content on the browser. Rendering steps include style, layout, paint, and, in some cases, compositing.
Critical Rendering Path (CRP) π£
The Critical Rendering Path is the sequence of steps the browser goes through to convert the HTML, CSS, and JavaScript into actually visible pixels on the screen.
The Render Tree π²
HTML5
and CSS
then summoned me to the Sacred Tree
. They began explaining the history of the tree and how it came to life.
Document Object Model (DOM) describes the structure browsers use to represent HTML elements internally.
CSS Object Model (CSSOM) describes the structure browsers use to represent CSS styles internally.
Both are represented internally as a tree-like structure that allows programs to interact with the CSS and HTML content of a web page.
The Render Tree is the product of combining DOM
and CSSOM
trees. It defines the structure of a web page. The tree contains only the visible elements of a web page.
The browser calculates the layout
of each visible element and then paints
it on the screen with the help of the Render Tree.
Layout (Reflow) πΊ
Browser computes the geometry of the layout and its elements based on the render tree.
Paint π¨
Browser paints pixel by pixel to create the visual representation we see on the screen. Using the Render Tree, the browser engine calculates the position of each visible element of a web page.
Rendering in Short
-
Assets Converting the web page's HTML and CSS code into
DOM
andCSSOM
. -
Render Tree Constructing the Render Tree by combining
DOM
andCSSOM
. -
Layout Calculate the size and position of each
node
. -
Paint painting
elements
on the browser's screen for users to view.
Rendering Patterns
The robots then began explaining how rendering
is practiced in Renderland.
Server Side Rendering (SSR) π
The most ancient form of Rendering. This pattern generates the full HTML for the page content to be rendered in response to a user request.
Client Side Rendering (CSR) π»
This form of rendering became popular during the Ajax
era in 2005. Ajax which stands for Asynchronous JavaScript and XML
allowed developers to build client-side applications.
In this pattern, the server renders a skeleton of an HTML container whilst the client handles the logic required to render a web page. The client takes care of fetching, templating, routing, etc.
Guardians of Renderland (The Pillars πΊ)
Also known as the Web's Vitals
, they are Renderland's guardians of performance. They measure and report any issues that may affect the performance of a web page.
This screenshot is from Lighthouse's
report on Hashnode's home page.
First Pillar (First Byte) 1
This Pillar is responsible for reporting the arrival of the very first byte of incoming data. It helps quantity a server's response time by measuring the latency of a round trip to and from said server. It precedes every other Pillar.
Time to First Byte (TTFB) The time between the initial request and the arrival of the first byte.
Second Pillar (Paint) π¨
This Pillar measures the time a browser takes to paint pixels on a screen. The shorter the time, the better the performance.
First Paint (FP)
The first instance of content that appears on the browser. Think of it as the first drop of water when you open the tap.
First Contentful Paint (FCP)
Measures how long it takes the browser to render the first piece of DOM content after a user navigates to your page.
π‘ The recommended FCP
score is 1.8 seconds or less
Largest Contentful Paint (LCP)
The time when the main page content becomes visible. It consists of the initial HTML document + LCP
Resource.
π‘ The recommended LCP
score is 2.5 seconds or less
Third Pillar (Time to Interactive) π¬
Also known as (TTI), represents the state at which a web page is ready to respond to events and user interactions. This is made possible when all the Scripts
tribe members have arrived/loaded.
TTI is reached only after FCP. Having a huge gap between these two metrics causes serious problems.
π‘ The recommended TTI
score is 3.8 seconds or less
Total Blocking Time (TBT)
The total amount of time between FCP and TTI. It means that the event handlers are registered for most visible page elements, and the page responds to user interactions within 50 milliseconds.
π‘ The recommended TBT
score is 200 milliseconds or less
Attack on Renderland πΎ - Second Act
"If you know the enemy and know yourself, you need not fear the result of a hundred battles. If you know yourself but not the enemy, for every victory gained you will also suffer a defeat. If you know neither the enemy nor yourself, you will succumb in every battle." - Sun Tzu, The Art of War.
We receive multiple reports from different locations. Web pages are unresponsive, some fail to load and others are painfully slow.
It was later revealed that Renderland is being invaded by an intelligent species of bugs
. They came in different shapes and sizes and wreaked havoc on the planet.
Bugs πΎ vs Pillars πΊ
The bugs have directed their first attack on the pillars. Let's see how each metric affects performance.
First Pillar (First Byte) 1
The bugs that affect this network usually manifest in the form of network
or device
issues.
The following factors may affect TTFB
- The Network protocol, HTTP/1 instead of HTTP/2 for example.
- Longer network
request phases
. You can learn more about this here.
Second Pillar (Paint) π¨
This metric mainly reports performance issues related to static/viewable content. The bugs that affect this metric usually manifest in the form of unoptimized assets such as HTML
, CSS
, and images.
Third Pillar (Interactivity) π¬
The bugs that affect this pillar mainly focus on scripts
since it focuses on issues related to the interactivity/usability of a web page. Unoptimized JavaScript is the biggest offender in this category because it needs to be parsed and compiled before it's finally executed.
Miscellaneous Performance Bottlenecks
These are some of the most common web performance bottlenecks.
Blocking Resources
These include the scripts, styles, and HTML imports that block or delay the browser from rendering content to the screen.
Bundle Size
This is the amount of JavaScript a user will have to download to load your website. A larger bundle size means users will have to wait longer before they could interact with your site.
Network Requests
Enormous network payloads reduce the application's performance. Also, higher latencies make requests take longer to travel to and from the server.
DOM/CSSOM Bottlenecks
- Event handlers are costly.
- Layout thrashing and reflows cause re-renders meaning the browser will have to recalculate and re-paint content with every reflow.
The Resistance - Final Act
"With great power comes great responsibility."
As developers, we must make sure that the apps we build are performant and resilient. This section will equip you with new superpowers to assume this role.
Measuring Performance
To defeat the bugs
, we need fully understand to how to measure the impact of their attacks on performance.
π‘ How is performance measured?
- Field Testing Involves real users loading and interacting with the page.
- Lab Testing Using tools to simulate a page load in a predictable environment.
Field Testing
Also known as Real user monitoring (RUM)
refers to the process of recording user interactions on a production website.
Examples of RUM
software: InfluxDB, Google Analytics, CloudFlare, Stackify, etc.
This topic is beyond the scope of this article so we'll jump right into Lab Testing
.
Lab Testing
Refers to the process of testing an application in an environment such as development
or staging
before the site is released to the public.
Rescuing the Pillars
Learning how to measure the performance of a website was the first step. Now we need to learn how to optimize the metrics we measured.
First Pillar (First Byte) 1
This metric indicates how fast or slow a server is. It measures the latency of a round trip to and from a server.
π‘ Measuring TTFB
- Field Web Vitals Library or Chrome's User Experience Report.
-
Lab The
Developer Tools
panel in web browsers or Web Page Test.
How to improve TTFB
- Better server infrastructure (Using Load Balancers and Caches) for example.
- Pre-connect to required origins for cross-origin resources.
- Using HTTP2 if possible.
Second Pillar (Paint) π¨
Asset optimization can play a huge role in improving this performance metric. Let's see how we can accomplish this.
π‘ Measuring Paint Metrics
- Field Web Vitals Library or Chrome's User Experience Report.
-
Lab The
Developer Tools
panel in web browsers or Web Page Test.
How to improveFCP
- Eliminate render-blocking resources.
- Minify CSS and remove unused JavaScript code.
- Reduce
TTFB
. - Avoid enormous network loads and
pre-load
crucial requests. - Serve static assets with an efficient cache policy.
How to improve LCP
- Reduce
TTFB
. - Optimize resource load times, for example compressing images, serving them in different sizes, using a
CDN
, etc. - Optimizing CSS, for example compressing, removing unused CSS and deferring non-critical CSS.
- Shortening the Critical Rendering Path (CRP).
- Deferring non-critical scripts and add scripts to the body of the HTML document.
Third Pillar (Time to Interactive) π¬
You might be familiar with JavaScript's single thread nature, if not then this article might be a great resource for you.
π‘ What is a Main Thread?
The main thread is where a browser processes user events and paints. The browser uses a single thread to run a page's JavaScript, as well as the Critical Rendering Path. The browser may not respond to user interactions if the main thread is blocked/occupied by another process
.
How to improve TTI
1. Minimizing Main thread's work
We run most of our code on the main thread. Lifting off the burden or delegating some of this work to another Service
can increase the performance of a web page.
2. Debouncing Events
Delaying the execution of event handlers can increase performance because it helps the browser avoid fast consecutive events. These events can block frames from completing, and can cause additional and unnecessary layout work.
3. Web Workers
Web workers can be used to delegate complex processes and run tasks in the background in a separate thread.
4. Minification
Minifying and deferring non-critical CSS
/JavaScript
can increase a web page's performance.
5. Code Splitting
Means the browser will only download the JavaScript users need at the time. For example, let's consider a web app with three pages, namely home
, chat
and notifications
. Code-splitting allows you to download only the JavaScript relevant to your home page and then download the remaining assets on-demand or when a user navigates to a page that actually needs.
6. Event Delegation
Propagating or bubbling up an event in the hierarchy of the DOM tree can increase a web page's performance.
Additional Rendering Patterns
We've previously discussed the two main rendering patterns, namely Client Side Rendering (CSR
) and Server Side Rendering (SSR)
. Now it's time to introduce some new rendering patterns that combine the best of the two worlds.
SSR
with Rehydration π¨
This pattern uses a pre-built
DOM with components rendered as HTML. The app then loads the remaining data in the client side.
CSR with Pre-rendering π§
This pattern renders an app shell
to static HTML during build time .
Miscellaneous Performance Tips
- Detect and eliminate unnecessary re-renders. Why did you render is a great library if you're building an app using
React
. - Memoize values with React.memo/callbacks.
- Analyze your packages if you're using
WebPack
. WebPack Bundle Analyzer is a great choice. I've personally used it to improve the performance of an NFT marketplace.
Conclusion
Choosing the right tool for the job is a critical skill for every Software Engineer. Software choices are usually determined by the project's requirements.
Resources π
- Web Performance Fundamentals by Todd Gardener.
- Chrome Developers Blog.
- Web Dev.
- Annie Sullivan | Lessons learned from performance monitoring in Chrome.
- Aero Twist's Blog.
- High Performance Networking.
- JavaScript Performance by Steve Kinney.
- The main thread is overworked & underpaid (Chrome Dev Summit 2019).
I'm currently working on a few more sagas. Let me know if you're interested in more sagas in the comments below π
NB: Part 2 of this article. will explore the practical aspects of web rendering performance. I decided to break it into two parts because I don't want to overwhelm the reader.
Subscribe or follow to get notified!
Fun Fact: This article's story line was inspired by
- This Tweet
- Lupe Fiasco's The Cool.
- Demon Slayer: Kimetsu no Yaiba.
- Marvel Movies (Thor, Spiderman and Thor 2).
- Attack on Titan.
Top comments (1)
Nice article, has alot of insights