Running fetch in a web worker

Jad Joubran
Google Developer Experts
5 min readFeb 27, 2018
The greatest Web Worker of all time

Performance is one of the biggest challenges on the Web & especially on Mobile. Running a web app on 60fps is not an easy task.

While there are many factors that affect the performance of your web apps, in this article I’m going to present Web Workers and how you can run fetch in a Web Worker and why you want to do that.

JavaScript code blocks the DOM, which slows down your User Interface. For example, you’d be surprised that JSON.parse blocks the DOM.

As your data source grows bigger and bigger, your UI performance will suffer more and more. That’s because DOM operations are running alongside your JavaScript code on the main thread.

Can we move some of these operations off the main thread?

Enter Web Workers

With web workers, we can move those expensive operations to a background process that’s running on a different thread.

A Web Worker is a simple means for web content to run scripts in background threads. Think of it as a background process running some JavaScript code that you wrote.

Even though you will most likely not see performance benefits of running fetch in a web worker, this article will serve as an introduction and explainer for Web Workers and Comlink.

Can I access the DOM from a web worker?

Web Workers don’t have access to the DOM because the DOM is not thread safe. Making the DOM accessible to web workers will defeat the purpose of having Web Workers as their implementation will be much slower.

Can I use Web Workers already?

Browser support for Web Workers: a green paradise.

The picture speaks for itself. 😅

Comlink

GoogleChromeLabs/Comlink makes it easier for us to write an ES2015 class in a web worker and expose it to our main thread.

Github repository for Comlink

The only way to communicate between a Web Worker and your main thread is through postMessage. While you don’t necessarily need Comlink to use Web Workers, Comlink makes it much easier to write a class in a web worker and expose it to be used from the main thread.

Communication between Web Worker & Your web page happens through postMessage

Comlink uses postMessage under the hood to communicate between the Web Worker & your page.

I believe that Comlink will motivate developers to rely more and more on Web Workers.

Fetch + Comlink

Comlink-fetch allows you to use Fetch in a web worker that is exposed through Comlink.

I recently published version 0.1.2 on npm. Here’s how it works:

Start by installing comlink-fetch from npm:

npm install comlink-fetch --save
install comlink-fetch

Then create a minimal index.html file that loads index.js:

I’m using JavaScript modules (type="module") because I want to be able to import Comlink from within that index.js

Now create an index.js with the below code:

Here’s a breakdown of what’s going on in this index.js:

  • You import Comlink from comlink.es6.js
  • You create a new Web Worker from comlink-fetch’s fetch.worker.js
  • You create a proxy for that worker using Comlink

And then you’re all set to use it! The rest of the code that I presented is a use case where you want to load some additional information in the background, for example posts that you’ll use later on.

Loading them in a web worker will make sure that they won’t block the main thread and won’t slow down your UI.

Network tab recording with Fast 3G network throttling

It’s worth noting that GET /posts/1 and GET /posts/2 are being executed at the same time, in the background.

How Comlink-fetch is built

Once you take a look at the source code of comlink-fetch’s fetch.worker.js, you’ll understand why Comlink is awesome.

I simply defined a class Fetch which is a wrapper on top of fetch that makes it possible to have nice features, such as setting a base url, default headers and default body.

You only have to import Comlink at the beginning and then expose the class you wrote so that it can be proxied from the the main thread later on.

Take a look at the signature of the class Fetch that I defined:

As you can see there’s no boilerplate or unnecessary code. Just a simple import at the beginning, and a Comlink.expose at the end.

Performance benefits

Will you directly see performance benefits if you use comlink-fetch? Most probably not. As outlined in this Stackoverflow thread by Konrad Dzwinel, a generic worker based fetch will not necessarily improve your performance.

However, if you have to do some heavy processing on fetched data, then it would make sense as you’re parsing results and processing them off the main thread.

Other alternatives to ComLink are workerize and greenlet which are developed by Jason Miller, the author of Preact and other awesome packages.

Stay tuned for more tips & tricks on how to use Web Workers in big projects, alongside some data about the performance benefits.

--

--