diff --git a/docs/guide/assets.md b/docs/guide/assets.md index f99d74224d3c1f..77988ff2092a08 100644 --- a/docs/guide/assets.md +++ b/docs/guide/assets.md @@ -45,7 +45,7 @@ import shaderString from './shader.glsl?raw' ### Importing Script as a Worker -Scripts can be imported as web workers with the `?worker` suffix. +Scripts can be imported as web workers with the `?worker` or `?sharedworker` suffix. ```js // Separate chunk in the production build diff --git a/docs/guide/features.md b/docs/guide/features.md index 383735ba0f8b4e..040376642ac719 100644 --- a/docs/guide/features.md +++ b/docs/guide/features.md @@ -290,7 +290,7 @@ In the production build, `.wasm` files smaller than `assetInlineLimit` will be i ## Web Workers -A web worker script can be directly imported by appending `?worker` to the import request. The default export will be a custom worker constructor: +A web worker script can be directly imported by appending `?worker` or `?sharedworker` to the import request. The default export will be a custom worker constructor: ```js import MyWorker from './worker?worker' diff --git a/packages/playground/worker/__tests__/worker.spec.ts b/packages/playground/worker/__tests__/worker.spec.ts index a096472547df46..9e19a9f60a8abf 100644 --- a/packages/playground/worker/__tests__/worker.spec.ts +++ b/packages/playground/worker/__tests__/worker.spec.ts @@ -1,6 +1,7 @@ import fs from 'fs' import path from 'path' import { untilUpdated, isBuild, testDir } from '../../testUtils' +import { Page } from 'playwright-chromium' test('normal', async () => { await page.click('.ping') @@ -16,17 +17,42 @@ test('inlined', async () => { await untilUpdated(() => page.textContent('.pong-inline'), 'pong') }) +const waitSharedWorkerTick = ( + (resolvedSharedWorkerCount: number) => async (page: Page) => { + await untilUpdated(async () => { + const count = await page.textContent('.tick-count') + // ignore the initial 0 + return count === '1' ? 'page loaded' : '' + }, 'page loaded') + // test.concurrent sequential is not guaranteed + // force page to wait to ensure two pages overlap in time + resolvedSharedWorkerCount++ + + await untilUpdated(() => { + return resolvedSharedWorkerCount === 2 ? 'all pages loaded' : '' + }, 'all pages loaded') + } +)(0) + +test.concurrent.each([[true], [false]])('shared worker', async (doTick) => { + if (doTick) { + await page.click('.tick-shared') + } + await waitSharedWorkerTick(page) +}) + if (isBuild) { // assert correct files test('inlined code generation', async () => { const assetsDir = path.resolve(testDir, 'dist/assets') const files = fs.readdirSync(assetsDir) - // should have only 1 worker chunk - expect(files.length).toBe(2) + // should have 2 worker chunk + expect(files.length).toBe(3) const index = files.find((f) => f.includes('index')) const content = fs.readFileSync(path.resolve(assetsDir, index), 'utf-8') // chunk expect(content).toMatch(`new Worker("/assets`) + expect(content).toMatch(`new SharedWorker("/assets`) // inlined expect(content).toMatch(`(window.URL||window.webkitURL).createObjectURL`) }) diff --git a/packages/playground/worker/index.html b/packages/playground/worker/index.html index e7bd7c78c1adb2..3203fb0a98874e 100644 --- a/packages/playground/worker/index.html +++ b/packages/playground/worker/index.html @@ -6,9 +6,16 @@