question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Cannot execute Classic Worker in dev mode due to imports injected by Vite

See original GitHub issue

Describe the bug

Problem

When I created and executed a classic Web Worker in dev mode, browsers will throw an error:

Uncaught SyntaxError: Cannot use import statement outside a module

Here is how I created the classic Web Worker:

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

classicWorker.addEventListener('message', ({ data }) => {
  // do something
});
classicWorker.postMessage('ping');

And, here is the Web Worker file. Note that it doesn’t contain any import statements or dynamic imports:

self.addEventListener('message', () => {
  self.postMessage('pong');
});

Possible Reason

In dev mode, Vite will inject a special module /@vite/env for shimming environment variables, and it will introduce an import statement. The internal “worker” and “workerImportMetaUrl” plugin inject:

https://github.com/vitejs/vite/blob/33f96718dc5d827612c300fb6d0258f1c040f5a1/packages/vite/src/node/plugins/worker.ts#L63

https://github.com/vitejs/vite/blob/33f96718dc5d827612c300fb6d0258f1c040f5a1/packages/vite/src/node/plugins/workerImportMetaUrl.ts#L28

Then, the worker script will become: (for the example I mentioned above)

import '/@vite/env'
self.addEventListener('message', () => {
  self.postMessage('pong');
});

Because import statements aren’t allowed in classic Web Worker, browsers threw that error.

Possible Solution

I tried using importScripts which is available in Web Worker to import that /@vite/env module. It works for my case, since it’s a Classic Worker, not a Module Worker.

importScripts('/@vite/env'); // It works here.
// ...

However, when running Vite’s tests, they failed. It reported:

Failed to execute 'importScripts' on 'WorkerGlobalScope': Module scripts don't support importScripts().

so I don’t have ideas about fixing this problem.

Q & A

  • Q: Can I just switch to Module Worker? Vite will bundle it in build mode. A: No, because in my real case, that snippet about creating worker (new Worker(/* */)) comes from a third-party library, which I’m not able to control. Also, I use Firefox, fixing this bug would be better.

Reproduction

https://stackblitz.com/edit/vitejs-vite-y9bsxv?file=main.js&terminal=dev

System Info

Browsers:
Chrome 98.0.4758.102
Firefox 97.0.1
Microsoft Edge 98.0.1108.50

Used Package Manager

pnpm

Logs

No response

Validations

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:2
  • Comments:6 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
patak-devcommented, Feb 25, 2022

I think we can detect the case where { type: 'module' } is not provided or { type: 'classic' } is passed with a static string and use classic workers. As @bluwy said, there are other places where we do the same. If a dynamic expression appears, we can issue an error. Or give the user a way out of Vite processing. We currently don’t support this case anyways, no? Also, I don’t think there are a lot of use cases for a dynamic worker type in the context of a Vite app

1reaction
bluwycommented, Feb 25, 2022

if use user config and code is dynamic. can’t match all.

PS: { type: fn() }

I think it would be fair to assume that type will always be static. Vite has certain assumptions about syntax like this, e.g. for import.meta.glob assert raw, and new URL(..., import.meta.url) 🤔

Read more comments on GitHub >

github_iconTop Results From Across the Web

Features | Vite
Vite will detect such bare module imports in all served source files and perform the following: Pre-bundle them to improve page loading speed...
Read more >
Ninja Squad: Le Blog
The Angular team introduced an importProvidersFrom() function, that you could use in the bootstrapApplication function to import providers from ...
Read more >
worker-loader - webpack - JS.ORG
webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable...
Read more >
migrate from webpack to vite - フードコネクション
Projects Using Vite.js Open Source. In development mode, Vite will automatically inject your CSS into the page. [Example commit] In package.json, ...
Read more >
Documentation - Apache Kafka
Kafka 2.0 Documentation · 1. Getting Started. 1.1 Introduction; 1.2 Use Cases; 1.3 Quick Start; 1.4 Ecosystem · 2. APIs. 2.1 Producer API;...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found