Web Performance - Renderland's Saga, Book 2

Web Performance - Renderland's Saga, Book 2

Destroying the bugs!

ยท

14 min read

The Galactic Federation ๐Ÿ‘ฎ๐Ÿฝโ€โ™€๏ธ๐Ÿ‘ฝ๐Ÿง๐Ÿพโ€โ™€๏ธ๐Ÿค– - Fourth Act

Despair and frustration will not shake our belief that resistance is the only way to liberation. - Emile Lahoud.

In the first part of the series, we learned about Renderland's history, its new savior, and the invaders who sought to destroy the planet.

The Galaxy is governed by an organization known as the Feds or the Federalis, they are an intergalactic organization that governs thousands of planets and galaxies including the Web Galaxy.

The Bugs ๐Ÿ‘พ

A coalition of criminals who were sentenced to and then escaped from the Devil's Planet intergalactic prison, a maximum-security prison for the galaxy's worst of the worst. The bugs seek to dismantle the Feds.

The attack on Renderland was the first of many attacks that soon followed after. Their primary goal is to destroy the Pillars and Federation's RAIL Model and eventually the entire Federation.

RAIL Model ๐Ÿ›ค

In the previous article, we introduced the Pillars of performance in Renderland. This section will also introduce a new performance model.

This model puts users at the center of the performance story and it helps describe performance from a user's perspective. It breaks down the experience into key actions namely response, animation, idle, and load. It helps define performance goals for each of the key actions that make up the user experience when navigating a website.

Response โœ…

Describes the time it takes from user interaction (such as a tap) to paint. It's the time between user interactivity and feedback from the interaction.

๐Ÿ’ก It's recommended to respond to users' actions in 100ms or less.

Animation ๐Ÿ…ฐ๏ธ

Animation is a technique used to make objects appear like they're moving. The Feds have defined a budget for each frame in animation which is 16 ms (1000 ms / 60 frames per second โ‰ˆ 16 ms). Humans view animations that take 16ms or less per frame as fluid, smooth and consistent.

๐Ÿ’ก It's recommended to produce frames in 10ms or less.

Idle ๐Ÿ’ค

Describes the state of a website after the initial load. It's a good time to pre-fetch resources.

๐Ÿ’ก It's recommended to respond to user input within 50ms.

Load ๐Ÿ’”

Loading pages should be seamless and to acquire that, the recommended time a page should take to load is 1000ms (1s) at most. Sites that load quickly have longer average sessions and lower bounce rates.

๐Ÿ’ก It's recommended to load pages within 1000ms (1s).

My First Board - Frame 2.jpg

๐Ÿ’กYou might be wondering, why a second model?

  • Pillars (Web Vitals) ๐Ÿ‘บ Help measure and quantify performance with respect to numbers (Quantitative).

  • RAIL ๐Ÿ›ค helps measure how users perceive performance (Qualitative).

Qualitative analysis

Deals with characteristics and quality. It's relevant because it helps you understand how users feel when using your websites. After all, emotions cannot be quantified.

Quantitative analysis

Deals with exact figures and it gives you accurate performance statistics which you can use to optimize.

  • โฑ 0 - 100ms Anything within this range is perceived as fast.

  • โฑ 100 - 300ms Users start noticing slight delays.

  • โฑ 300 - 1000ms Delays are evident and users start feeling uncomfortable.

  • โฑ 1000+ms Users start to check out mentally.

  • โฑ 10,000+ms Users perceive a web page as responsive and abandon the task at hand.

The Fusion โ˜ฏ๏ธ

Dragon Balls has a concept called Fusion, which allows two Saiyans to merge into a single more powerful being. This newly created being surpasses the fusees power levels by incredible margins.

Fusing Web Vitals and RAIL lets us utilize the powers of perception and reality to create an enjoyable user experience. For instance 10ms and 15ms are treated as two distinct values quantitatively but users won't notice the difference, they'd simply perceive both as fast!

๐Ÿ’กBy fusing the Web Pillars and RAIL, we end up getting

My First Board - Frame 3.jpg

The Chairman โœ๐Ÿพ

