Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to import WebWorkers #403

Closed
ashubham opened this issue Jun 17, 2020 · 10 comments
Closed

Ability to import WebWorkers #403

ashubham opened this issue Jun 17, 2020 · 10 comments
Labels
enhancement New feature or request

Comments

@ashubham
Copy link
Contributor

ashubham commented Jun 17, 2020

Is your feature request related to a problem? Please describe.

I have been using Rollup with the https://github.com/darionco/rollup-plugin-web-worker-loader . Which enables to load web workers within modules. I want to move to ViteJS for Dev but this limitation prevents me from doing the migration.

Describe the solution you'd like
Support web-workers import within ViteJS.

Describe alternatives you've considered

Not moving to VIte until this is resolved.

Additional context
There are other plugins which do the same thing like: https://github.com/surma/rollup-plugin-off-main-thread

@hellboywar
Copy link

hellboywar commented Jun 18, 2020

In fact WebWorkers work just fine in dev out of the box, but not in prod though...

try this:

// src/index.js
import { wrap } from 'https://unpkg.com/comlink/dist/esm/comlink.mjs';

const worker = new Worker('src/worker.js', { type: 'module' });
const obj = wrap(worker);

obj.inc().then(count => {
  console.log('count', count);
  // count 1
});


// src/worker.js
import { expose } from 'https://unpkg.com/comlink/dist/esm/comlink.mjs';

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

expose(obj);

or if workers module support is an issue

// src/index.js
import { wrap } from 'https://unpkg.com/comlink/dist/esm/comlink.mjs';

const worker = new Worker('src/worker.js');
const obj = wrap(worker);

obj.inc().then(count => {
  console.log('count', count);
  // count 1
});

// src/worker.js
importScripts("https://unpkg.com/comlink/dist/umd/comlink.js");

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

Comlink.expose(obj);

@yyx990803
Copy link
Member

yyx990803 commented Jun 18, 2020

Since the worker file should be left un-bundled for production, you can place in public and then do new Worker('/worker.js') (files in public are referenced from root).

I guess what @ashubham want is to be able to import the work script (and automatically inlining it into the bundle), which is a reasonable feature request, but standard worker usage should just work when it's inside public.

@yyx990803 yyx990803 added the enhancement New feature or request label Jun 18, 2020
@ashubham
Copy link
Contributor Author

Thanks @yyx990803 Yes thats what I am looking for, inlining workers into modules.

@intrnl
Copy link
Contributor

intrnl commented Jun 30, 2020

One thing I see from the ?worker import is that you can't really configure the type of worker you want.

Module workers can benefit from code splitting between main entrypoint and worker, or perhaps you wanted a SharedWorker instead? 🙂

edit: actually I realized just now that it does a module worker by default, but that still doesn't address the second point of wanting to do a SharedWorker with module type.

@intrnl
Copy link
Contributor

intrnl commented Jun 30, 2020

I might be nitpicking too much here, but is there a way to configure it so that it doesn't inline?

with large workers it makes the bundle sizes considerably large considering that it has to account for sourcemaps as well (?, not sure why this is chucked in during production)

@yyx990803
Copy link
Member

If you don't want inline, you can just put the worker script in public and use it like normal.

@intrnl
Copy link
Contributor

intrnl commented Jun 30, 2020

That wouldn't get you the code splitting benefits of a module worker though unfortunately 😅

@intrnl
Copy link
Contributor

intrnl commented Jun 30, 2020

I could perhaps write a plugin to override this behavior ^^

@egriff38
Copy link

Any known workaround for this? Looking to port parcel 1 project to Vite, and bundling of worker dependencies is the one feature still outstanding for me. I suppose if it is inlined, one could make use of the dynamic import() to avoid oversized inlines?

// worker-import.js
export {default} from './worker-file?worker'

// main.js
(async () => {
  const MyWorker = await import('./worker-import') // dynamic import allows code splitting, yes?
  //...
})()

For that matter, is there anything barring the use of ?worker flag inside a dynamic import?

  const MyWorker = await import('./worker-file?worker')

@userquin
Copy link
Contributor

userquin commented Mar 15, 2021

@egriff38 have you tried this?

const MyWorkerModule = await import('./worker-file?worker')
const myWorker = MyWorkerModule.default()

Since you are using dynamic import, then the definition is wrong, it is a hack so you can use it as a constructor:

cliend.d.ts

// web worker
declare module '*?worker' {
  const workerConstructor: {
    new (): Worker
  }
  export default workerConstructor
}

but the function is just a plain function returning the worker (you can see it in worker plugin):

src/node/plugins/worker.ts

async transform(_, id) {
  ...
  return `export default function WorkerWrapper() {
    return new Worker(${JSON.stringify(url)}, { type: 'module' })
  }`
}

@github-actions github-actions bot locked and limited conversation to collaborators Jul 16, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

6 participants