-
-
Notifications
You must be signed in to change notification settings - Fork 6.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(worker): support dynamic worker option fields #19010
base: main
Are you sure you want to change the base?
feat(worker): support dynamic worker option fields #19010
Conversation
Looks like this change broke the tests in two ways 😅
I'll look into fixing these tomorrow. |
expect( | ||
await transform('new Worker(new URL("./worker.js", import.meta.url))'), | ||
).toMatchInlineSnapshot( | ||
`"new Worker(new URL(/* @vite-ignore */ "/worker.js?worker_file&type=classic", import.meta.url))"`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
packages/vite/src/node/__tests__/plugins/workerImportMetaUrl.spec.ts > workerImportMetaUrlPlugin > without worker options
Error: Snapshot `workerImportMetaUrlPlugin > without worker options 1` mismatched
Expected: ""new Worker(new URL(/* @vite-ignore */ "/worker.js?worker_file&type=classic", import.meta.url))""
Received: ""new Worker(new URL(/* @vite-ignore */ "/@fs/D:/a/vite/vite/worker.js?worker_file&type=classic", import.meta.url))""
Is there a way to compensate for this when testing on windows? Or should I add some kind of flag or annotation to skip the tests when isWindows
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you try setting up an actual fixture? Something like this. You might not need an actual files, but importer being full id probably affects transform behavior.
const root = path.join(import.meta.dirname, "fixtures/worker")
const config = await resolveConfig({ configFile: false, root }, 'serve') //// <---- pass root
...
const result = await instance.transform.call(
{ environment, parse: parseAst },
code,
path.join(root, 'foo.ts'), //// <---- pass full id
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the suggestion @hi-ogawa.
After debugging further it seems as if there may be a bug or undesired handling for windows paths in this plugin.
- The worker file is resolved initially with
path.resolve
and thentryFsResolve
. Both would result in a windows-like path:
D:\\a\\vite\\vite\\packages\\vite\\src\\node\\__tests__\\plugins\\fixtures\\worker\\worker.js
-
The plugin then tries to turn this into a dev asset url with the function
fileToUrl
which internally callsfileToDevUrl
. However, the function assumes that it is dealing with posix paths. This results in the method always returning an absolute URL, instead of the expected relative URL.
vite/packages/vite/src/node/plugins/asset.ts
Lines 297 to 299 in ac32968
} else if (id.startsWith(withTrailingSlash(config.root))) { // in project root, infer short public path rtn = '/' + path.posix.relative(config.root, id)
Theif
condition above will always returnfalse
when a windows string is presented. -
Vite configures the absolute URL as seen in the test failure
Does Vite have any guidelines on handling Windows paths? It feels like at step 1. we should turn the path into a posix path 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. Actually this looks suspicious and we probably want slash(path.resolve(...))
like it's done in assetImportMetaUrlPlugin
vite/packages/vite/src/node/plugins/assetImportMetaUrl.ts
Lines 114 to 116 in ac32968
if (url[0] === '.') { | |
file = slash(path.resolve(path.dirname(id), url)) | |
file = tryFsResolve(file, fsResolveOptions) ?? file |
I don't use Windows, so I'm just guessing though.
@@ -140,7 +140,6 @@ const genWorkerName = () => 'module' | |||
const w2 = new SharedWorker( | |||
new URL('../url-shared-worker.js', import.meta.url), | |||
{ | |||
/* @vite-ignore */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removing the comment as the options can now legitimately be used as defined.
Should we add any explicit tests in the playground or will this suffice?
Description
The Problem
Vite has a hard requirement that worker options are defined statically or it throws an error. This prevents some legitimate use cases, such as when a dynamic name is used to differentiate workers. As seen in the Emscripten project (code reference)
This is causing some issues in trying to update Emscripten to support Vite when workers are in use.
Solution
Vite only needs to ensure that the
type
value is statically defined. Other fields could be dynamically computed with no effect on the Vite bundling process.A side discussion was started in #18396 (comment) about relaxing the usage of some worker option fields to support this.
This PR hopes to solve this issue in a backwards compatible way that still ensures that Vite can have high confidence in asserting the worker type at compile time.