What makes the web slow? browser's bottleneck

In this article, I will explain briefly How the web works, and explain the core reasons behind the slowness of the web, specially browser’s main thread, I advice you to check the previous Article about the motivation behind optimizing the performance in general before reading this one.

Source: Nick Abrams on Unsplash 🔗

How the web works?

First, we need to understand how the web works, starting from writing the domain name in the browser until having a fully interactive webpage

Websites are usually hosted on a server which has an IP address (x:x:x:x), this IP address is attached to a name called domain such as example.com, so when the user write “example.com” in the address bar in the browser and hit enter here is what is happening briefly:

  1. browser tries to contact the DNS server searching for the IP address attached to the name you entered
  2. after the browser receives the right IP address it sends a request to load the page from the server (after making the TLS handshakes 🔗)
  3. then browser receives the stream of bytes from the server and translate it based on its MIME types
  4. then the browser starts to process each files based on its type to render HTML and compile JS files and paint the CSS files and so on
  5. until the website is fully loaded, the browser is busy doing all of that for you to make the site fully interactive then browser can go idle waiting for the first user input

All this process above takes seconds usually so you don’t really notice it most of the times, but it might take more time depending on your implementation and understanding of all aspects in the process or of course the hardware of the client.

From the scenario above we have 3 main characters that might play a role in the slowness of the internet:

  • the Server that we host our files on,
  • the Client(Browser) that our online customers are using to use our website
  • and in between is the Network of course

Core reasons behind a slow website?

  • Slow servers: it causes your server to respond with a delay or high latency which cause the website to be slower of course
  • Slow connection: if the website loads a lot of files in the first load, that will be a very slow FCP 🔗 and TTFB 🔗 in 3G slow connections for example
  • Large images/videos: definitely having large images or videos is taking too long to load and might block the main thead longer
  • Too many 3rd parties: most websites are using a lot of 3rd parties like the analytics and consent managers and more, they might block the loading of your main content
  • Large bundle libraries: almost all websites are using some npm packages carelessly without paying much attention to its bundle size or speed performance or how tolerant to tree shaking
  • Bad implementation: using a bad algorithm to work with data at a scale might cause a big impact
  • Large loaded DOM size: that would cause blocking into the main thread every time you change a parent element, that will cause some slowness in rendering as well and latency in the user input responsiveness
  • Large bundles: having all website code into on one or a few files would make them too big, split them wisely to load only what the user need is a challenge

All the reasons above are there because of how browsers work and also client and server’s hardware, in this article I’m more into explaining why web browsers are slow and requires some understanding to make it fast or at least pretend to be fast toward web users, let me explain it now

Browsers are single threaded

Since the beginning of the web browsers they have only a single thread, what makes browsers can do only one thing at a time “theoretically”, either to render HTML or paint UI based on CSS or decoding and painting Images or compiling and run JavaScript. every task of those takes some time from the main thread, and this is the main problem of slow websites, having some long tasks that blocks the main thread for long time without letting the other waiting tasks to be executed even partially.

main thread tasks

source: state of web workers 2021 🔗

To mitigate the load of tasks on the main thread that could be a bit tricky, one solution could be to split tasks into smaller executable ones, which will make the main thread able to switch between all tasks and makes the websites feels smooth and functional all the time

You might be wondering, Why we call it Main Thread if it is only a single one? that is a good question, that is because you can basically move some heavy work from it to some other parallel thread (you create) using web workers, and they can be connected together using some browser APIs or using some libraries that makes life easier with Workers for example comlink 🔗 by chrome team, we can elaborate about that in a different article.

Does file type affect the rendering time?

Absolutely, different files of the same size could be downloaded in the same time for the same network condition, but the point here is about what is after the download, how the browser deal with it? so in the example below we have 2 files one JavaScript 170kb and another one image with the same size.

As you can see for the image it is downloaded, then decoded and finally painted, the download time takes around 3.4s based on the test on slow 3G and Moto G4 mobile(middle-tier), and the Decoding ~64ms and finally ~28ms to be Rasterize painted

In the other hand the JavaScript file takes the same amount of time to download 3.4s fair, then it gets into the Parse/Compile process which takes ~2s and finally Execution which takes ~1.5s more, what a huge difference between the 2 files, so after all we discover that JavaScript is your heaviest asset of a website, it is not only about file size.

The problem with long tasks

Unfortunately, one the main thread started in a task it cannot be interrupted, it we block it too long the user will feel that the website is a bit laggy, most screens are running with 60fps what means that browser should paint a new frame each ~16ms.

that’s why browsers consider any task with longer than 50ms as a long task, it drops about ~3 frames or more, the user might notice the slow rendering and this brings a bad UX in general and more waiting time to respond to user input.

What can we do to enhance main thread?

Since the main thread is being the bottle neck for a fast (web) browser, can we offload it a bit? or at least make it somehow performant, a quick answer is Yes, we can manoeuver to make the main thread performant by:

  • Making smaller tasks in general (Images, JS files, CSS files, fonts, …etc)
  • Move heavy tasks to Web/service workers
  • Maybe run your application on SSR (Servrer-Side Rendering) that will do the rendering on the server and offload the main thread
  • Avoid wasted re-rending, because anytime it happens it causes the browser to re-flow which is expensive
  • Build your application with slow devices in mind and this will make it faster on all other devices as well

And much more optimizations can be applied as well, in general try to make the main thread Idle as soon as possible.

Conclusion

In this article we talked about how the web works and the reasons behind a slow website, focused on the main reason which is browsers’ single thread, talked about the files type effect and how JS files take longer time to be processed comparing to an image of the same file size, and finally some quick ideas to mitigate the pressure on the main thread.

if you want to discuss it more, feel free to ping me on Twitter 🔗

Tot ziens 👋

SHARE