From Facemash to Songmash: How I Take Mark Zuckerberg’s Drunken Idea and Turn It Into Mine (Part II)

Hi, it’s me again.

About a month ago, we talked about developing an application of which the inspiration comes straight from Mack Zuckerberg’s infamous Facemash. We have discussed the backstory, the algorithm and the underlying engine of the app. I am very proud to know that the first part of the blog has been received with warmth and recognition.

Then, I left you with a cliffhanger: the app’s client side will not be written with, I can say with utmost certainty, any framework language that you have ever known of. Not React, nor Angular, nor Vue. For an entire month with no update, I can only imagine how much you are craving this second part, and some of you may have feared an “Italian Job” situation.

But, no worries, I have returned here today to finish what I have started. In this edition of BraveBits’ monthly blog posts, we are going to discuss about three emerging questions:

  • Why a new framework?
  • What is the new framework?
  • How does the new framework work with our app?

So, tighten your seatbelt for this bumpy ride, shall we?

 

A Pretentious Title and The Problems with Current State-of-the-Arts

The date is September 28, 2022. I was strolling on Medium like usual, searching for some new stuff coming from the web dev’s gurus. Nothing was out of ordinary, then, came a news with this title:

Yes, what you are feeling is particularly what I felt the first time I read this: “What the f-”? React is the most widely-used web library as of May 2022 (as reported by StackOverflow), and Next.js is gaining more and more recognition in the developers’ community. It must be insane to suggest an ending of these two powerful tools that are being used to create thousands of thousands of web apps out there. 

However, as my curiosity kicked in, I had to read and devour that news. And, while I certainly did not agree with everything written, I really started to have a deeper understanding on what actually is going behind the curtain of web application, and, digging into it, it is revealing that our current state-of-the-art contains many unresolved problems.

The increasing demand of interactivity, and eventually, JavaScript

Web development is rapidly developing, as the demand for websites’ interactivity and usefulness has been increasing to the n-fold. And, not only do websites nowadays need to care about its users’ experience, but a lot of effort is also spent on retrieving users’ behavior to gain better insights, hence, better web building mechanisms. So and so, this results in much more complex web infrastructure, our websites keep getting bigger and bigger, and it leads to a detrimental problem: more JavaScript needed. Loading and parsing JavaScript files is slow and cumbersome, and it is the main reason why our dynamic web experience is not as smooth as a static one: there is no JS needed in such an app!

Truthfully, our CPU does not prepare for this

Remember when Gangnam Style broke YouTube for a couple of hours once it reached 1 billion views, as YouTube’s mechanism, at that time, only held a maximum-9-digit data types for video views (since no one thought any videos could surpass the milestone)? Well, the problem with CPUs is the same. It is true that CPU is getting faster yearly, however, we are closing in on the maximum speed that CPU can run, and it is now relying on parallelism of multiple cores, not just one single core.

The problem is that JavaScript is single-threaded, and the more JavaScript required, the more work for that one miserable single core to execute. It is vital to realize that our current JS load is increasing at a faster rate than its of a single CPU core performance.

The linear problem

When building a web application nowadays, we tend to care too much about runtime without looking over to the matter of TTI (time-to-interactive), and as our applications are getting more and more complicated, the time it takes from static HTML generation to rich interaction is being stretched out longer and longer.

This is due to the fact that an application’s bootup process consists of two things: the slope, which is the complexity of the application, and the constant, which is the framework’s initial cost. So, we are really talking about a “y=mx+b” relationship here.

And we can clearly see from the graph above, no matter how much we try to optimize our code, the bundle size gets larger with the more complex the app gets. This is known as the linear problem. So, the question remains: how to reduce the “m” slope to 0 and serve only the constant figure for the bootup process?

Resolving the cliffhanger (with a revolutionary twist)

“Our current frameworks are O(n); we need O(1)” – Misko Hevery, creator of Qwik.

What we need is a new paradigm. We need a framework with a constant load time no matter the application complexity.

So, what are our frameworks currently doing, under the hood. In a typical web application, we send server-side rendered HTML to the client, and it first renders it – a static site, and we cannot interact with it at all. Then, it downloads all JavaScript files and parses them, before attaching listeners and executes it – only then can we interact with our app. This is a concept known as ‘hydration’. And, as we have discussed, hydration is expensive, since even after we have all the structure and content rendered for the view, we still have to wait for it to become interactive.

