Giter Site home page Giter Site logo

parcel-import-meta-url-bug's Introduction

Parcel import.meta.url bug

Repro

Run any of these:

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/

Expected

If you open the appropriate URL for the commands above, you'll end up with Received message: 4 in the JS console.

Bug

However, if you run npx parcel src/index.html and open http://localhost:1234/ then it fails with:

Not allowed to load local resource: file:///src/worker.js

Explanation

It is very difficult to write a library using web workers that will correctly run in node and on the web (in particular, when hosted on a CDN) and won't be mangled by bundlers. This repo demonstrates a bug or assumption in Parcel that breaks semantics, which is otherwise be a good cross-compatible solution for module workers.

Note that it's possible work around this by trying other methods as fallbacks, but that is still pretty difficult to maintain in a library because people will still run that library through various toolchains. I would like to advocate that there should be at least one solution that has the proper semantics in ESM and won't be broken by bundlers.

The fundamental challenge is that this does not always work:

const worker = new Worker("./worker-entry.js", { type: "module" });
  1. Some bundlers do not pick up "./worker-entry.js" as an entry path (i.e. don't treat it like a dynamic import) and therefore do not preserve the semantics without plugins or hacks.
  2. This code does not work when served from a CDN, because the browser will try to construct the worker with the CDN's origin and then deny this due to security restrictions. So we have to use a trampoline:
const workerURL = "https://cdn.cubing.net/worker.js";
const blob = new Blob([`import "${workerURL}";`], { type: "text/javascript" });
new Worker(URL.createObjectURL(blob), { type: "module" });

It's possible to instantiate the worker using a trampoline if you can get its URL, but that URL will often be rewritten by bundlers. An obvious approach would be to compute the URL using new URL("./worker-entry.js", import.meta.url), but many bundlers do not preserve the semantics of this either (because there could be lots of reasons to construct a relative URL, not just for code).

However, most bundlers actually preserve the semantic meaning a dynamic import as a form of code splitting. And thanks to import.meta.url, it's possible to ask a worker file for its own file URL, which can be used for 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;

This has very well-defined semantics in ESM, and most bundlers seem to preserve it. Unfortunately, Parcel seems to rewrite the import.meta.url calculation to 'file:///worker.js instead of preserving the runtime semantics.

I'd like to ask the Parcel team for some way to preserve the semantics so that it also works in Parcel without any custom hacks.

parcel-import-meta-url-bug's People

Contributors

lgarron avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.