vitejs / vite

Next generation frontend tooling. It's fast!
http://vite.dev
MIT License
68.5k stars 6.18k forks source link

Allow custom generate web workers from custom plugins using custom constructors. #16128

Open Danielku15 opened 8 months ago

Danielku15 commented 8 months ago

Description

As an author of a library needing both Web Workers and Audio Worklets I want to provide developers (consumers of my library) using Vite, but also WebPack an easy integration of my library using plugins.

I am using a custom Web Worker constructor with the common syntax to ensure my plugin can configure the bundlers specifically for my workers: new Environment.alphaTabWorker(new URL('./alphatab.worker.js', import.meta.url), { type: "module" }).

Vite only supports workers if they use the default constructors like Worker or SharedWorker.

It might be the case that application authors have disabled or reconfigured the default worker settings to their needs and still generation of workers for my library should be possible.

Suggested solution

I would like to reuse certain functionality of the built-in worker and workerImportMetaUrl plugins from within my own plugin shipped along my library to create web workers using my own syntax.

Hence it would be needed that within my plugin I can trigger the built-in mechanisms to generate workers but using my syntax. And this even if for some reasons the default worker functionality is disabled.

My plugin shoudn't interfere with the user config more than necessary to activate the worker generation hence it would be good if I can implement the relevant bits in my plugin reusing provided functionalities.

Alternative

Unfortunately due to Angular having WebWorkers disabled by default in the angular.json I opted in my library for a custom syntax and handling of Workers hence changing the syntax to the default Worker is maybe not really possible without conflict.

As a starting point maybe Vite could also just expose a way of configuring the allowed constructors to extend Worker and SharedWorker with custom strings. But currently the RegExp in both related plugins check for only those strings.

Additional context

As a next step I will also have to consider audioWorklets where I will need to generate worker-like entry points. I'm not yet sure if and how Vite supports them but typically the web worker parts can be reused. The tricky part is the handling of transitive dependencies.

The matched syntax would be someVar.audioWorklet.addModule(new URL('./myworklet.js', import.meta.url)) or someVar.addModule(new URL('./myworklet.js', import.meta.url)).

Validations

hi-ogawa commented 8 months ago

As an author of a library needing both Web Workers and Audio Worklets I want to provide developers (consumers of my library) using Vite, but also WebPack an easy integration of my library using plugins.

Can you clarify whether you expect some transform to be done to worker source files (such as ./alphatab.worker.js and ./myworklet.js)? From the description, it looks like you are only concerned with how to reference fully transpiled/bundled worker file as url, but I think clarifying that might help just in case.

For example, for AudioWorklet, there is some known issue when applying Vite's transform during dev due to a limited feature of AudioWorkletGlobalScope https://github.com/vitejs/vite/discussions/15036, so you might not want any transform for this case.

Danielku15 commented 8 months ago

Can you clarify whether you expect some transform to be done to worker source files

I'm thinking of following approach for best reusability:

So to answer the question: I think yes, transforms/plugins for workers should also be supported like today. I'm thinking that maybe for the compatibility with audio worklets and their restrictions some special plugins should be injected to the worklet script.

For example, for AudioWorklet, there is some known issue when applying Vite's transform during dev due to a limited feature of AudioWorkletGlobalScope https://github.com/vitejs/vite/discussions/15036, so you might not want any transform for this case.

I faced similar problems with my WebPack plugin as the AudioWorkletGlobalScope is quite limited (especially as there are no dynamic imports or importScripts available). In webpack I found my way by calling .addModule() myself for the dependency graph and ensuring the pre-injected chunks are considered correctly. Multiple calls to .addModule end up in the same worklet context.

In detail I'm not yet that far with Vite to see what conflicts I have with the defaults injected to modules. But you might be right with my need to customize some aspects of the entry point and shared chunks.