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-level knowledge of web performance at the time. I spent an insane amount of time researching and watching tech talks and videos so 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 it down and then go out for a walk to clear my thoughts.
I return 30 minutes later to find a strange blue light emitting from the room. It was coming from the PC which was still on but frozen. I try long pressing the power button but I end up getting sucked into the screen instead.
The Giant Robot
I wake up in this weird-looking room where I immediately get approached by a giant robot with the letters HTML
on its chest.
๐ค Hi, I'm HTML5
. I'm glad you woke up, welcome to Renderland!
๐จ๐ฟโ๐ป Where am I?
๐ค You're in Renderland
.
๐จ๐ฟโ๐ป 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 before it reaches a server
that 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
.
๐ค 1 I'm HTML
, you've probably met my grandson, HTML5
. We're both from the Markup
tribe and we make up the content of pages on the web.
๐ค 2 I'm CSS
from the Styles
tribe, and we give web pages looks and style
.
๐ค 3 I'm JavaScript
but you can call me JS
, I'm from the Scripts
tribe- no relation, and we make 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 a server
and a Clientland
native is referred to as a 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, JS, 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 represents the sequence of steps the browser goes through to convert the HTML, CSS, and JS into actually visible pixels on the screen.
The Render Tree ๐ฒ
HTML5
and CSS
then summon me into another private meeting under 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.
<head>
<title>Renderland</title>
</head>
<body>
<header>
<ul>
<li>Book 1</li>
<li>Book 2</li>
</ul>
</header>
<main>
<h1>The Sacred Tree </h1>
</main>
</body>
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 quantify 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 the most visible page elements, and the page responds to user interactions within 50 milliseconds.
๐ก The recommended TBT
score is 200 milliseconds or less.
Measuring Performance
You can't improve what you don't measure. - Peter Drucker.
Learning how to measure performance on the web is crucial. The previous section introduced the Pillars, the section will show you how they perform their duties.
๐ก 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
.
Field tests can be conducted using
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.
Lab tests can be conducted using
Developer Tools
panel in web browsers.- Web Page Test.
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 decided to lay a siege on Renderland by cutting off its supply routes. They initiated by attacking Serverland
aka the source, where the planet's data comes from.
TTFB is affected by many factors, some are within Renderland's territory and others are in faraway planets such as Serverland
and Cacheland
. Defeating the bugs that have attacked this pillar will take a lot of effort.
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) ๐จ
The bugs used a set of advanced attacks to target this Pillar. They knew that having a large bundle size
or simply blocking the Critical Render Path CRP
would have the potential to deal great damage to Renderland.
The bugs did both, they first infected unoptimized
assets with a virus which resulted in really large bundle sizes
and then blocked the CRP
, thus making it difficult to render anything.
Third Pillar (Interactivity) ๐ฌ
The bugs launched their attacks on unoptimized JavaScript. Unoptimized scripts
can slow down performance because they need to parsed and compiled before they're finally executed.
๐ก What is a Main Thread?
JS derives its power from its Main Thread
. This article might be a great resource if you aren't familiar with JavaScript's single threaded nature.
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 bugs
decide to attack this Pillar by overwhelming/overworking the main thread because they browser may not respond to user interactions if the main thread is blocked/occupied by another process
.
Miscellaneous Performance Bottlenecks
These are some of the most common web performance bottlenecks.
Unoptimized
Resources
Resources which haven't been optimized
are prone to the virus. Scripts, styles, and HTML imports may 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 Render League โ๏ธ - Third (Final) Act
"With great power comes great responsibility."
The natives of Renderland formed an alliance known as The Render League
to combat the bugs and defend the planet. Each alliance member has a special set of abilities that can be used to help improve a performance metric.
Learning how to measure the performance of a website was the first step. Now we need to learn how to optimize the metrics we measure.
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.
How to improve TTFB
Let's see how we can fight back these bugs!
On the Client
- Caching assets and requests with the use of web/service workers (more on these later).
On the Server
- 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) ๐จ
To defend this Pillar, the alliance sent a special team known as the Assets
or simply as the A-Team
. It consisted of HTML
, CSS
, JS
and many others.
NB: Every Renderland native posses the ability to shrink themselves. This ability is known as minification
.
The A-Team laid out a brilliant plan to fix FCP
and LCP
.
Optimizing Assets
Assets who were optimized
were immune to the virus.
๐ก How?
- Use minification on
CSS
,HTML
,JS
and other assets so browsers can download them faster. - Optimize resource load times, for example compressing images, serving them in different sizes, using a
CDN
, etc. - Compressing, removing unused code and deferring non-critical scripts or styles.
Summary
- Reducing
TTFB
. - Optimization and caching assets.
- Shortening the Critical Rendering Path.
- Using 3rd party tools such as Cloudinary.
Third Pillar (Time to Interactive) ๐ฌ
The robot JS
and I paired up to help improve this metric while the other assets remained to defend FCP
and LCP
.
How to improve TTI
In order to improve this metric, JS
and I will have to accomplish the following objectives:
Minimizing Main thread's work
Shinobis
in Nauroto) are known for their Clone Jutsu
technique which enables them to create multiple clones of themselves. JS
can also summon other threads
such as Service Workers
or Web Workers
to delegate work.
Book 2 of the Saga will cover this topic.
Debouncing Events
JS also has the ability to slow down time at will! JS
can use this power to delay the execution of event handlers to 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.
๐ก How to Debounce?
- Leading Debounce executes a function once and waits until there's a pause in consecutive events.
- Trailing Debounce postpones a function's execution based on a time interval.
๐ช Benefits/ examples
- Dynamic search bars.
- Saving content as a user types, for example Hashnode's editor does this :)
Minification
Being a a Renderland native, JS
is able to downsize or minify itself so it can travel quicker when it's needed.
๐ก How to minify
?
- Using a
CDN
provides automatic minification. - VSCode supports minification for several programming languages.
๐ช Benefits/ examples
Scripts
travel through the network faster.
Code Splitting
JS
can also split its body parts and have each body part can perform a task/function.
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.
๐ก How to Code Split
?
- Using a
bundler
such as Webpack or Browserify. - Using a framework that provides code-splitting by default such as Next.js.
๐ช Benefits/ examples
- Downloading code in
chunks
or inparallel
can help reduce an app's bundle size.
Event Delegation
If a web page has a lot of elements with events that could be handled the same way, delegating the event handler to a common parent can potentially improve performance,
๐ก How to delegate events?
- Putting a single handler in the container.
- Handle event based on the event's
target
.
๐ช Benefits/ examples
- Less code and more control over event handling.
Throttling
Throttle prevents a function from executing more than once every specified amount of time. It guarantees the function execution once every specified amount of time.
๐ก How to Throttle
?
- A bit similar to debouncing, you'd use a time
interval
.
๐ช Benefits/ examples
- Preventing repetitive function execution.
Miscellaneous Performance Tips
Re-Renders
- Detect and eliminate unnecessary re-renders. Why did you render is a great library if you're building an app using
React
.
Memoization
- Memoize values with React.memo/callbacks.
Packages
- 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.
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.