DEV Community

Evan Winter
Evan Winter

Posted on • Edited on

Use Web Workers in a Gatsby project

Update Feb. 2022 – This probably doesn't work anymore... I haven't worked on a Gatsby project in a while. I'll try to find some time to revisit this and get it working again.

Introduction

Have a CPU-intensive task that's blocking your UI? Do you want to offload it to a background thread using a Web Worker? Here's how it's done in the context of a Gatsby project.

I came across this approach in a GitHub issue, and decided to write it up here for anyone else looking for the same solution.

Install dependencies

Install workerize-loader:

npm install --save workerize-loader # or yarn add workerize-loader
Enter fullscreen mode Exit fullscreen mode

Add workerize-loader to Webpack bundle

Now, we need to inject our workerize-loader configuration into the Webpack bundle generated by Gatsby.

To do so, add the following code to gatsby-node.js:

exports.onCreateWebpackConfig = ({ actions: { replaceWebpackConfig }, getConfig }) => {
  const config = getConfig()

  config.module.rules.push({
    test: /\.worker\.js$/,
    use: { loader: 'workerize-loader' }
  })

  config.output.globalObject = 'this'

  replaceWebpackConfig(config)
}
Enter fullscreen mode Exit fullscreen mode

This code gets the current Webpack config generated for us by Gatsby, and adds the workerize-loader rule which finds files with a .worker suffix and processes them as Web Workers.

Create a worker file

Create a file with a .worker suffix, like so:

// expensive.worker.js
export function doExpensiveTask(num) {
  let result = 0
  for (let i = 0; i < Math.pow(num, 10); i++) {
    result += result / i
  }
  return result
}
Enter fullscreen mode Exit fullscreen mode

Usage

Now, you can import it and use it like a normal function.

import MyWorker from "path/to/expensive.worker.js"

const result = MyWorker.doExpensiveTask(5)
Enter fullscreen mode Exit fullscreen mode

Bonus: Async Example

// expensive-async.worker.js
export async function doExpensiveAsyncTask() {
  const url = "https://jsonplaceholder.typicode.com/todos/1"
  return await fetch(url)
}
Enter fullscreen mode Exit fullscreen mode
import MyAsyncWorker from "path/to/expensive-async.worker.js"

const result = await MyAsyncWorker.doExpensiveAsyncTask()
Enter fullscreen mode Exit fullscreen mode

Top comments (2)

Collapse
 
niclaslovdahl profile image
Niclas Lövdahl

Do you have a working example of this? Can't get it working.

Collapse
 
4sight profile image
Peter

This worked well, and it was straightforward to integrate with typescript. Thanks