parcel: Parcel breaks `import.meta.url` in worker entry files
🐛 bug report
Parcel breaks trampoline code for worker instantiation:
// index.js
const workerURL = (await import("./worker.js")).WORKER_ENTRY_FILE_URL;
const blob = new Blob([`import "${workerURL}";`], { type: "text/javascript" });
new Worker(URL.createObjectURL(blob), { type: "module" });
// worker.js
export const WORKER_ENTRY_FILE_URL = import.meta.url;
🤔 Expected Behavior
The worker is instantiated properly, as it does when the source code is served either directly or with other tools:
Command | URL |
---|---|
npx serve (or any static file server) |
http://localhost:3000/src/ |
npx vite |
http://localhost:3000/src/ |
npx wmr |
http://localhost:8080/src/ |
npx esbuild src/index.js --format=esm --bundle --splitting --servedir=src |
http://localhost:8000/src/ |
😯 Current Behavior
Parcel errors with:
Not allowed to load local resource: file:///src/worker.js
💁 Possible Solution
There should be a way to preserve the semantics of import.meta.url
.
At the very least, it would be sufficient in our case if import.meta.url
is left untransformed when it is assigned to an export.
🔦 Context
We maintain a library that:
- is used in
node
and on the web (in particular, is available from a CDN), and - must use web workers for acceptable end-user experience, and
- is published and consumed by bundlers through
npm
.
Unfortunately, instantiating workers in a portable way is challenging. The trampoline approach is the closest to a universal approach.
💻 Code Sample
See https://github.com/lgarron/parcel-import-meta-url-bug for a runnable repro:
git clone https://github.com/lgarron/parcel-import-meta-url-bug && cd parcel-import-meta-url-bug
npx parcel src/index.html
🌍 Your Environment
Software | Version(s) |
---|---|
Parcel | 2.2.1 |
Node | v17.4.0 |
npm/Yarn | npm 8.3.1 |
Operating System | macOS 12.2 |
About this issue
- Original URL
- State: open
- Created 2 years ago
- Reactions: 1
- Comments: 24 (7 by maintainers)
As far as I know, this is still relevant.
Yeah, it’s been over a year and the choice continues to be:
esbuild
does not support (until https://github.com/evanw/esbuild/issues/312 or https://github.com/evanw/esbuild/issues/2866 is implemented).With both approaches it’s “obvious” how to maintain correctness with standard code splitting, so it’s a matter of the ecosystem settling on a cross-compatible solution.
For now, we’ve given up on Parcel compatibility, given that this issue is stalled.
I have read throughout this conversation and I do understand the maintainers and the users point of view somehow.
I just want to share some insights from using webpack for a similar issue.
we wanted to develop the worker script in typescript rather than in javascript. so webpack/tsc needs to transpile the typescript into javascript first and than provide a link to that javascript file, that works within a deployed environment - so no file:/// links. also we out-sourced the shared worker into it’s own library, so multiple applications can use it, instead of having the same shared worker file duplicated.
instance SharedWorker:
the interessting part here is, that the combination
new SharedWorker(new URL('xxx', import.meta.url))
must be written like this. it is not possible put any of those terms into a variable. otherwise webpack will not produce a working worker, or will even prevent it from compiling…it seems webpack handles to the combination of (Shared)Worker and URL specially to just fullfill the usecase.
https://webpack.js.org/guides/web-workers/
more from the example - in case someone stumbles across this.
tsconfig.ts
api module`s index.ts
shared-worker.ts