Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

fix(worker): inline es worker does not work in build mode #14307

Merged
merged 5 commits into from
Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 26 additions & 17 deletions packages/vite/src/node/plugins/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,10 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
? 'module'
: 'classic'
: 'module'
const workerTypeOption = workerType === 'classic' ? undefined : 'module'
const workerTypeOption = `{
${workerType === 'module' ? `type: "module",` : ''}
name: options?.name
}`

if (isBuild) {
getDepsOptimizer(config, ssr)?.registerWorkersSource(id)
Expand All @@ -315,33 +318,42 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
// Using blob URL for SharedWorker results in multiple instances of a same worker
workerConstructor === 'Worker'
? `${encodedJs}
const blob = typeof window !== "undefined" && window.Blob && new Blob([atob(encodedJs)], { type: "text/javascript;charset=utf-8" });
const blob = typeof window !== "undefined" && window.Blob && new Blob([${
workerType === 'classic'
? ''
: // `URL` is always available, in `Worker[type="module"]`
`'URL.revokeObjectURL(import.meta.url);'+`
}atob(encodedJs)], { type: "text/javascript;charset=utf-8" });
export default function WorkerWrapper(options) {
let objURL;
try {
objURL = blob && (window.URL || window.webkitURL).createObjectURL(blob);
if (!objURL) throw ''
return new ${workerConstructor}(objURL, { name: options?.name })
const worker = new ${workerConstructor}(objURL, ${workerTypeOption});
worker.addEventListener("error", () => {
(window.URL || window.webkitURL).revokeObjectURL(objURL);
});
return worker;
} catch(e) {
return new ${workerConstructor}(
"data:application/javascript;base64," + encodedJs,
{
${workerTypeOption ? `type: "${workerTypeOption}",` : ''}
name: options?.name
}
${workerTypeOption}
);
} finally {
objURL && (window.URL || window.webkitURL).revokeObjectURL(objURL);
}${
// For module workers, we should not revoke the URL until the worker runs,
// otherwise the worker fails to run
workerType === 'classic'
? ` finally {
objURL && (window.URL || window.webkitURL).revokeObjectURL(objURL);
}`
: ''
}
}`
: `${encodedJs}
export default function WorkerWrapper(options) {
return new ${workerConstructor}(
"data:application/javascript;base64," + encodedJs,
{
${workerTypeOption ? `type: "${workerTypeOption}",` : ''}
name: options?.name
}
${workerTypeOption}
);
}
`
Expand Down Expand Up @@ -371,10 +383,7 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
code: `export default function WorkerWrapper(options) {
return new ${workerConstructor}(
${JSON.stringify(url)},
{
${workerTypeOption ? `type: "${workerTypeOption}",` : ''}
name: options?.name
}
${workerTypeOption}
);
}`,
map: { mappings: '' }, // Empty sourcemap to suppress Rollup warning
Expand Down
18 changes: 15 additions & 3 deletions playground/worker/__tests__/es/es-worker.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ test('normal', async () => {
})

test('named', async () => {
await untilUpdated(() => page.textContent('.pong-named'), 'pong', true)
await untilUpdated(() => page.textContent('.pong-named'), 'namedWorker', true)
})

test('TS output', async () => {
Expand All @@ -35,7 +35,19 @@ test('inlined', async () => {
})

test('named inlined', async () => {
await untilUpdated(() => page.textContent('.pong-inline-named'), 'pong', true)
await untilUpdated(
() => page.textContent('.pong-inline-named'),
'namedInlineWorker',
true,
)
})

test('import meta url', async () => {
await untilUpdated(
() => page.textContent('.pong-inline-url'),
/^(blob|http):/,
true,
)
})

test('shared worker', async () => {
Expand Down Expand Up @@ -83,7 +95,7 @@ describe.runIf(isBuild)('build', () => {
)

// worker should have all imports resolved and no exports
expect(workerContent).not.toMatch(`import`)
expect(workerContent).not.toMatch(/import[^.]/)
expect(workerContent).not.toMatch(`export`)
// chunk
expect(content).toMatch(`new Worker("/es/assets`)
Expand Down
8 changes: 6 additions & 2 deletions playground/worker/__tests__/iife/iife-worker.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ test('normal', async () => {
})

test('named', async () => {
await untilUpdated(() => page.textContent('.pong-named'), 'pong', true)
await untilUpdated(() => page.textContent('.pong-named'), 'namedWorker', true)
})

test('TS output', async () => {
Expand All @@ -38,7 +38,11 @@ test('inlined', async () => {
})

test('named inlined', async () => {
await untilUpdated(() => page.textContent('.pong-inline-named'), 'pong', true)
await untilUpdated(
() => page.textContent('.pong-inline-named'),
'namedInlineWorker',
true,
)
})

test('shared worker', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ test('normal', async () => {
})

test('named', async () => {
await untilUpdated(() => page.textContent('.pong-named'), 'pong', true)
await untilUpdated(() => page.textContent('.pong-named'), 'namedWorker', true)
})

test('TS output', async () => {
Expand Down
8 changes: 8 additions & 0 deletions playground/worker/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ <h2 class="format-iife">format iife:</h2>
</p>
<code class="pong-inline-named"></code>

<p>
import InlineWorker from '../my-worker?worker&inline'
<span>new InlineWorker()</span>
<span>import.meta.url</span>
<span class="classname">.pong-inline-url</span>
</p>
<code class="pong-inline-url"></code>

<p>
import TSOutputWorker from '../possible-ts-output-worker?worker'
<span class="classname">.pong-ts-output</span>
Expand Down
13 changes: 11 additions & 2 deletions playground/worker/my-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,22 @@ import { msg as msgFromDep } from '@vitejs/test-dep-to-optimize'
import { mode, msg } from './modules/workerImport.js'
import { bundleWithPlugin } from './modules/test-plugin'
import viteSvg from './vite.svg'
const metaUrl = import.meta.url

self.onmessage = (e) => {
if (e.data === 'ping') {
self.postMessage({ msg, mode, bundleWithPlugin, viteSvg })
self.postMessage({ msg, mode, bundleWithPlugin, viteSvg, metaUrl, name })
}
}
self.postMessage({ msg, mode, bundleWithPlugin, msgFromDep, viteSvg })
self.postMessage({
msg,
mode,
bundleWithPlugin,
msgFromDep,
viteSvg,
metaUrl,
name,
})

// for sourcemap
console.log('my-worker.js')
10 changes: 8 additions & 2 deletions playground/worker/worker/main-module.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ worker.addEventListener('message', (e) => {
const namedWorker = new myWorker({ name: 'namedWorker' })
namedWorker.postMessage('ping')
namedWorker.addEventListener('message', (e) => {
text('.pong-named', e.data.msg)
text('.pong-named', e.data.name)
})

const inlineWorker = new InlineWorker()
Expand All @@ -36,7 +36,13 @@ inlineWorker.addEventListener('message', (e) => {
const namedInlineWorker = new InlineWorker({ name: 'namedInlineWorker' })
namedInlineWorker.postMessage('ping')
namedInlineWorker.addEventListener('message', (e) => {
text('.pong-inline-named', e.data.msg)
text('.pong-inline-named', e.data.name)
})

const inlineWorkerUrl = new InlineWorker()
inlineWorkerUrl.postMessage('ping')
inlineWorkerUrl.addEventListener('message', (e) => {
text('.pong-inline-url', e.data.metaUrl)
})

const startSharedWorker = () => {
Expand Down