-
-
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. |
@@ -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?
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.
It seems this was added by #7099 and looks fine to simply remove the comment 👍
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.
Thank you! I left some minor comments.
let opts: WorkerOptions = {} | ||
try { | ||
opts = evalValue<WorkerOptions>(rawOpts) | ||
} catch { | ||
const { parseAstAsync } = await import('rollup/parseAst') |
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.
We statically import rollup/parseAst
in other places so let's do it here as well.
const optsNode = ((await parseAstAsync(`(${rawOpts})`)).body[0] as any) | ||
.expression |
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.
const optsNode = ((await parseAstAsync(`(${rawOpts})`)).body[0] as any) | |
.expression | |
const optsNode = ( | |
(await parseAstAsync(`(${rawOpts})`)) | |
.body[0] as RollupAstNode<ExpressionStatement> | |
).expression |
Let's add some types to make it safer.
} | ||
|
||
function extractWorkerTypeFromAst( | ||
astNode: any, |
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.
astNode: any, | |
astNode: Expression, |
continue | ||
} | ||
|
||
if (property.type === 'Property' && property.key?.name === 'type') { |
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.
if (property.type === 'Property' && property.key?.name === 'type') { | |
if ( | |
property.type === 'Property' && | |
((property.key.type === 'Identifier' && property.key.name === 'type') || | |
(property.key.type === 'Literal' && property.key.value === 'type')) | |
) { |
I think we can add support for { "type": "module" }
. It would be nice to have a test for this one.
) | ||
} | ||
|
||
if (typeProperty?.value?.type !== 'Literal') { |
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.
if (typeProperty?.value?.type !== 'Literal') { | |
if (typeProperty?.value.type !== 'Literal') { |
I guess this ?
is not necessary.
// @Note copied from packages/vite/src/shared/utils.ts | ||
const windowsSlashRE = /\\/g | ||
function slash(p: string): string { | ||
return p.replace(windowsSlashRE, '/') | ||
} | ||
|
||
async function createWorkerImportMetaUrlPluginTransform() { | ||
const root = slash(path.join(import.meta.dirname, 'fixtures/worker')) | ||
const config = await resolveConfig({ configFile: false, root }, 'serve') | ||
const instance = workerImportMetaUrlPlugin(config) | ||
const environment = new PartialEnvironment('client', config) | ||
|
||
return async (code: string) => { | ||
// @ts-expect-error transform should exist | ||
const result = await instance.transform.call( | ||
{ environment, parse: parseAst }, | ||
code, | ||
path.join(root, 'foo.ts'), | ||
) | ||
return result?.code || result | ||
} | ||
} |
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.
// @Note copied from packages/vite/src/shared/utils.ts | |
const windowsSlashRE = /\\/g | |
function slash(p: string): string { | |
return p.replace(windowsSlashRE, '/') | |
} | |
async function createWorkerImportMetaUrlPluginTransform() { | |
const root = slash(path.join(import.meta.dirname, 'fixtures/worker')) | |
const config = await resolveConfig({ configFile: false, root }, 'serve') | |
const instance = workerImportMetaUrlPlugin(config) | |
const environment = new PartialEnvironment('client', config) | |
return async (code: string) => { | |
// @ts-expect-error transform should exist | |
const result = await instance.transform.call( | |
{ environment, parse: parseAst }, | |
code, | |
path.join(root, 'foo.ts'), | |
) | |
return result?.code || result | |
} | |
} | |
async function createWorkerImportMetaUrlPluginTransform() { | |
const config = await resolveConfig({ configFile: false }, 'serve') | |
const instance = workerImportMetaUrlPlugin(config) | |
const environment = new PartialEnvironment('client', config) | |
return async (code: string) => { | |
// @ts-expect-error transform should exist | |
const result = await instance.transform.call( | |
{ environment, parse: parseAst }, | |
code, | |
'foo.ts', | |
) | |
return result?.code || result | |
} | |
} |
It seems we can now simplify this and align with assetImportMetaUrl.spec.ts
.
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.