Web-workers in Create React App (CRA) without unmounting
Tags: createreactapp, comlink, workerize, threadsjs
Published: 2020-03-26 16:31:02

---
title: Web-workers in Create React App (CRA) without unmounting
published: true
description: How I used web-workers in my CRA-based app without unmounting.
tags: create-react-app,comlink,workerize,threads.js
---

There are a lot of great options available when it comes to using web-workers in your web-app. Unfortunately, it can be challenging to use in a [Create React Application (CRA)](xxx) without un-mounting your application.

In this article, we share my journey of using web-workers in CRA (without un-mounting!)

- [Why not unmounting?](#why-not-unmounting-)
- [Finding the right tools for YOU](#finding-the-right-tools-for-you)
  * [Attempt 1: Threads.js](#attempt-1--threadsjs)
  * [Attempt 2: Workarize](#attempt-2--workarize)
  * [Attempt 3: Worker-loader](#attempt-3--worker-loader)
  * [Attempt 4: Comlink](#attempt-4--comlink)
    + [How it looks](#how-it-looks)
- [That's it](#that-s-it)

<small><i><a href='http://ecotrust-canada.github.io/markdown-toc/'>Table of contents generated with markdown-toc</a></i></small>

# Why not unmounting?

* Webpack configuration can be overwhelming
* It can be difficult to upgrade to the next version of `react-scripts`
* CRA team will not help us if something goes side-ways

# Finding the right tools for YOU

The right tool for me would check the items in the following list:
* Must: Not unmounting CRA
* Must: Support [transferable objects](https://developer.mozilla.org/en-US/docs/Web/API/Transferable)
* Nice to have: Easy to use
* Nice to have: Typescript support
* Nice to have: Pooling system

## Attempt 1: Threads.js

[Threads.js](https://github.com/andywer/threads.js/) looked very promising and feature complete (according to my requirements).

However, to use it within `webpack`, you must use its companion loader ([threads-plugin](https://github.com/andywer/threads-plugin)).

That means you must access the `webpack` configuration file and add the loader there. That was a no-go for me because it implies un-mounting CRA.

## Attempt 2: Workarize

The next step was to find a tool that leverages `webpack loaders` rather than plugins. With `webpack loaders`, we can inline the loader in the import statement, therefore, we do not need to modify the `webpack` configuration file to use it.

```typescript
\\ inline the loader in the import statement
import {Something} from 'my-loader!./utils/filename'
```

[workarize](https://github.com/developit/workerize) and its [workarize-loader](https://github.com/developit/workerize-loader) seemed pretty cool. Although it doesn't support pooling the API looked awesome and super intuitive.

But it doesn't support transferable objects at the time I write this post (03-26-2020), so that was another no-go.

## Attempt 3: Worker-loader

Next, I tested [worker-loader](https://github.com/webpack-contrib/worker-loader) and its transferable objects.

It worked fine but using web-workers without sugar on top just didn't feel right for me - we can do better!

## Attempt 4: Comlink

Then comes [comlink](https://github.com/GoogleChromeLabs/comlink). It "makes WebWorkers enjoyable again" (to quote their README).

`comlink` works nicely with the `worker-loader` and adds this nice touch on top of the web-workers to make it easy to use.

It may provide features you do not need but works fine in my experience (so far 🤞).

It also works well with Typescript.

It doesn't support pooling but I can live with that!

### How it looks
```typescript
\\ main.ts
import * as Comlink from 'comlink';
/* eslint-disable import/no-webpack-loader-syntax */
import Worker from 'worker-loader!../util/worker';

async function init() {
  const worker = new Worker();
  const obj = Comlink.wrap(worker);
  await obj.inc();
}
init();

\\ worker.ts
import * as Comlink from 'comlink';

const obj = {
  counter: 0,
  inc() {
    this.counter++;
  }
};

Comlink.expose(obj);
```
# That's it
Each tool that was tested is great and you should really consider what you are looking for before making an informed decision.

I can live without pooling as long as it is enjoyable to work with the web-worker so that's why I chose `comlink`.

TLDR:
* ✅Must: Not unmounting CRA
* ✅Must: Support [transferable objects](xxx)
* ✅Nice to have: Easy to use
* ✅Nice to have: Typescript support
* 🔴Nice to have: Pooling system

Thanks for reading!