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
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)
}
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
}
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)
Bonus: Async Example
// expensive-async.worker.js
export async function doExpensiveAsyncTask() {
const url = "https://jsonplaceholder.typicode.com/todos/1"
return await fetch(url)
}
import MyAsyncWorker from "path/to/expensive-async.worker.js"
const result = await MyAsyncWorker.doExpensiveAsyncTask()
Top comments (2)
Do you have a working example of this? Can't get it working.
This worked well, and it was straightforward to integrate with typescript. Thanks