Skip to content
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

fix: errors in worker handling #7236

Merged
merged 33 commits into from Mar 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
806ea51
chore(deps): update all non-major dependencies
renovate-bot Mar 8, 2022
ccc789c
test: legacy worker
poyoho Mar 9, 2022
f19b8b1
fix: worker options
poyoho Mar 9, 2022
ccbf13d
Merge branch 'vitejs:main' into main
poyoho Mar 9, 2022
bc7f9aa
Revert "chore(deps): update all non-major dependencies"
poyoho Mar 9, 2022
2690dd5
Revert "chore(deps): update all non-major dependencies"
poyoho Mar 9, 2022
ff1d716
chore: rebase
poyoho Mar 9, 2022
3070519
fix: worker options
poyoho Mar 9, 2022
c7b7809
Revert "chore(deps): update all non-major dependencies"
poyoho Mar 9, 2022
0c9e0b3
Revert "chore(deps): update all non-major dependencies"
poyoho Mar 9, 2022
1912a16
test: legacy worker
poyoho Mar 9, 2022
ab7c306
feat: ignore importAnalysis in worker
poyoho Mar 9, 2022
f3b15e9
chore: remove worker test
poyoho Mar 9, 2022
ec1e532
chore: remove test
poyoho Mar 9, 2022
897c005
chore: code style
poyoho Mar 9, 2022
6b8dad2
feat: supplementary test
poyoho Mar 9, 2022
9a8b713
refactor: isWorker move into funtion params
poyoho Mar 9, 2022
9ccc1dd
chore: code style
poyoho Mar 9, 2022
fe8ac39
Revert "refactor: isWorker move into funtion params"
poyoho Mar 10, 2022
baec513
chore: ignore import analyse in worker
poyoho Mar 10, 2022
81d07f0
fix: ignore dynamic import analyse in worker
poyoho Mar 10, 2022
5870ca2
chore: code style
poyoho Mar 10, 2022
7a4db00
feat: module import
poyoho Mar 10, 2022
71fe7b5
feat: one import module
poyoho Mar 10, 2022
a167395
chore: nice output for worker dev
poyoho Mar 11, 2022
df56fa3
refactor: worker test
poyoho Mar 16, 2022
1664dce
test: add format: es worker test
poyoho Mar 16, 2022
59d60d9
fix: test
poyoho Mar 16, 2022
7892f20
test: add es worker test
poyoho Mar 16, 2022
7764280
feat: rename the config file to vite.config.js
poyoho Mar 16, 2022
19af9e6
chore: rebase
poyoho Mar 16, 2022
f3e8b93
test: remove comment
poyoho Mar 16, 2022
0d6ebe8
feat: nice error message
poyoho Mar 21, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
102 changes: 102 additions & 0 deletions packages/playground/worker/__tests__/es/es-worker.spec.ts
@@ -0,0 +1,102 @@
import fs from 'fs'
import path from 'path'
import { untilUpdated, isBuild, testDir } from '../../../testUtils'
import type { Page } from 'playwright-chromium'

test('normal', async () => {
await page.click('.ping')
await untilUpdated(() => page.textContent('.pong'), 'pong')
await untilUpdated(
() => page.textContent('.mode'),
isBuild ? 'production' : 'development'
)
await untilUpdated(
() => page.textContent('.bundle-with-plugin'),
'worker bundle with plugin success!'
)
})

test('TS output', async () => {
await page.click('.ping-ts-output')
await untilUpdated(() => page.textContent('.pong-ts-output'), 'pong')
})

test('inlined', async () => {
await page.click('.ping-inline')
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++
if (resolvedSharedWorkerCount < 2) return

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)
})

test('worker emitted', async () => {
await untilUpdated(() => page.textContent('.nested-worker'), 'pong')
})

if (isBuild) {
const assetsDir = path.resolve(testDir, 'dist/es/assets')
// assert correct files
test('inlined code generation', async () => {
const files = fs.readdirSync(assetsDir)
expect(files.length).toBe(20)
const index = files.find((f) => f.includes('main-module'))
const content = fs.readFileSync(path.resolve(assetsDir, index), 'utf-8')
const worker = files.find((f) => f.includes('my-worker'))
const workerContent = fs.readFileSync(
path.resolve(assetsDir, worker),
'utf-8'
)

// worker should have all imports resolved and no exports
expect(workerContent).not.toMatch(`import`)
expect(workerContent).not.toMatch(`export`)
// chunk
expect(content).toMatch(`new Worker("/es/assets`)
expect(content).toMatch(`new SharedWorker("/es/assets`)
// inlined
expect(content).toMatch(`(window.URL||window.webkitURL).createObjectURL`)
expect(content).toMatch(`window.Blob`)
})
}

test('module worker', async () => {
expect(await page.textContent('.shared-worker-import-meta-url')).toMatch(
'A string'
)
})

test('classic worker', async () => {
expect(await page.textContent('.classic-worker')).toMatch('A classic')
expect(await page.textContent('.classic-shared-worker')).toMatch('A classic')
})