A bearded elderly man appeared to us in hologram form to assure us that the federation is fully aware of Renderland's situation and is currently mobilizing re-enforcements to rescue the planet. They've shared a list of measures to be taken to hold back the bugs until help arrives.

It was later revealed that the elderly man was the Federation's chairman and it was non-other than the legendary Dennis Richie!

Here is what you can do to stall the bugs until re-enforcements arrive

  • Code Split

  • Compress, Cache, and Minify (CCM)

  • Optimize Images

Code Splitting

To counter the bugs, the natives trained on how to split and control their body parts at will. This makes it possible to split code into various bundles or components which can then be loaded on-demand or in parallel.

My First Board - Frame 1.jpg

๐Ÿ’ก There are two main types of code-splitting.

Route Based ๐Ÿš

Route-based code-splitting is a method of delivering code in chunks based on user navigation i.e switching between routes.

Component-Based ๐Ÿ”ฒ

Component-based code splitting is a method that delivers code in chunks based on user interaction within the same page. For example, modals contain components that may be heavy and it wouldn't make sense to load them before a user opens the modal.

Caching

Besides Minification, the natives of Renderland also could create clones of themselves to be used in Cacheland.

Caching is the process of storing copies of files in a cache, or temporary storage location so that they can be accessed more quickly. Caching can be done on both the server-side and client-side.

๐Ÿ’ก There are two main types of caches.

Server-Side Cache

Server-side caching is beyond the scope of this article but you can utilize a NoSQL key-value store such as Redis to perform caching. Redis also provides a Client-Side caching mechanism but I haven't tried it yet. You can learn more about it here.

Client-Side Cache

The process of caching assets on the client-side of things. This can be done via HTTP or a Service Worker.

Browser (HTTP) cache

When a browser visits a page for the first time, it stores copies of assets in its HTTP cache for faster retrieval the next time the resource is required. It then serves non-expired requests from the cache.

HTTP Cache Headers

Your application servers can attach cache headers to the response to control cache behavior.

  • Cache-Control

  • ETag

  • Last-Modified

Service worker cache

Service Worker caching requires a fetch event handler in an app's service worker file. Network requests are intercepted and responses are served from the worker's cache whenever possible.

Untitled Diagram.drawio (6).png

Compression

In the previous part, the bugs have infected unoptimized assets with a virus that caused them to grow in size which makes it difficult for them to travel and respond to requests.

The A-Team came up with a temporary technique to reduce their sizes thus reducing their transfer times. This technique is known as compression.

HTTP Compression

๐Ÿ’ก There are mainly two types

  • Lossless means you can retrieve the original data.

  • Lossy means you might not get the original data due to a change in its quality.

Optimize Images

Optimizing images allows the creation and display of images using the best format, size, and resolution depending on network and device constraints.

Formats

There are new image formats that were developed specifically for the web. They offer greater compression and quality benefits.

  • WebP is a format created by Google and it was intended as a replacement for jpeg, PNG, and gif formats.

Accessibility

Adding ALT tags can bring about accessibility benefits and a better user experience for users who fail to load images due to network or device constraints.

<figure>
    <img src="awesome-photo.png" alt="An awesome photo!!" />
</figure>

A well-written ALT tag can help your users visualize an image if it fails to load for whatever reason. It can also help images rank higher in search.

srcset

This is an HTML attribute that allows you to specify different image sources to serve depending on factors such as the width of a device or its resolution.

<figure>
    <img 
        srcset="high-res.png, medium-res.png, low-res" 
        src="high-res.png"
        alt="Serving different " 
     />
</figure>

Lazy-loading

Setting an image's loading attribute to lazy can help the browser prioritize when to load the image

<figure>
    <img 
        src="irrelevant.png" 
        loading="lazy" 
        alt="I am not in the view port"  
     />
</figure>

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.

Static Generation

A static site generator is a tool that generates a full static HTML website in advance (build time). This helps create views that are ready to serve ahead of time.

๐Ÿ’ก How to do static generation

  • Using a static site generation tool such as Gatsby.js and Jekyll.

  • Rolling out own static pages via a custom server.

