The case for Workers
See original GitHub issueDo you want to request a feature or report a bug?
Feature! 🎉
What is the current behavior?
(This is gonna be a bit longer.)
Let’s imagine working on a project using WebWorkers. Let’s say I am using this great new shiny library Comlink. It’s needed by both main.js
and worker.js
as Comlink is an abstraction over postMessage
. Of course both main.js
and worker.js
have other dependencies besides Comlink.
(You might already be able to tell where I’m going with this)
Attempt 1: Entry points
Listing both worker.js
and main.js
as entry points doesn’t yield the expected results as all static imports will be inlined. Comlink will be (down)loaded twice. The semantics of entry points are that only one entry point will be loaded at a time. In the context of my example, though, two entry points are loaded in parallel.
Attempt 2: Dynamic loading
I tried some hackery with import()
, but the problem is that WebPack (rightly) assumes that there’s is a global registry of loaded modules. worker.js
, however, runs in a different realm and has a separate global scope to main.js
Workaround: Force a common chunk
My current workaround is to use the entry point approach and manually maintain a list of shared modules that need to be put in a separate chunk using CommonChunksPlugin
:
module.exports = {
entry: {
main: './src/main.js',
worker: './src/worker.js',
},
output: {
filename: '[name].js',
},
plugins: [
// Force comlink into its own bundle
new webpack.optimize.CommonsChunkPlugin({
name: 'comlink',
minChunks: 2,
}),
],
};
If the current behavior is a bug, please provide the steps to reproduce.
What is the expected behavior?
Under the assumption that there’s good caching headers, the optimal behavior is to put Comlink in it’s own chunk (or a chunk for shared modules) so it’s only downloaded once. The second request by the worker will hit the HTTP cache and re-use the already downloaded shared chunk.
API
I’m not sure what the API for this would look like. This API would not only be useful for workers, but also for pages that load another entry point in an iframe (although, tbh, I struggle to find a good example for this 🤷♂️ )
I think the most straight-forward way would to add a realmEndpoints
(name pending lol) to the webpack config which lists entry points that can be loaded in parallel to one of the main entry points.
What do y’all think? API suggestions/corrections? Am I just holding it wrong?
If this is a feature request, what is motivation or use case for changing the behavior?
Please mention other relevant information such as the browser version, Node.js version, webpack version and Operating System.
Issue Analytics
- State:
- Created 6 years ago
- Reactions:49
- Comments:35 (11 by maintainers)
I forgot about that bit! In my workaround (see below) I currently also hand-load the chunks using
importScript
. I think an agnostic format that can be loaded by both workers and web would be great to see.@sokra and @anilanar thank very much for clarifications. I understand that new way of creating a worker is
const w = new Worker(new URL('./worker.js', import.meta.url));
which will handle things for us, but could you please clarify how can I do the same without usingimport.meta.url
? From my understand steps should be like this:chunks: 'all', minSize: 0,
const w = new Worker('worker.js')
andconst w = new Worker('./worker.js')
doesn’t work.I guess I should use a new way of importing assets in Webpack 5 or somehow construct the URL without using
import.meta.url
. Or I just should use old WorkerLoader for this purpose?Could you please help me with that?