test('emit chunk', async () => {
expect(await page.textContent('.emti-chunk-worker')).toMatch(
'{"msg1":"module1","msg2":"module2","msg3":"module3"}'
)
expect(await page.textContent('.emti-chunk-dynamic-import-worker')).toMatch(
'"A string/es/"'
)
})
1 change: 1 addition & 0 deletions packages/playground/worker/__tests__/es/vite.config.js
@@ -0,0 +1 @@
module.exports = require('../../vite.config-es')
22 changes: 12 additions & 10 deletions packages/playground/worker/__tests__/worker.spec.ts
Expand Up @@ -53,19 +53,15 @@ test.concurrent.each([[true], [false]])('shared worker', async (doTick) => {

test('worker emitted', async () => {
await untilUpdated(() => page.textContent('.nested-worker'), 'pong')
await untilUpdated(
() => page.textContent('.nested-worker-dynamic-import'),
'"msg":"pong"'
)
})

if (isBuild) {
const assetsDir = path.resolve(testDir, 'dist/assets')
const assetsDir = path.resolve(testDir, 'dist/iife/assets')
// assert correct files
test('inlined code generation', async () => {
const files = fs.readdirSync(assetsDir)
expect(files.length).toBe(11)
const index = files.find((f) => f.includes('index'))
expect(files.length).toBe(13)
const index = files.find((f) => f.includes('main-module'))
const content = fs.readFileSync(path.resolve(assetsDir, index), 'utf-8')
const worker = files.find((f) => f.includes('my-worker'))
const workerContent = fs.readFileSync(
Expand All @@ -77,15 +73,21 @@ if (isBuild) {
expect(workerContent).not.toMatch(`import`)
expect(workerContent).not.toMatch(`export`)
// chunk
expect(content).toMatch(`new Worker("/assets`)
expect(content).toMatch(`new SharedWorker("/assets`)
expect(content).toMatch(`new Worker("/iife/assets`)
expect(content).toMatch(`new SharedWorker("/iife/assets`)
// inlined
expect(content).toMatch(`(window.URL||window.webkitURL).createObjectURL`)
expect(content).toMatch(`window.Blob`)
})
}

test('classic worker is run', async () => {
test('module worker', async () => {
expect(await page.textContent('.shared-worker-import-meta-url')).toMatch(
'A string'
)
})

test('classic worker', async () => {
expect(await page.textContent('.classic-worker')).toMatch('A classic')
expect(await page.textContent('.classic-shared-worker')).toMatch('A classic')
})
@@ -1,4 +1,4 @@
importScripts('/classic.js')
importScripts(`/${self.location.pathname.split('/')[1]}/classic.js`)

self.onconnect = (event) => {
const port = event.ports[0]
Expand Down
30 changes: 3 additions & 27 deletions packages/playground/worker/classic-worker.js
@@ -1,29 +1,5 @@
// prettier-ignore
function text(el, text) {
document.querySelector(el).textContent = text
}
importScripts(`/${self.location.pathname.split("/")[1]}/classic.js`)

const classicWorker = new Worker(
new URL('./newUrl/classic-worker.js', import.meta.url) /* , */ ,
// test comment

)

classicWorker.addEventListener('message', ({ data }) => {
text('.classic-worker', data)
})
classicWorker.postMessage('ping')

const classicSharedWorker = new SharedWorker(
new URL('./newUrl/classic-shared-worker.js', import.meta.url),
{
type: 'classic'
}
)
classicSharedWorker.port.addEventListener('message', (ev) => {
text(
'.classic-shared-worker',
ev.data
)
self.addEventListener('message', () => {
self.postMessage(self.constant)
})
classicSharedWorker.port.start()
@@ -0,0 +1,3 @@
import('./modules/module').then((module) => {
self.postMessage(module.default + import.meta.env.BASE_URL)
})
7 changes: 7 additions & 0 deletions packages/playground/worker/emit-chunk-nested-worker.js
@@ -0,0 +1,7 @@
import SubWorker from './emit-chunk-sub-worker?worker'

const subWorker = new SubWorker()

subWorker.onmessage = (event) => {
self.postMessage(event.data)
}
6 changes: 6 additions & 0 deletions packages/playground/worker/emit-chunk-sub-worker.js
@@ -0,0 +1,6 @@
Promise.all([import('./modules/module2'), import('./modules/module3')]).then(
(data) => {
const _data = { ...data[0], ...data[1] }
self.postMessage(_data)
}
)
165 changes: 56 additions & 109 deletions packages/playground/worker/index.html
@@ -1,3 +1,4 @@
<h2 class="format-iife">format iife:</h2>
<div>Expected values: <span class="mode-true"></span></div>
<button class="ping">Ping</button>
<div>
Expand All @@ -20,113 +21,59 @@
<span class="tick-count">0</span>
</div>

<p>new Worker(new Url('path', import.meta.url), { type: 'module' })</p>
<div class="worker-import-meta-url"></div>

<p>new SharedWorker(new Url('path', import.meta.url), { type: 'module' })</p>
<div class="shared-worker-import-meta-url"></div>

<p>nested worker</p>
<div class="nested-worker"></div>
<div class="nested-worker-dynamic-import"></div>
<p>new Worker(new Url('path', import.meta.url))</p>
<div class="classic-worker"></div>

<p>new Worker(new Url('path', import.meta.url), { type: 'classic' })</p>
<div class="classic-shared-worker"></div>

<script type="module">
import myWorker from './my-worker?worker'
import InlineWorker from './my-worker?worker&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'
import { mode } from './workerImport'
import './classic-worker'

document.querySelector('.mode-true').textContent = mode

const worker = new myWorker()
worker.addEventListener('message', (e) => {
text('.pong', e.data.msg)
text('.mode', e.data.mode)
text('.bundle-with-plugin', e.data.bundleWithPlugin)
})

document.querySelector('.ping').addEventListener('click', () => {
worker.postMessage('ping')
})

const inlineWorker = new InlineWorker()
inlineWorker.addEventListener('message', (e) => {
text('.pong-inline', e.data.msg)
})

document.querySelector('.ping-inline').addEventListener('click', () => {
inlineWorker.postMessage('ping')
})

const sharedWorker = new mySharedWorker()
document.querySelector('.tick-shared').addEventListener('click', () => {
sharedWorker.port.postMessage('tick')
})

sharedWorker.port.addEventListener('message', (event) => {
text('.tick-count', event.data)
})

sharedWorker.port.start()

const tsOutputWorker = new TSOutputWorker()
tsOutputWorker.addEventListener('message', (e) => {
text('.pong-ts-output', e.data.msg)
})

document.querySelector('.ping-ts-output').addEventListener('click', () => {
tsOutputWorker.postMessage('ping')
})

function text(el, text) {
document.querySelector(el).textContent = text
<p>
new Worker(new Url('./url-worker.js', import.meta.url), { type: 'module' })
<span class="classname">.worker-import-meta-url</span>
</p>
<code class="worker-import-meta-url"></code>

<p>
new SharedWorker(new Url('./url-shared-worker.js', import.meta.url), { type:
'module' })
<span class="classname">.shared-worker-import-meta-url</span>
</p>
<code class="shared-worker-import-meta-url"></code>

<p>
import NestedWorker from './worker-nested-worker?worker' - nested worker
<span class="classname">.nested-worker</span>
</p>
<code class="nested-worker"></code>

<p>
new Worker(new Url('./classic-worker.js', import.meta.url))
<span class="classname">.classic-worker</span>
</p>
<code class="classic-worker"></code>

<p>
new SharedWorker(new Url('./classic-shared-worker.js', import.meta.url), {
type: 'classic' })
<span class="classname">.classic-shared-worker</span>
</p>
<code class="classic-shared-worker"></code>

<hr />
<h2 class="format-es"></h2>

<p>
worker emit chunk
<span class="classname">.emti-chunk-worker</span>
</p>
<code class="emti-chunk-worker"></code>

<p>
worker dynamic import to emit chunk
<span class="classname">.emti-chunk-dynamic-import-worker</span>
</p>
<code class="emti-chunk-dynamic-import-worker"></code>

<style>
p {
background: rgba(0, 0, 0, 0.1);
}
const workerOptions = { type: 'module' }
// url import worker
const w = new Worker(
new URL('./newUrl/url-worker.js', import.meta.url),
/* @vite-ignore */ workerOptions
)
w.addEventListener('message', (ev) =>
text(
'.worker-import-meta-url',
'worker import.meta.url' + JSON.stringify(ev.data)
)
)

const genWorkerName = () => 'module'
const w2 = new SharedWorker(
new URL('./newUrl/url-shared-worker.js', import.meta.url),
{
/* @vite-ignore */
name: genWorkerName(),
type: 'module'
}
)
w2.port.addEventListener('message', (ev) => {
text(
'.shared-worker-import-meta-url',
'shared-worker import.meta.url' + JSON.stringify(ev.data)
)
})
w2.port.start()

const nestedWorker = new NestedWorker()
nestedWorker.addEventListener('message', (ev) => {
console.log(ev)
if (typeof ev.data === 'string') {
text('.nested-worker', ev.data)
} else {
text('.nested-worker-dynamic-import', JSON.stringify(ev.data))
}
})
nestedWorker.postMessage('ping')
</script>
.classname {
color: green;
}
</style>
<script type="module" src="./worker/main.js"></script>
1 change: 1 addition & 0 deletions packages/playground/worker/modules/module1.js
@@ -0,0 +1 @@
export const msg1 = 'module1'
3 changes: 3 additions & 0 deletions packages/playground/worker/modules/module2.js
@@ -0,0 +1,3 @@
export * from './module'
export * from './module1'
export const msg2 = 'module2'
2 changes: 2 additions & 0 deletions packages/playground/worker/modules/module3.js
@@ -0,0 +1,2 @@
export * from './module'
export const msg3 = 'module3'