Shopify / quilt

A loosely related set of packages for JavaScript/TypeScript projects at Shopify
MIT License
1.7k stars 220 forks source link

Web worker blocks main thread and freezes UI #2232

Open szymswiat opened 2 years ago

szymswiat commented 2 years ago

Overview

I'm using createWorkerFactory and useWorker exactly as shown here, but long running operation started on "web worker" completely freezes UI, like it was executing on main thread.

Scope

szymswiat commented 2 years ago

I created an example with reproducing issue: https://codesandbox.io/s/hopeful-mcnulty-xwy9m4?file=/src/worker.ts

852Kerfunkle commented 2 years ago

Same issue here.

alexcrist commented 2 years ago

I seem to be running into the same problem

qmn1711 commented 2 years ago

Same issue here. Any update pls?

alexcrist commented 2 years ago

Actually, I believe my problem was due to the fact that I created my project using create-react-app which seems to be incompatible with this particular web-worker library

maht0rz commented 2 years ago

@alexcrist how did you end up solving your problem? I also can't get this to work while trying to follow instructions from the shopify web worker tooling docs.

I've adjusted my CRA webpack config using craco, but my worker script is still included in the main thread, rather than in a standalone worker.

alexcrist commented 2 years ago

@maht0rz - I ended up writing my web worker code without an external library. Unfortunately, the project isn't open source but I'll post some key snippets.

file1.js - the file that calls the web worker


const worker = new Worker(new URL('./file2.js', import.meta.url));

const App = () => {

  // Code...

  const onCalculate = async () => {
    worker.postMessage({ someDataDefinedElsewhereInTheComponent });
    worker.addEventListener('message', (message) => {
      const workerResponse = message.data;
      // Handle worker response here
    });
  };

  // More code...
};

export default App;

file2.js - the web worker


self.onmessage = async (message) => {
  const workerInput = message.data;
  const result = doWork(workerInput);
  self.postMessage(result);
};
VithuJey commented 1 year ago

any update on this issue?

eyorokoninvivoax commented 1 year ago

I came across this: https://stackoverflow.com/a/48234335 which points to https://nolanlawson.com/2016/02/29/high-performance-web-worker-messages/ and says to serialize the data sent to the web worker. But I'm still not having any luck and my UI still freezes.

I like how simple Shopify's Web Worker implementation is but since it's not working - Are there any other alternatives to this package anyone recommends in the meantime?

Andonvr commented 1 year ago

I'm having the same problem. I thought the point of WebWorkers was to have them run in the background, and not block the UI...? Why use this package then?

// test.worker.ts
export const test = () => {
  const id = Math.random() * 10

  for (let i = 0; i < 1000000000; i++) {
    continue
  }
  return "DONE!"
}
// useTestWorker.ts
import { useCallback, useEffect, useState } from "react"
import { createWorkerFactory, useWorker } from "@shopify/react-web-worker"

const createWorker = createWorkerFactory(() => import("../workers/test.worker"))

export const useTestWorker = () => {
  const worker = useWorker(createWorker)

  useEffect(() => {
    const runWorker = async () => {
      const result = await worker.test()
      console.log(result)
    }
    runWorker()
  }, [worker])
}
Wxh16144 commented 10 months ago

I'm having this problem too and it's very frustrating.

onursercanyilmaz commented 8 months ago

I'm encountering a similar issue despite trying Shopify's package, but the UI freezes persist.

Arichy commented 7 months ago

Same issue here. It seems that the code in worker.ts is actually run in main thread because I tried printing window in it and it had window.

image

iSuslov commented 5 months ago

Make sure your bundler is properly configured: https://github.com/Shopify/quilt/tree/main/packages/web-worker#tooling

This library only works if your application is bundled with webpack.