There are many workarounds for hydration, such as to partially hydrate (island architecture) or lazy load content, but really, workarounds are never the proper solution for any matters.

So that’s when a youthful and energetic framework comes into play. Introducing… Qwik.

Developed by the Builder.io team, led by CTO Misko Hevery (who actually was the creator of AngularJS!) in 2022 and currently in beta, Qwik describes itself as the framework of the future. And it isn’t just a loudmouth. Qwik’s secret lies in their two powerful concepts: Resumable and Progressive.

Resumable

Resumability is about pausing execution in the server and resuming execution in the client without having to replay and download all of the application logic.

Imagine watching a Netflix series, and anytime you go for a break and then revisit the series, you have to watch everything from episode 1. How terrible is that?

Qwik realizes that hydration is pure overhead: anytime our app boots up, it needs to run through the process of downloading, parsing and binding listeners all over again. Resumability was developed to tackle the root of this issue. Basically, Qwik skips the bootup and goes directly to the state where you are. Qwik applications at any point in their lifecycle can be serialized and moved to a different instance (server to browser). There, the application simply resumes where the serialization stopped. We the users decide which part of the application we want and when — that’s why we are calling it resumable.

 

Progressive

Progression is about downloading code as the application needs, without having to download the entire codebase eagerly. Instead of loading every scripting file at the initialized moment of the app, Qwik breaks up the application into many lazy loadable chunks and only loads the ones needed whenever necessary.

Qwik does this by implementing a tool called the Optimizer, and the strange-looking symbol $. Whenever the machine detects a code with that symbol, the Optimizer would split it into a new file, and only asynchronously import the file at the fingertip of users’ interactions.

By being resumable and progressive, Qwik is the first one to break away from the reliance on hydration and the island architecture, and just maybe, revolutionizes web development for the years to come. I am not trying to downgrade any other frameworks here, but we must compliment a good framework when we see one, and Qwik is that one today.

Qwik x Songmash

So, with all that long talking, I will take the chance of Songmash to first put my hand onto the new found treasure called Qwik. After all, the project stems from the pure joy of coding, so there is no harm at all in doing something new, isn’t it?

All right, let’s dive in and see what the client-side looks like with Qwik implemented.

User Flow

The apps can be divided into two pages: the homepage and the artist’s page. The homepage simply holds the information of all the artists there that users can choose to interact with, while the artist’s ones are where our fun kicks in.

The artist’s biography section

The artist’s mashing section: this is the main part of our app, where users can choose one song over two, and our backend will implement the Elo algorithm to calculate the scores.

And the artist’s song ranking section, which displays the calculated scores and rankings.

Breaking down the Codes

  1. The routings, very simple since we only have to deal with two kinds of pages.
  2. The services, which we use to connect our client-side application to the API written and discussed in the server-side section
  3. The helpers, storing our utilities TypeScript files, including the ones that we used to implement the Elo algorithm
  4. The components, breaking into smaller folders for easier management.

An example of Qwik’s syntax: notice the usage of three hooks: useStore, useClientEffect and useWatch. The first one, useStore, is equivalent to useState in React, obviously to manage and update the state, while the two others are a bit different, which Qwik decides to break React’s useEffect into smaller chunks. This is extremely helpful since Qwik wants to separate the functionality of the server side and client side, to pause and resume it harmonically as the rules of resumability states.

It is noticeable how the Lighthouse score of my app increases rapidly with the use of Qwik, and that I have not really fully optimized it!

Endnote

And so, that was our journey with Songmash. Began with a fragment of an idea by Mark Zuckerberg, with the help of an intriguing algorithm, an unconventional data retrieving method, and a soon-to-be revolutionary framework, we ended up with an application that fulfills my pure joy of coding as well as my eagerness to learn new things, and I hope, it also becomes an inspirations for you guys out there to start getting yourself together and building things.

A small idea, a little bit of knowledge, and a lot of love for coding, that is the recipe for success, or at least, joy.

The Github repository for the client-side is as follows: link. See you again soon!

An X. Cao

Comments

Let’s make a great impact together

Be a part of BraveBits to unlock your full potential and be proud of the impact you make.