โœ… Good for

  • Static websites such blogs, landing pages, and campaign/event sites.

  • Generating leads and SEO.

Rehydration ๐Ÿšฐ

When CSR and SSR fuse, they unlock a more powerful form of rendering known as Rehydration. This pattern uses a pre-built DOM with components rendered as HTML. The app then loads the remaining data in the client side.

๐Ÿ’ก There are several variants of rehydration

  • ๐Ÿ’ง Progressive Rehydration this approach serves chunks of server rendered applications overtime instead of doing it at once.

  • ๐Ÿ’งPartial Rehydration this approach serves components that meet a certain criteria.

  • ๐Ÿ’ง Lazy Rehydration this approach serves components in chunks and on demand.

โœ… Good for

  • Generating leads and SEO.

  • Apps that prioritize first contentful paint (FCP).

Pre-rendering ๐Ÿšง

This pattern pre-loads content in anticipation of users interacting with said content. This pattern renders an app shell to static HTML during build time.

โœ… Good for

  • Apps where SEO is a top priority.

  • Search engine UIs render highly ranked sites at the top because users are high likely to visit.


The Reinforcements ๐Ÿš€ - Fifth (Final) Act

Geography has made us neighbors. History has made us friends. Economics has made us partners. And necessity has made us allies. Those whom nature hath so joined together, let no man put asunder. - John F. Kennedy

The Render League and the A-Team followed the Federation's advice and they managed to hold some of the bugs back. However, the danger still remains as the bugs were still fixed (get it) on destroying the pillars.

The techniques listed in the previous act could enhance an app's performance but they aren't really sufficient. Modern apps are quite complex and they contain many moving parts.

The Federation dispatched several units of their most elite warriors, we'll discover each soon!

The Frameworks/Libraries

Dennis Richie has previously mentioned that Scripts have the ability to transform just like the Super Saiyans in Dragon Ball. This transformation gives JS a set of new powers and abilities that will make it easier to fight the bugs. Dennis revealed that the current form of JS is known as Vanilla and that it could evolve into much more powerful forms.

React.js โš›

React is a free and open-source front-end JavaScript library for building user interfaces based on UI components.

Historically, the DOM manipulation in Renderland was done directly by the Scripts. It was a heavy task and the Scripts had to evolve. jQuery was one form that allowed easier DOM manipulation but it was still lacking in some aspects.

Finally came React which is an evolved form that doesn't need to manipulate the DOM directly to reflect changes. It had a new super power known as the Shadow Clone.

Shadow Clone (Virtual DOM) ๐Ÿชž

Also known as the Virtual DOM, is a representation of the actual DOM in a browser. It's what React uses to re-render content.

Reactions โ˜ข๏ธ

As stated above, React utilizes its Shadow Clone to re-render content on a web page. The re-renders are a product of a reaction such as a change in state or props.

React's smallest building blocks are known as components. Components contain the data to be rendered. React is interested in knowing when a component's data has changed so it could initiate a re-render.

  • State contains information that describes the characteristics or behavior of a component at a given point in time. For example a button component could be in an active or a disabled states.

  • Props short for properties and it describes the attributes of a component.

The Algorithm ๐ŸŒ—

At its core lies the mechanism that tracks changes in a component's state and then updates the dome based on this new state.

Untitled Diagram-Page-2.drawio.png

It's an ideal, or โ€œvirtualโ€, representation of a UI is kept in memory and synced with the โ€œrealโ€ DOM using a library such as ReactDOM. This process is called reconciliation.

Renderer

React separates its implementation from the UI. It mainly focuses on diffing. The rendering is handled by a renderer which is an API that allows rendering of content in any environment.

import React from 'react' // the algorithm
import ReactDOM from 'react-dom/client' // the renderer

function App() {
  return (
      <main/>
           <h1>Renderland's Sagas</h1>
      </main>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));

// is invoked once on initial load and on subsequent state/prop changes.
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

Code-Splitting

Code splitting in React allows the delivery of React code in chunks.

Before

import { robot } from './js';

console.log(robot(16, 26));
After

