Skip to content

Commit

Permalink
test: worker with relative base
Browse files Browse the repository at this point in the history
  • Loading branch information
patak-dev committed May 17, 2022
1 parent 7629352 commit f785bed
Show file tree
Hide file tree
Showing 7 changed files with 186 additions and 4 deletions.
7 changes: 5 additions & 2 deletions packages/vite/src/node/plugins/worker.ts
Expand Up @@ -156,7 +156,7 @@ function encodeWorkerAssetFileName(
): string {
const { fileNameHash } = workerCache
const hash = getHash(fileName)
if (!fileNameHash.get(fileName)) {
if (!fileNameHash.get(hash)) {
fileNameHash.set(hash, fileName)
}
return `__VITE_WORKER_ASSET__${hash}__`
Expand Down Expand Up @@ -297,10 +297,13 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
while ((match = workerAssetUrlRE.exec(code))) {
const [full, hash] = match
const filename = fileNameHash.get(hash)!
const outputFilepath = path.relative(
let outputFilepath = path.relative(
path.dirname(chunk.fileName),
filename
)
if (!outputFilepath.startsWith('.')) {
outputFilepath = './' + outputFilepath
}
const replacement = JSON.stringify(outputFilepath).slice(1, -1)
s.overwrite(match.index, match.index + full.length, replacement, {
contentOnly: true
Expand Down
127 changes: 127 additions & 0 deletions playground/worker/__tests__/relative-base/relative-base-worker.spec.ts
@@ -0,0 +1,127 @@
import fs from 'fs'
import path from 'path'
import type { Page } from 'playwright-chromium'
import { isBuild, page, testDir, untilUpdated } from '~utils'

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.each([[true], [false]])('shared worker', async (doTick) => {
if (doTick) {
await page.click('.tick-shared')
}
await waitSharedWorkerTick(page)
})

test('worker emitted and import.meta.url in nested worker (serve)', async () => {
expect(await page.textContent('.nested-worker')).toMatch(
'worker-nested-worker'
)
expect(await page.textContent('.nested-worker-module')).toMatch('sub-worker')
expect(await page.textContent('.nested-worker-constructor')).toMatch(
'"type":"constructor"'
)
})

describe.runIf(isBuild)('build', () => {
// assert correct files
test('inlined code generation', async () => {
const chunksDir = path.resolve(testDir, 'dist/chunks')
const files = fs.readdirSync(chunksDir)
const index = files.find((f) => f.includes('main-module'))
const content = fs.readFileSync(path.resolve(chunksDir, index), 'utf-8')
const workerEntriesDir = path.resolve(testDir, 'dist/worker-entries')
const workerFiles = fs.readdirSync(workerEntriesDir)
const worker = workerFiles.find((f) => f.includes('worker_entry.my-worker'))
const workerContent = fs.readFileSync(
path.resolve(workerEntriesDir, 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("../worker-entries/`)
expect(content).toMatch(`new SharedWorker("../worker-entries/`)
// inlined
expect(content).toMatch(`(window.URL||window.webkitURL).createObjectURL`)
expect(content).toMatch(`window.Blob`)
})

test('worker emitted and import.meta.url in nested worker (build)', async () => {
expect(await page.textContent('.nested-worker-module')).toMatch(
'"type":"module"'
)
expect(await page.textContent('.nested-worker-constructor')).toMatch(
'"type":"constructor"'
)
})
})

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

// TODO: Maybe we can modify classic-worker.js and classic-shared-worker.js to take into account the different asset paths
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('.emit-chunk-worker')).toMatch(
'["A string",{"type":"emit-chunk-sub-worker","data":"A string"},{"type":"module-and-worker:worker","data":"A string"},{"type":"module-and-worker:module","data":"module and worker"},{"type":"emit-chunk-sub-worker","data":{"module":"module and worker","msg1":"module1","msg2":"module2","msg3":"module3"}}]'
)
expect(await page.textContent('.emit-chunk-dynamic-import-worker')).toMatch(
'"A string./"'
)
})

test('import.meta.glob in worker', async () => {
expect(await page.textContent('.importMetaGlob-worker')).toMatch('["')
})

test('import.meta.glob with eager in worker', async () => {
expect(await page.textContent('.importMetaGlobEager-worker')).toMatch('["')
})
1 change: 1 addition & 0 deletions playground/worker/__tests__/relative-base/vite.config.js
@@ -0,0 +1 @@
module.exports = require('../../vite.config-relative-base')
5 changes: 4 additions & 1 deletion playground/worker/classic-shared-worker.js
@@ -1,4 +1,7 @@
importScripts(`/${self.location.pathname.split('/')[1]}/classic.js`)
let base = `/${self.location.pathname.split('/')[1]}`
if (base === `/worker-entries`) base = '' // relative base

importScripts(`${base}/classic.js`)

self.onconnect = (event) => {
const port = event.ports[0]
Expand Down
5 changes: 4 additions & 1 deletion playground/worker/classic-worker.js
@@ -1,4 +1,7 @@
importScripts(`/${self.location.pathname.split("/")[1]}/classic.js`)
let base = `/${self.location.pathname.split('/')[1]}`
if (base === `/worker-entries`) base = '' // relative base

importScripts(`${base}/classic.js`)

self.addEventListener('message', () => {
self.postMessage(self.constant)
Expand Down
3 changes: 3 additions & 0 deletions playground/worker/package.json
Expand Up @@ -18,6 +18,9 @@
"dev:sourcemap-inline": "cross-env WORKER_MODE=inline vite --config ./vite.config-sourcemap.js dev",
"build:sourcemap-inline": "cross-env WORKER_MODE=inline vite --config ./vite.config-sourcemap.js build",
"preview:sourcemap-inline": "cross-env WORKER_MODE=inline vite --config ./vite.config-sourcemap.js preview",
"dev:relative-base": "cross-env WORKER_MODE=inline vite --config ./vite.config-relative-base.js dev",
"build:relative-base": "cross-env WORKER_MODE=inline vite --config ./vite.config-relative-base.js build",
"preview:relative-base": "cross-env WORKER_MODE=inline vite --config ./vite.config-relative-base.js preview",
"debug": "node --inspect-brk ../../packages/vite/bin/vite"
},
"devDependencies": {
Expand Down
42 changes: 42 additions & 0 deletions playground/worker/vite.config-relative-base.js
@@ -0,0 +1,42 @@
const vueJsx = require('@vitejs/plugin-vue-jsx')
const vite = require('vite')
const path = require('path')

module.exports = vite.defineConfig({
base: './',
enforce: 'pre',
worker: {
format: 'es',
plugins: [vueJsx()],
rollupOptions: {
output: {
assetFileNames: 'worker-assets/worker_asset.[name]-[hash].[ext]',
chunkFileNames: 'worker-chunks/worker_chunk.[name]-[hash].js',
entryFileNames: 'worker-entries/worker_entry.[name]-[hash].js'
}
}
},
build: {
outDir: 'dist',
rollupOptions: {
output: {
assetFileNames: 'other-assets/[name]-[hash].[ext]',
chunkFileNames: 'chunks/[name]-[hash].js',
entryFileNames: 'entries/[name]-[hash].js'
}
}
},
plugins: [
{
name: 'resolve-format-es',
transform(code, id) {
if (id.includes('main.js')) {
return code.replace(
`/* flag: will replace in vite config import("./format-es.js") */`,
`import("./main-format-es")`
)
}
}
}
]
})

0 comments on commit f785bed

Please sign in to comment.