Skip to content

Commit

Permalink
fix: correct shared worker test
Browse files Browse the repository at this point in the history
  • Loading branch information
fi3ework committed Mar 8, 2023
1 parent b111ee7 commit dbe765b
Show file tree
Hide file tree
Showing 11 changed files with 77 additions and 26 deletions.
2 changes: 1 addition & 1 deletion docs/config/worker-options.md
Expand Up @@ -14,7 +14,7 @@ Output format for worker bundle.
- **Type:** `'blob' | 'base64'`
- **Default:** `'blob'`

URL type for inline worker, when setting to `'blob'`, the worker will be loaded as a blob URL with a fallback to data URL. Set to `'base64'` to load the worker as a data URL.
URL type for inline worker, when setting to `'blob'`, the worker will be loaded as a blob URL with a fallback to data URL. Set to `'base64'` to load the worker as a data URL. When not set, `inlineUrl` will be `'blob'` for Worker and `'base64'` for SharedWorker as blob URL not works with a shared worker.

## worker.plugins

Expand Down
4 changes: 2 additions & 2 deletions packages/vite/src/node/config.ts
Expand Up @@ -320,9 +320,9 @@ export interface LegacyOptions {

export interface ResolveWorkerOptions extends PluginHookUtils {
format: 'es' | 'iife'
inlineUrl: 'blob' | 'base64'
plugins: Plugin[]
rollupOptions: RollupOptions
inlineUrl?: 'blob' | 'base64'
}

export interface InlineConfig extends UserConfig {
Expand Down Expand Up @@ -637,7 +637,7 @@ export async function resolveConfig(
workerConfig = await runConfigHook(workerConfig, workerUserPlugins, configEnv)
const resolvedWorkerOptions: ResolveWorkerOptions = {
format: workerConfig.worker?.format || 'iife',
inlineUrl: workerConfig.worker?.inlineUrl || 'blob',
inlineUrl: workerConfig.worker?.inlineUrl,
plugins: [],
rollupOptions: workerConfig.worker?.rollupOptions || {},
getSortedPlugins: undefined!,
Expand Down
23 changes: 21 additions & 2 deletions packages/vite/src/node/plugins/worker.ts
@@ -1,4 +1,5 @@
import path from 'node:path'
import colors from 'picocolors'
import MagicString from 'magic-string'
import type { EmittedAsset, OutputChunk } from 'rollup'
import type { ResolvedConfig } from '../config'
Expand Down Expand Up @@ -281,6 +282,7 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
const encodedJs = `const encodedJs = "${Buffer.from(
chunk.code,
).toString('base64')}";`

const blobCode = `${encodedJs}
const blob = typeof window !== "undefined" && window.Blob && new Blob([atob(encodedJs)], { type: "text/javascript;charset=utf-8" });
export default function WorkerWrapper() {
Expand All @@ -298,9 +300,26 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
}
`

// inline as blob data url
// If inlineUrl is not specified, use base64 for SharedWorker and blob for Worker
const resolvedInlineUrl = inlineUrl
? inlineUrl
: workerConstructor === 'SharedWorker'
? 'base64'
: 'blob'

if (
workerConstructor === 'SharedWorker' &&
resolvedInlineUrl === 'blob'
) {
config.logger.warn(
colors.yellow(
`\nThe inlined SharedWorker: ${id} does not work with blob URL, considering set 'worker.inlineUrl' to 'base64'. \n`,
),
)
}

return {
code: inlineUrl === 'blob' ? blobCode : base64Code,
code: resolvedInlineUrl === 'blob' ? blobCode : base64Code,
// Empty sourcemap to suppress Rollup warning
map: { mappings: '' },
}
Expand Down
2 changes: 1 addition & 1 deletion playground/worker/__tests__/es/es-worker.spec.ts
Expand Up @@ -76,7 +76,7 @@ describe.runIf(isBuild)('build', () => {
expect(content).toMatch(`(window.URL||window.webkitURL).createObjectURL`)
expect(content).toMatch(`window.Blob`)
expect(content).toMatch(
/try\{return e\?new Worker\(.+\):new Worker\("data:application\/javascript;base64,"\+/,
/try\{return .*\?new Worker\(.+\):new Worker\("data:application\/javascript;base64,"\+/,
)
})

Expand Down
Expand Up @@ -11,9 +11,14 @@ describe.runIf(isBuild)('build', () => {
const index = files.find((f) => f.includes('main-module'))
const content = fs.readFileSync(path.resolve(assetsDir, index), 'utf-8')

// inlined
// inline worker
expect(content).toMatch(
`return new Worker("data:application/javascript;base64,"+`,
/try\{return .*\?new Worker\(.+\):new Worker\("data:application\/javascript;base64,"\+/,
)

// inline sharedworker
expect(content).toMatch(
`return new SharedWorker("data:application/javascript;base64,"+`,
)
})
})
2 changes: 1 addition & 1 deletion playground/worker/__tests__/inline-url/vite.config.js
@@ -1 +1 @@
module.exports = require('../../vite.config-inline-url')
export { default } from '../../vite.config-inline-url'
6 changes: 6 additions & 0 deletions playground/worker/index.html
Expand Up @@ -26,6 +26,12 @@ <h2 class="format-iife">format iife:</h2>
</p>
<code class="pong-inline"></code>

<p>
import InlineSharedWorker from '../my-shared-worker?sharedworker&inline'
<span class="classname">.pong-shared-inline</span>
</p>
<code class="pong-shared-inline"></code>

<p>
import TSOutputWorker from '../possible-ts-output-worker?worker'
<span class="classname">.pong-ts-output</span>
Expand Down
11 changes: 4 additions & 7 deletions playground/worker/my-shared-worker.ts
@@ -1,14 +1,11 @@
const ports = new Set()
let sharedWorkerCount = 0

// @ts-expect-error onconnect exists in worker
self.onconnect = (event) => {
sharedWorkerCount++
const port = event.ports[0]
ports.add(port)
port.postMessage('pong')
port.onmessage = () => {
ports.forEach((p: any) => {
p.postMessage('pong')
})
if (sharedWorkerCount === 2) {
port.postMessage('pong')
}
}

Expand Down
2 changes: 2 additions & 0 deletions playground/worker/vite.config-es.js
@@ -1,6 +1,8 @@
import vite from 'vite'
import workerPluginTestPlugin from './worker-plugin-test-plugin'

/** @type {import('vite').UserConfig} */
// @ts-expect-error typecast
export default vite.defineConfig({
base: '/es/',
resolve: {
Expand Down
16 changes: 11 additions & 5 deletions playground/worker/vite.config-inline-url.js
@@ -1,5 +1,11 @@
const config = require('./vite.config-es')
config.worker.inlineUrl = 'base64'
config.base = '/inline-url/'
config.build.outDir = 'dist/inline-url'
module.exports = config
import { defineConfig } from 'vite'
import config from './vite.config-es'

export default defineConfig({
...config,
base: '/inline-url/',
build: {
...config.build,
outDir: 'dist/inline-url',
},
})
26 changes: 21 additions & 5 deletions playground/worker/worker/main-module.js
@@ -1,5 +1,6 @@
import myWorker from '../my-worker.ts?worker'
import InlineWorker from '../my-worker.ts?worker&inline'
import InlineSharedWorker from '../my-shared-worker?sharedworker&inline'
import mySharedWorker from '../my-shared-worker?sharedworker&name=shared'
import TSOutputWorker from '../possible-ts-output-worker?worker'
import NestedWorker from '../worker-nested-worker?worker'
Expand All @@ -26,11 +27,26 @@ inlineWorker.addEventListener('message', (e) => {
text('.pong-inline', e.data.msg)
})

const sharedWorker = new mySharedWorker()
sharedWorker.port.addEventListener('message', (event) => {
text('.tick-count', event.data)
})
sharedWorker.port.start()
const startSharedWorker = () => {
const sharedWorker = new mySharedWorker()
sharedWorker.port.addEventListener('message', (event) => {
text('.tick-count', event.data)
})
sharedWorker.port.start()
}
startSharedWorker()
startSharedWorker()

const startInlineSharedWorker = () => {
const inlineSharedWorker = new InlineSharedWorker()
inlineSharedWorker.port.addEventListener('message', (event) => {
text('.pong-shared-inline', event.data)
})
inlineSharedWorker.port.start()
}

startInlineSharedWorker()
startInlineSharedWorker()

const tsOutputWorker = new TSOutputWorker()
tsOutputWorker.postMessage('ping')
Expand Down

0 comments on commit dbe765b

Please sign in to comment.