import("./js").then(robot => {
  console.log(robot.add(16, 26));
});

Next.js ๊†Ž

Next.js is a flexible React framework that gives you building blocks to create fast web applications.

It's the Next (pun intended) transformation of React, its new superpowers include image optimization, server side rendering, automatic code-splitting and more!

Data

Next.js has the ability to render in different forms. With Next.js, you could do

  • Server Side Rendering

  • Pre-Rendering

  • Incremental Static Regeneration

  • Static Generation

Dynamic imports


import { useState } from 'react'

export default function App() {
  const [user, setUser] = useState()

  return (
    <>
      <input
        type="text"
        placeholder="Search"
        onChange={async (e) => {
          const { value } = e.currentTarget
          // dynamically loaded script
          const Auth = (await import('auth.js')).default
          const user = new Auth(value)

          setUser(user)
        }}
      />
    </>
  )
}

Optimizing images

Refer to the docs for more information about image optimization in Next.js.

The Tools ๐Ÿ”ง

Service Workers

You could use service workers to execute JS logic outside of the main thread.

Lifecycle

Before you could use a service worker, you must first register it via the ServiceWorkerContainer.register() method. The worker's lifecycle begins after it's successfully registered.

๐Ÿ’กEvents

To utilize workers, you'd generally listen for events on a worker and then respond accordingly.

Download

The worker is downloaded into the client.

Install

The worker is being installed. If successful, then this is a good time to prepare the worker for usage.

Active

Installation is successful and the worker is ready to receive events. The point where this event fires is generally a good time to clean up old caches and other things associated with the previous version of your service worker.

๐Ÿ’ก Caching strategies:

Cache only

Generally used for content that's considered static to a particular "version" of a website. They're usually cached in the install event of a service worker.

๐Ÿ’ก It's good for:

  • Static content.

Cache, falling back to the network

Generally used for building apps that are intended to be offline-first.

๐Ÿ’ก It's good for:

  • Application shell and common resources such as logos.

Network only

This strategy skips the cache and sends requests directly to the server. It's mainly used when your app requires content to always be up to date. It's also ideal for requests that cannot be cached such as POST or PUT requests.

๐Ÿ’ก It's good for:

  • Payment related applications

  • Content that changes frequently.


The Aftermath

Set your face towards danger, Set your heart on victory. - Gail Carson Levine

The bugs started retreating after acknowledging defeat in the battle for the Pillars. Renderland isn't fully safe yet but we won't have to worry about the bugs for quite a while.

It was a battle to be remembered, the natives showed incredible resilience and finesse in defending their land. They've also unlocked higher levels of power in the process.

The Sacred Tree ๐ŸŒฒ

The planet's elders summoned a great meeting under the Sacred Tree to celebrate their victory.

Web Performance is a topic that I have avoided for years due to the perceived difficulty, scarcity of easy to read material and my total reliance on frameworks to build web apps.

I have learned valuable lessons working on optimizing this NFT marketplace. I wanted to share my learning journey with you in this article. I hope you found it useful!

The Weird Looking Room

HTML5 and JS escort me intto the weird looking room I woke up in after being sucked into my PC's screen. I am then given a piece of paper with a code that says h3ll0, w0rld!, they said I could type these letters into any web browser and it'll open the portal to Renderland.

  • HTML5 ๐Ÿค– It was nice having you here, come visit any time!

  • JS ๐Ÿค– Come back and I'll tell you about my cousin Java.

  • Me It's been lit ๐Ÿ”ฅ


Conclusion

Book 1 introduced a lot of concepts and book 2 expanded upon them. Book 3 shall include practical examples of most of the concepts presented in this article.

It's highly recommended to spend extra time reviewing and practicing these concepts. Learning by doing is most often the best way to learn IMHO.

Screen Shot 2022-05-20 at 05.19.10.png

Resources ๐Ÿ“š


NB: Part 3 of this series will explore the practical aspects of web rendering performance. I decided to break it into parts because I don't want to overwhelm the reader.

Fun Fact: This article's story line was inspired by

See you in Part 3!

ย