Skip to content

[BUG] Vite production builds doesn't recognise web worker #9

@VeryStrongFingers

Description

@VeryStrongFingers

Preface
I'm not sure whether this Is a bug with @okikio/sharedworker or Vite itself - thought it was best to report here firstly in case you've seen this before, or I'm doing something dumb.

Describe the bug
Only seems to affect Vite production builds, development works without issue.

When the worker is created through your package (via import SharedWorker from "@okikio/sharedworker";) Vite doesn't seem to recognise the Worker/SharedWorker and it will be missing from the production build. Usually workers are chunked separately (i.e. have their own file), but it's just missing entirely.

I believe Vite expects Web Workers to be constructed in the application itself, not within a separate package (node_modules).
https://v3.vitejs.dev/guide/features.html#web-workers

Versions
Vite 5.4.11 (latest at time of posting)
also tried older 5.3.* versions, same result

(I believe the usage of Vue & TypeScript is irrelevant here though)
Vue 3.5.6
TypeScript 4.7.4

Additional context
Seems that Vite does not recognise Web Workers that are constructed in a third-party package.
I have been able to resolve this issue with these changes

package:

--- a/src/index.ts
+++ b/src/index.ts
@@ -7,19 +7,15 @@
 export const SharedWorkerSupported = "SharedWorker" in globalThis;
 
 /**
  * A polyfill class for `SharedWorker`, it accepts a URL/string as well as any other options the spec. allows for `SharedWorker`. It supports all the same methods and properties as the original, except it adds compatibility methods and properties for older browsers that don't support `SharedWorker`, so, it can switch to normal `Workers` instead. 
  */
 export class SharedWorkerPolyfill implements SharedWorker, EventTarget, AbstractWorker {
     /**
      * The actual worker that is used, depending on browser support it can be either a `SharedWorker` or a normal `Worker`.
      */
     public ActualWorker: SharedWorker | Worker;
-    constructor(url: string | URL, opts?: WorkerOptions) {
-        if (SharedWorkerSupported) {
-            this.ActualWorker = new SharedWorker(url, opts);
-        } else {
-            this.ActualWorker = new Worker(url, opts);
-        }
+    constructor(worker: SharedWorker | Worker) {
+        this.ActualWorker = worker;
     }
 
     /**

usage:

        let worker: SharedWorkerPolyfill;

        if (SharedWorkerSupported) {
            worker = new SharedWorkerPolyfill(new SharedWorker(new URL("./../worker.ts", import.meta.url), { name: "position-sync", type: "module" }));
        } else {
            worker = new SharedWorkerPolyfill(new Worker(new URL("./../worker.ts", import.meta.url), { name: "position-sync", type: "module" }));
        }

^the above code means the new Worker/SharedWorker is part of the application now and is realised by Vue during the build.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions