DEV Community

Cover image for ⚔️ End Game - A split second later
Anton Korzunov
Anton Korzunov

Posted on • Edited on

⚔️ End Game - A split second later

In the Famous End Game, Avengers assembled to fight the threat and they won. This is the End Article for a Split Second Later series, and it's time to assemble all our heroes.

Before we start - let's recap the previous series

☠️ Who is the BAD GUY ? - the Time between you hit "enter", and your site or application is "ready". And it does not matter what does mean "ready" for you - for your user it's always just "ready". So simple, it's really so simple.

🔥 Who are the GOOD GUYS? There are many!

  • a faster Server-Side or CDN response
  • a faster Client-Side boot
  • a smaller Network payload
  • fewer roundtrips for resources and fewer blocks
  • right content and actions delivered in the right time and the right order

Let's found how they would make your site, or application, be ready just a split second later.

👉 In an alternative universe (multiverse?!) Das Surma has written the same story - techniques to make a web app load fast, even on a feature phone. Check it out


Faster Response

There are a few ways you can display a final picture to your customer. To be more concrete - two ways. As HTML-first, and as JS-first. But this is not just two ways - they are creating some spectrum, and let me cite the famous Rendering on the Web to explain it:

Rendering performance target

However, SSR at this comparison table has a con - slow TTFB, which means - you will start getting a response from a server not as soon as in other cases.
This limitation is driven by two technologies:

  • MVC, which is a common way to SSR react applications - first get everything, then read everything, then send everything
  • lambda functions of any sort. Which by design accumulates everything you want to send, and then "return" it as one big string.

While lambdas are not yet stream rendering compatible, and there is nothing you can do with it, "MVC problem" is a lie - nothing stops you from sending <head><script src='main.bundle.js'> first, letting user start downloading js-bundle, then read all data, and then renderToStream the result, significantly reducing TTFB. Just get rid of declarative helmets, which are not single rendering pass compatible.

Yes, to be honest - to achieve the best results, you have to get rid of react-router and react-helmet. Patterns they implement are not SSR friendly.

This technique is known as progressive rendering and here is my friend @flexdinesh explaining it in details:

Btw, do you still remember the second article of this series - React Cache?

Faster Client-Side boot

So you open the page, server sent some bytes - the rest is browser job.
"The Rest":

  • download all needed scripts
  • download all needed styles
  • download all needed data
  • display something to the client, and ideally from the first try

Preloading the right content is key here. Preload font's before they got used by HTML (which is not loaded yet), and CSS (which is not loaded yet), as well scripts.

The majority thinks that this is achievable only thought HTML LINK meta tag, thus not usefull for lamdas, not yet compatible with stream rendering, but the truth is - you might send preload as a HTTP, not HTML header, you can send from a service "before" labmda.

Link: <https://example.com/app/script.js>; rel=preload; as=script
//
<link rel="preload" href="//example.com/widget.html" as="document">
Enter fullscreen mode Exit fullscreen mode

  • display something to the client, and ideally from the first try

first try

And that's the key point - displaying something "once" is a key. I am not talking about the Death By A Thousand Loading Spinners, so popular among modern SPA - even Progressive JPEG(considered as "good" for slow connections) is leading to multiple renders(while a picture is progressivle loading) wasting CPU(and battery) of your phone. So doing something "once" - is a key for a more idle CPU, and more power to do other stuff.

Finding the good balance between network and CPU utilization, as well as between render/redraw/layout - is a key to better user experience.

Finding the good balance between data sent from a server (the less you send - the faster you read it), and data requested by a client (why not to fetch something a bit later? Why not... not?) - is the point of equilibrium.

...and don't forget about critical CSS.

It's always about balance

Smaller Network payload

Is about making your scripts smaller, and about using as fever lines of code as possible. It's about code splitting and code optimization.

  • properly isolate your use cases and your code from each other
  • use code splitting
  • measure intermediate and the final results. size-limit and import-cost are your best friends.
  • try deferential bundling to ship more efficient code
  • CSS usually is not a problem

Optimizing JS delivery is an article you have to recap.

Fewer roundtrips for resources and fewer blocks

HTTP nowadays is a very complex thing. It's not only about fetching the data from the remote server, but also about TSL handshaking secure connection, connection latency, and effective CDNs.

The key to a faster (up to 2x) response is to use as fewer "connections" as possible, and trying to fit your content into TCP window size blocks, to optimize the transport layer (14kb according to Yandex research).

Loading spectrum

Fun fact - according to the statistics acquired by Yandex(link in Russian)[https://habr.com/ru/company/yandex/blog/358944/] - the actual "downloading" part is NOT a problem for mobile phones - but DNS lookups, and network ceremonies are.

Right content in the right time

Is about loading something when you need it. It's also about coherence, and loading that something when you actually need it. It's also not about loading, but executing.

It has many names, like:

  • critical CSS, styles for a footer defined before the footer, not the header - are styles delivered at the right time
  • some data stored during SSR in HTML​ data- attributes, not in a single and global Redux store - is data defined in the right time
  • js code executed, and HTML rehydrated when it really needed, not in the real beginning (also known as a partial hydration) - is ​the right action, done in the right time.

My tech stack

And so, it's time to explain why you should start with imported-component...

Top comments (0)