From 95297dd1846318697f6b3b40752ba9fa43664d1a Mon Sep 17 00:00:00 2001
From: yoho
Date: Sat, 21 May 2022 15:56:14 +0800
Subject: [PATCH] feat: worker support query url (#7914)
---
packages/vite/src/node/plugins/worker.ts | 47 ++++++++++++++++---
.../src/node/plugins/workerImportMetaUrl.ts | 37 +--------------
.../worker/__tests__/es/es-worker.spec.ts | 8 +++-
.../worker/__tests__/iife/worker.spec.ts | 8 +++-
.../sourcemap-hidden-worker.spec.ts | 2 +-
.../sourcemap-inline-worker.spec.ts | 2 +-
.../sourcemap/sourcemap-worker.spec.ts | 2 +-
playground/worker/index.html | 6 +++
playground/worker/simple-worker.js | 1 +
playground/worker/worker/main-url.js | 11 +++++
playground/worker/worker/main.js | 1 +
11 files changed, 79 insertions(+), 46 deletions(-)
create mode 100644 playground/worker/simple-worker.js
create mode 100644 playground/worker/worker/main-url.js
diff --git a/packages/vite/src/node/plugins/worker.ts b/packages/vite/src/node/plugins/worker.ts
index 21d61b579adbb0..99eef51a4a2bd7 100644
--- a/packages/vite/src/node/plugins/worker.ts
+++ b/packages/vite/src/node/plugins/worker.ts
@@ -3,6 +3,8 @@ import MagicString from 'magic-string'
import type { EmittedAsset, OutputChunk, TransformPluginContext } from 'rollup'
import type { ResolvedConfig } from '../config'
import type { Plugin } from '../plugin'
+import type { ViteDevServer } from '../server'
+import { ENV_ENTRY, ENV_PUBLIC_PATH } from '../constants'
import {
cleanUrl,
getHash,
@@ -10,7 +12,6 @@ import {
isRelativeBase,
parseRequest
} from '../utils'
-import { ENV_PUBLIC_PATH } from '../constants'
import { onRollupWarning } from '../build'
import { fileToUrl } from './asset'
@@ -27,7 +28,9 @@ interface WorkerCache {
fileNameHash: Map
}
-const WorkerFileId = 'worker_file'
+export type WorkerType = 'classic' | 'module' | 'ignore'
+
+export const WORKER_FILE_ID = 'worker_file'
const workerCache = new WeakMap()
function saveEmitWorkerAsset(
@@ -188,10 +191,16 @@ export async function workerFileToUrl(
export function webWorkerPlugin(config: ResolvedConfig): Plugin {
const isBuild = config.command === 'build'
+ let server: ViteDevServer
const isWorker = config.isWorker
+
return {
name: 'vite:worker',
+ configureServer(_server) {
+ server = _server
+ },
+
buildStart() {
if (isWorker) {
return
@@ -215,11 +224,30 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
}
},
- async transform(_, id) {
+ async transform(raw, id) {
const query = parseRequest(id)
- if (query && query[WorkerFileId] != null) {
+ if (query && query[WORKER_FILE_ID] != null && query['type'] != null) {
+ const workerType = query['type'] as WorkerType
+ let injectEnv = ''
+
+ if (workerType === 'classic') {
+ injectEnv = `importScripts('${ENV_PUBLIC_PATH}')\n`
+ } else if (workerType === 'module') {
+ injectEnv = `import '${ENV_PUBLIC_PATH}'\n`
+ } else if (workerType === 'ignore') {
+ if (isBuild) {
+ injectEnv = ''
+ } else if (server) {
+ // dynamic worker type we can't know how import the env
+ // so we copy /@vite/env code of server transform result into file header
+ const { moduleGraph } = server
+ const module = moduleGraph.getModuleById(ENV_ENTRY)
+ injectEnv = module?.transformResult?.code || ''
+ }
+ }
+
return {
- code: `import '${ENV_PUBLIC_PATH}'\n` + _
+ code: injectEnv + raw
}
}
if (
@@ -259,7 +287,14 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
}
} else {
url = await fileToUrl(cleanUrl(id), config, this)
- url = injectQuery(url, WorkerFileId)
+ url = injectQuery(url, WORKER_FILE_ID)
+ }
+
+ if (query.url != null) {
+ return {
+ code: `export default ${JSON.stringify(url)}`,
+ map: { mappings: '' } // Empty sourcemap to suppress Rollup warning
+ }
}
const workerConstructor =
diff --git a/packages/vite/src/node/plugins/workerImportMetaUrl.ts b/packages/vite/src/node/plugins/workerImportMetaUrl.ts
index 92bac1ab997ae1..3e7426f52cda24 100644
--- a/packages/vite/src/node/plugins/workerImportMetaUrl.ts
+++ b/packages/vite/src/node/plugins/workerImportMetaUrl.ts
@@ -6,16 +6,12 @@ import { stripLiteral } from 'strip-literal'
import type { ResolvedConfig } from '../config'
import type { Plugin } from '../plugin'
import { cleanUrl, injectQuery, normalizePath, parseRequest } from '../utils'
-import { ENV_ENTRY, ENV_PUBLIC_PATH } from '../constants'
-import type { ViteDevServer } from '..'
-import { workerFileToUrl } from './worker'
+import type { WorkerType } from './worker'
+import { WORKER_FILE_ID, workerFileToUrl } from './worker'
import { fileToUrl } from './asset'
-type WorkerType = 'classic' | 'module' | 'ignore'
const ignoreFlagRE = /\/\*\s*@vite-ignore\s*\*\//
-const WORKER_FILE_ID = 'worker_url_file'
-
function getWorkerType(raw: string, clean: string, i: number): WorkerType {
function err(e: string, pos: number) {
const error = new Error(e) as RollupError
@@ -68,41 +64,12 @@ function getWorkerType(raw: string, clean: string, i: number): WorkerType {
export function workerImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
const isBuild = config.command === 'build'
- let server: ViteDevServer
return {
name: 'vite:worker-import-meta-url',
- configureServer(_server) {
- server = _server
- },
-
async transform(code, id, options) {
const query = parseRequest(id)
- if (query && query[WORKER_FILE_ID] != null && query['type'] != null) {
- const workerType = query['type'] as WorkerType
- let injectEnv = ''
-
- if (workerType === 'classic') {
- injectEnv = `importScripts('${ENV_PUBLIC_PATH}')\n`
- } else if (workerType === 'module') {
- injectEnv = `import '${ENV_PUBLIC_PATH}'\n`
- } else if (workerType === 'ignore') {
- if (isBuild) {
- injectEnv = ''
- } else if (server) {
- // dynamic worker type we can't know how import the env
- // so we copy /@vite/env code of server transform result into file header
- const { moduleGraph } = server
- const module = moduleGraph.getModuleById(ENV_ENTRY)
- injectEnv = module?.transformResult?.code || ''
- }
- }
-
- return {
- code: injectEnv + code
- }
- }
let s: MagicString | undefined
if (
(code.includes('new Worker') || code.includes('new SharedWorker')) &&
diff --git a/playground/worker/__tests__/es/es-worker.spec.ts b/playground/worker/__tests__/es/es-worker.spec.ts
index 767fd386606afc..b901a7deaeedbc 100644
--- a/playground/worker/__tests__/es/es-worker.spec.ts
+++ b/playground/worker/__tests__/es/es-worker.spec.ts
@@ -66,7 +66,7 @@ describe.runIf(isBuild)('build', () => {
test('inlined code generation', async () => {
const assetsDir = path.resolve(testDir, 'dist/es/assets')
const files = fs.readdirSync(assetsDir)
- expect(files.length).toBe(25)
+ expect(files.length).toBe(27)
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'))
@@ -116,6 +116,12 @@ test('emit chunk', async () => {
)
})
+test('url query worker', async () => {
+ expect(await page.textContent('.simple-worker-url')).toMatch(
+ 'Hello from simple worker!'
+ )
+})
+
test('import.meta.glob in worker', async () => {
expect(await page.textContent('.importMetaGlob-worker')).toMatch('["')
})
diff --git a/playground/worker/__tests__/iife/worker.spec.ts b/playground/worker/__tests__/iife/worker.spec.ts
index 3e5458bbe9a1a2..0aba9611368737 100644
--- a/playground/worker/__tests__/iife/worker.spec.ts
+++ b/playground/worker/__tests__/iife/worker.spec.ts
@@ -65,7 +65,7 @@ describe.runIf(isBuild)('build', () => {
test('inlined code generation', async () => {
const assetsDir = path.resolve(testDir, 'dist/iife/assets')
const files = fs.readdirSync(assetsDir)
- expect(files.length).toBe(13)
+ expect(files.length).toBe(15)
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'))
@@ -106,6 +106,12 @@ test('classic worker', async () => {
expect(await page.textContent('.classic-shared-worker')).toMatch('A classic')
})
+test('url query worker', async () => {
+ expect(await page.textContent('.simple-worker-url')).toMatch(
+ 'Hello from simple worker!'
+ )
+})
+
test('import.meta.glob eager in worker', async () => {
expect(await page.textContent('.importMetaGlobEager-worker')).toMatch('["')
})
diff --git a/playground/worker/__tests__/sourcemap-hidden/sourcemap-hidden-worker.spec.ts b/playground/worker/__tests__/sourcemap-hidden/sourcemap-hidden-worker.spec.ts
index c60be7016d6477..b0a591ac18dd50 100644
--- a/playground/worker/__tests__/sourcemap-hidden/sourcemap-hidden-worker.spec.ts
+++ b/playground/worker/__tests__/sourcemap-hidden/sourcemap-hidden-worker.spec.ts
@@ -9,7 +9,7 @@ describe.runIf(isBuild)('build', () => {
const files = fs.readdirSync(assetsDir)
// should have 2 worker chunk
- expect(files.length).toBe(26)
+ expect(files.length).toBe(30)
const index = files.find((f) => f.includes('main-module'))
const content = fs.readFileSync(path.resolve(assetsDir, index), 'utf-8')
const indexSourcemap = getSourceMapUrl(content)
diff --git a/playground/worker/__tests__/sourcemap-inline/sourcemap-inline-worker.spec.ts b/playground/worker/__tests__/sourcemap-inline/sourcemap-inline-worker.spec.ts
index d82185a3f3f26b..d9f4e9826703e9 100644
--- a/playground/worker/__tests__/sourcemap-inline/sourcemap-inline-worker.spec.ts
+++ b/playground/worker/__tests__/sourcemap-inline/sourcemap-inline-worker.spec.ts
@@ -9,7 +9,7 @@ describe.runIf(isBuild)('build', () => {
const files = fs.readdirSync(assetsDir)
// should have 2 worker chunk
- expect(files.length).toBe(13)
+ expect(files.length).toBe(15)
const index = files.find((f) => f.includes('main-module'))
const content = fs.readFileSync(path.resolve(assetsDir, index), 'utf-8')
const indexSourcemap = getSourceMapUrl(content)
diff --git a/playground/worker/__tests__/sourcemap/sourcemap-worker.spec.ts b/playground/worker/__tests__/sourcemap/sourcemap-worker.spec.ts
index 3b0a300c5e10f0..af4a074549b167 100644
--- a/playground/worker/__tests__/sourcemap/sourcemap-worker.spec.ts
+++ b/playground/worker/__tests__/sourcemap/sourcemap-worker.spec.ts
@@ -8,7 +8,7 @@ describe.runIf(isBuild)('build', () => {
const assetsDir = path.resolve(testDir, 'dist/iife-sourcemap/assets')
const files = fs.readdirSync(assetsDir)
// should have 2 worker chunk
- expect(files.length).toBe(26)
+ expect(files.length).toBe(30)
const index = files.find((f) => f.includes('main-module'))
const content = fs.readFileSync(path.resolve(assetsDir, index), 'utf-8')
const indexSourcemap = getSourceMapUrl(content)
diff --git a/playground/worker/index.html b/playground/worker/index.html
index 243f3657ff0161..1fd387d5a9c08b 100644
--- a/playground/worker/index.html
+++ b/playground/worker/index.html
@@ -72,6 +72,12 @@
+
+ new Worker(new URL('../simple-worker.js', import.meta.url).href)
+ .simple-worker-url
+
+
+
use import.meta.glob with eager in iife worker
.importMetaGlobEager-worker
diff --git a/playground/worker/simple-worker.js b/playground/worker/simple-worker.js
new file mode 100644
index 00000000000000..3b7e9a75fd8c5f
--- /dev/null
+++ b/playground/worker/simple-worker.js
@@ -0,0 +1 @@
+self.postMessage('Hello from simple worker!')
diff --git a/playground/worker/worker/main-url.js b/playground/worker/worker/main-url.js
new file mode 100644
index 00000000000000..ba395926009754
--- /dev/null
+++ b/playground/worker/worker/main-url.js
@@ -0,0 +1,11 @@
+import workerUrl from '../simple-worker?worker&url'
+
+function text(el, text) {
+ document.querySelector(el).textContent = text
+}
+
+const worker = new Worker(workerUrl, { type: 'classic' })
+
+worker.addEventListener('message', (ev) => {
+ text('.simple-worker-url', JSON.stringify(ev.data))
+})
diff --git a/playground/worker/worker/main.js b/playground/worker/worker/main.js
index 953b5ef1bf3b53..ce434c38e79ce6 100644
--- a/playground/worker/worker/main.js
+++ b/playground/worker/worker/main.js
@@ -1,3 +1,4 @@
/* flag: will replace in vite config import("./format-es.js") */
import('./main-module')
import('./main-classic')
+import('./main-url')