vitejs / vite

Next generation frontend tooling. It's fast!
http://vitejs.dev
MIT License
67.08k stars 6.02k forks source link

paintWorklet broken with production build (`.ts?url`) #6979

Open rynpsc opened 2 years ago

rynpsc commented 2 years ago

Describe the bug

When using paintWorklet a browser console error is thrown in production after running vite build. The error is:

Uncaught (in promise) DOMException: The user aborted a request.

This error does not occur when using the dev server via vite dev.

This can be reproduced at https://stackblitz.com/edit/vitejs-vite-x6rmew?file=index.html

  1. Run npm run dev
  2. check console for errors and that the paintWorklet is working, if working the button will have a black background and console will be free of errors.
  3. Run npm run build && npm run start
  4. Check console where you should see the error and the button won't have its black fill.

Reproduction

https://stackblitz.com/edit/vitejs-vite-x6rmew?file=index.html

System Info

System:
    OS: Linux 5.10 Debian GNU/Linux 11 (bullseye) 11 (bullseye)
    CPU: (2) x64 Intel(R) Core(TM) i5-4570 CPU @ 3.20GHz
    Memory: 1.78 GB / 3.84 GB
    Container: Yes
    Shell: 5.1.4 - /bin/bash
  Binaries:
    Node: 14.15.5 - /usr/local/nvm/versions/node/v14.15.5/bin/node
    Yarn: 1.22.17 - /usr/bin/yarn
    npm: 6.14.11 - /usr/local/nvm/versions/node/v14.15.5/bin/npm
  npmPackages:
    @vitejs/plugin-legacy: 1.7.1 => 1.7.1 
    vite: 2.8.4 => 2.8.4

Used Package Manager

npm

Logs

No response

Validations

haoqunjiang commented 2 years ago

It seems that Vite treats .ts?url as a media asset. Workaround: use .js instead of .ts.

That makes sense in some way. Because the .ts extension as TypeScript source file doesn't have a proper corresponding MIME type. So .ts?url is ambiguous. The best guess is video/mp2t.

Vite should warn against that usage in development. So I mark the issue as a minor bug.

astahmer commented 2 years ago

Hey, also got that error (wrong MIME video/mp2t type with .ts worker files) when building in production mode using:

new Worker(new URL('./generatePdf.worker.ts', import.meta.url), { type: 'module' })

it seems to work just fine with: import PdfWorker from './generatePdf.worker?worker'; even tho it's not the recommended/standard approach

bluwy commented 2 years ago

I'm not sure if it's about the mime type, since the issue in the repro is that the URL is being inline as a data uri, which causes the error. If we specify build.assetsInlineLimit: 0 to prevent that from happening, we get the raw TS file in the final bundle which wouldn't work if if the correct mime type is served because browsers don't understand TypeScript.

The issue seems to be that Vite treats them as pure assets like png, but instead if should be like workers with it's own custom handling.

@astahmer I'm surprised that the new Worker syntax doesn't work. Perhaps it's different bug with web worker handling but it should be working the same way as ?worker. Would appreciate if you can open another issue with a repro for it.

penx commented 1 year ago

I was stuck on this for audio workers for a while, incase it's of any help to anyone also ending up here I got it working with

import MyWorkletProcessorUrl from "./MyWorkletProcessor?worker&url";

...

await context.audioWorklet.addModule(MyWorkletProcessorUrl);

https://github.com/vitejs/vite/blob/main/docs/guide/features.md#import-with-query-suffixes

ersinakinci commented 5 months ago

I ran into this problem and used @penx's workaround. For me, it works when I build the bundle but gives me a bogus URL for the dev server.

My workaround for his workaround is to import twice, once for dev and once for prod, and use the appropriate URL:

import clientProd from "../client?worker&url";
import clientDev from "../client?url";

<script
  type="module"
  src={import.meta.env.PROD ? clientProd : clientDev}
/>