Made in Builder

×

Developers

Product

Use Cases

Pricing

Developers

Resources

Company

Get StartedLogin

Product

Features

Integrations

Talk to an Expert

Pricing

Blog

Home

Resources

Blog

Forum

Github

Login

Signup

×

Visual CMS

Drag-and-drop visual editor and headless CMS for any tech stack

Theme Studio for Shopify

Build and optimize your Shopify-hosted storefront, no coding required

Resources

Blog

Get StartedLogin

‹ Back to blog

From Static to Interactive: Why Resumability is the Best Alternative to Hydration

March 30, 2022

Written By Miško Hevery

No one wants a slow, unresponsive website. Prerendering your site is one of your most powerful tools as a web developer when it comes to website performance optimization.

Almost all front-end JavaScript (JS) frameworks have a way to prerender content as HTML through server side rendering (SSR) or static site generation (SSG). The result is that the site displays almost instantly as the HTML is streamed into your user’s browser.

However, there’s a problem. HTML is static whereas websites are usually dynamic and interactive. How do frameworks make pre-rendered HTML interactive on the browser?

The current generation of frameworks solves this through a client-side process called hydration, a resource-intensive process that adds significant overhead to the page’s startup cost.

Here’s my controversial opinion: hydration is what happens when you add SSR/SSG as an afterthought to a front-end framework.

A framework designed from the ground up for prerendering can avoid hydration and its performance penalty by serializing state on the server and resuming it on the client.

Before diving into serialization and resumability, let’s talk about the problem that hydration solves.


How does a framework make a page interactive?

Any front-end framework needs three things to be able to respond to interactivity:

  1. Associating event handlers: The framework must have a way to associate DOM elements with their corresponding event handlers, which are the functions that respond to user input and enable interaction with your website.
  2. Recovering application state: Once a user event triggers an event handler, the function updates application state.
  3. Recreating the component hierarchy: Once the application state updates, the framework needs to re-render the application view to reflect the state to the user. The framework must understand the relationship between the state and the components to complete rendering.

Let's look deeper into how hydration handles these tasks and why it’s an expensive approach.


Associating event handlers

Frameworks associate event handlers with specific DOM elements by executing a component template. For example, in React, a button component written in JSX might have an onClick prop with an event handler. Hydration requires that the browser downloads and executes all components’ templates before associating event handlers.

Unfortunately, the JS bundle’s download size and code execution time is proportional to the complexity of the page. A small demo page will download a small amount of JS and execute quickly, but the bootstrap cost becomes prohibitively expensive when it comes to real-world pages, often leading to multi second times to interactive (TTI).

Some frameworks mitigate this performance penalty by attempting to delay when certain parts of a page are rendered. This strategy works reasonably well for content-centric pages such as marketing pages. For sites like web apps where components share state in complex ways, however, frameworks still need to download every component in the DOM tree and execute its template.


Recovering application state

Event handlers need an application state to update, which is present on the server during prerendering. Frameworks must reconstruct this state on the client for the DOM to update properly.

Hydration’s basic approach is to execute the same code that generated the application state on the server again within the browser, which adds to execution time and delays interactivity.

That’s why many meta-frameworks serialize the application state on the server and include it in the HTML so that state can be restored using JSON.parse(). Deserialization is significantly faster than reconstructing state by executing application code on the browser, and it works well for simple and complex pages.

Even when application state is serialized, however, hydration still reconstructs internal framework state by slowly executing code.


Recreating the component hierarchy

For the final piece, frameworks need to recreate the component hierarchy, which is part of a framework’s internal state. It keeps track of which components need to be rerendered when your application state changes.

Similar to how it associates event handlers with DOM elements, hydration must download all of a page’s components and execute their templates to rebuild a component hierarchy, adding still more overhead.


The alternative to hydration

Front-end frameworks perform hydration to recover event handlers, application state, and the component hierarchy in order to make the page interactive.

Each step requires downloading and executing code, which is expensive. Code execution time in particular is proportional to your page’s complexity when using hydration. We could roughly model this limitation with an equation:

No matter how small your payload, hydration will always be a bottleneck.

One solution to this problem is to eliminate the need to execute any code to restore a page’s interactivity, which we can do through serialization. As mentioned above, many meta-frameworks already serialize application state. Why not serialize event handler associations and component hierarchies, as well?

Because it’s really hard!

Function closures, promises, and resource references, among other structures, are all difficult to serialize. So a framework needs to be designed with serializability and resumability in mind. These aren’t features that can easily be added to existing frameworks without large-scale breaking changes.

The biggest win of serializing page state into HTML is that making the page interactive doesn’t require downloading or executing any template code. The framework simply resumes the page.

The bottom line? Resumable frameworks would reduce execution cost to zero and incur a constant overhead regardless of page complexity.


Resumability in Qwik

We at Builder.io have created a resumable front-end framework, Qwik. Our goal is to bring every web page’s time to interactive to its absolute minimum.

While we got the ball rolling, Qwik is open to the community. Everyone who’s as passionate about web performance as we are is invited to try it out and contribute and comment.

Head over to Qwik’s repository to learn more, or try our starter:

npm init qwik@latest

If you have any questions, ask away on our discussions forum and join our Discord server.

Share

Twitter
LinkedIn
Facebook

Continue Reading
-36 MIN
Our current frameworks are O(n); we need O(1)
WRITTEN BYMiško Hevery
May 17, 2022
4 MIN
Fast to Faster: What You Need to Do to Improve Performance in Next.js
WRITTEN BYSteve Sewell
May 13, 2022
9 MIN
Don't blame the developer for what the frameworks did!
WRITTEN BYMiško Hevery
May 4, 2022

Product

Visual CMS

Theme Studio for Shopify

Sign up

Login

Featured Integrations

React

Angular

Next.js

Gatsby

Get In Touch

Chat With Us

Twitter

Linkedin

Careers

© 2020 Builder.io, Inc.

Security

Privacy Policy

Terms of Service

Visually build and optimize digital experiences on any tech stack. No coding required, and developer approved.

Sign up

Log in

DEVELOPERS

Builder for Developers

Developer Docs

Github

JSX Lite

Qwik

INTEGRATIONS

React

Angular

Next.js

Gatsby

PRODUCT

Product features

Pricing

RESOURCES

User Guides

Blog

Forum

Templates

COMPANY

About

Careers 🚀

Visually build and optimize digital experiences on any tech stack. No coding required, and developer approved.
Get Started
Log in

DEVELOPERS

Builder for Developers

Developer Docs

Open Source Projects

Performance Insights

INTEGRATIONS

All Integrations

Shopify

React

Angular

Next.js

Gatsby

RESOURCES

User Guides

Blog

Community Forum

Templates

Partners

Submit an Idea

PRODUCT

Features

Pricing

© 2022 Builder.io, Inc.

Security

Privacy Policy

Terms of Service