next.js
next.js copied to clipboard
Wrong file path generated when using new URL with import.meta.url as the base.
Verify canary release
- [X] I verified that the issue exists in the latest Next.js canary release
Provide environment information
Operating System: Platform: darwin Arch: arm64 Version: Darwin Kernel Version 21.4.0: Fri Mar 18 00:47:26 PDT 2022; root:xnu-8020.101.4~15/RELEASE_ARM64_T8101 Binaries: Node: 16.15.1 npm: 8.11.0 Yarn: 1.22.17 pnpm: N/A Relevant packages: next: 12.2.4-canary.12 eslint-config-next: 12.2.4 react: 18.2.0 react-dom: 18.2.0
What browser are you using? (if relevant)
No response
How are you deploying your application? (if relevant)
No response
Describe the Bug
When trying to create a url to a file using new URL(<path_to_file>, import.meta.url) the second argument seems to be ignored. I'm getting /_next/static/media/file.js whereas, according to webpack docs It should be prefixed with the document.baseURI.
I've tried to reproduce it in a vanilla webpack project as well with CRA with no luck, so I assume it's somehow related to next's webpack config.
I first encountered this when trying to use a Stencil generated component library in a next app. The library used web workers and they'd throw Uncaught DOMException: Failed to execute 'importScripts' on 'WorkerGlobalScope': The URL '/_next/static/media/file.js' is invalid. in Chrome (and similar errors in Firefox and Safari). However if I tried to open the file, it was there.
This issue affects Stencil due to how they implement their web workers transform. When building for a component library what they do is generate the url to the file (using new URL with import.meta.url as the base), then create a Blob with importScripts('<url.href>') and then use that blob as the scriptURL for the worker. Since importScripts needs the full file url, not just an absolute path, it fails.
Expected Behavior
A proper file url is generated, so that it can be consumed inside workers.
Link to reproduction
https://stackblitz.com/edit/vercel-next-js-zvgw7e?file=pages/index.tsx
To Reproduce
Open the minimal reproduction & check the console output.
I have opened a related issue in the stencil repo. Found a fix there, so maybe this will get (partially?) fixed. For reference: https://github.com/ionic-team/stencil/issues/3512
This might be because in your example the URL is created at the top-level of the module, where document would be undefined, but webpack will use a different target anyway, creating a different URL.
See: https://webpack.js.org/guides/asset-modules/#url-assets:~:text=location)%3B-,//%20target%3A%20node,-%2C%20node%2Dwebkit%2C%20nwjs
An example of setting up a Web Worker in Next.js is here:
https://github.com/vercel/next.js/blob/0571885ec4e324b4722c24712677169851ed3560/examples/with-web-worker/pages/index.js#L6
Hey @balazsorban44 thanks for your answer.
At the top level document would be defined for the web target, however this is irrelevant, if I put the code in a useEffect hook it clearly demonstrates the bug I'm getting with Stencil.
https://stackblitz.com/edit/vercel-next-js-dv2xc3?file=pages%2Findex.tsx
I agree that the way you shared would work, but sadly this isn't how Stencil uses Web Workers.
See also https://github.com/vercel/next.js/issues/37031 .