Skip to content

Commit c82a7d1

Browse files
committed
feat: allow worker options via variable
1 parent 159b4f4 commit c82a7d1

File tree

4 files changed

+77
-3
lines changed

4 files changed

+77
-3
lines changed

docs/guide/features.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,15 @@ const worker = new Worker(new URL('./worker.js', import.meta.url), {
657657
})
658658
```
659659

660-
The worker detection will only work if the `new URL()` constructor is used directly inside the `new Worker()` declaration. Additionally, all options parameters must be static values (i.e. string literals).
660+
The worker detection will only work if the `new URL()` constructor is used directly inside the `new Worker()` declaration. Additionally, all options parameters must be static values (i.e. string literals), or a variable that is defined before the `new Worker()`, as follows:
661+
662+
```ts
663+
const workerOptions = { type: 'module' }
664+
const worker = new Worker(
665+
new URL('./worker.js', import.meta.url),
666+
workerOptions,
667+
)
668+
```
661669

662670
### Import with Query Suffixes
663671

packages/vite/src/node/plugins/workerImportMetaUrl.ts

+50-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ function parseWorkerOptions(
3434
opts = evalValue<WorkerOptions>(rawOpts)
3535
} catch {
3636
throw err(
37-
'Vite is unable to parse the worker options as the value is not static.' +
37+
'Vite is unable to parse the worker options as the value is neither static or variable.' +
3838
'To ignore this error, please use /* @vite-ignore */ in the worker options.',
3939
optsStartIndex,
4040
)
@@ -54,6 +54,38 @@ function parseWorkerOptions(
5454
return opts
5555
}
5656

57+
function findVarDefinition(
58+
raw: string,
59+
clean: string,
60+
endIndex: number,
61+
errorReportIndex: number,
62+
varName: string,
63+
): [string, number] {
64+
const workerOptionsVarRE = new RegExp(
65+
`(?:var|let|const)\\s*${varName}\\s*=\\s*`,
66+
'g',
67+
)
68+
69+
let optsStartIndex = 0
70+
while (workerOptionsVarRE.exec(clean)) {
71+
if (workerOptionsVarRE.lastIndex >= endIndex) break
72+
optsStartIndex = workerOptionsVarRE.lastIndex
73+
}
74+
75+
if (optsStartIndex == 0) {
76+
throw err(
77+
'Vite is unable to parse the worker options as the value is neither static or variable. ' +
78+
'To ignore this error, please use /* @vite-ignore */ in the worker options.',
79+
errorReportIndex,
80+
)
81+
}
82+
83+
const optsEndIndex = clean.indexOf('}', optsStartIndex)
84+
const workerOptString = raw.substring(optsStartIndex, optsEndIndex + 1)
85+
86+
return [workerOptString, optsStartIndex]
87+
}
88+
5789
function getWorkerType(raw: string, clean: string, i: number): WorkerType {
5890
const commaIndex = clean.indexOf(',', i)
5991
if (commaIndex === -1) {
@@ -82,7 +114,23 @@ function getWorkerType(raw: string, clean: string, i: number): WorkerType {
82114
return 'classic'
83115
}
84116

85-
const workerOpts = parseWorkerOptions(workerOptString, commaIndex + 1)
117+
let workerOpts: WorkerOptions
118+
119+
// if worker options is a variable, try to find its closest definition
120+
const varMatch = cleanWorkerOptString.match(/^\s*(\w+)\s*(?:,\s*)?$/)
121+
if (varMatch) {
122+
const [workerOptString, workerOptIndex] = findVarDefinition(
123+
raw,
124+
clean,
125+
i,
126+
commaIndex + 1,
127+
varMatch[1],
128+
)
129+
workerOpts = parseWorkerOptions(workerOptString, workerOptIndex)
130+
} else {
131+
workerOpts = parseWorkerOptions(workerOptString, commaIndex + 1)
132+
}
133+
86134
if (
87135
workerOpts.type &&
88136
(workerOpts.type === 'module' || workerOpts.type === 'classic')

playground/worker/index.html

+7
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,13 @@ <h2 class="format-iife">format iife:</h2>
9999
</p>
100100
<code class="worker-import-meta-url-without-extension"></code>
101101

102+
<p>
103+
var workerOptions = { type: 'module' } new Worker(new URL('./url-worker.js',
104+
import.meta.url), workerOptions)
105+
<span class="classname">.worker-import-meta-url-via-variable</span>
106+
</p>
107+
<code class="worker-import-meta-url-via-variable"></code>
108+
102109
<p>
103110
new SharedWorker(new URL('./url-shared-worker.js', import.meta.url), { type:
104111
'module' })

playground/worker/worker/main-module.js

+11
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,17 @@ wWithoutExt.addEventListener('message', (ev) =>
135135
text('.worker-import-meta-url-without-extension', JSON.stringify(ev.data)),
136136
)
137137

138+
const myWorkerOptions = { type: 'module' }
139+
140+
// url import worker via variable
141+
const wViaVariable = new Worker(
142+
new URL('../url-worker', import.meta.url),
143+
myWorkerOptions,
144+
)
145+
wViaVariable.addEventListener('message', (ev) =>
146+
text('.worker-import-meta-url-via-variable', JSON.stringify(ev.data)),
147+
)
148+
138149
const genWorkerName = () => 'module'
139150
const w2 = new SharedWorker(
140151
new URL('../url-shared-worker.js', import.meta.url),

0 commit comments

Comments
 (0)