-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
/
worker.ts
103 lines (93 loc) · 2.97 KB
/
worker.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import { ResolvedConfig } from '../config'
import { Plugin } from '../plugin'
import { parse as parseUrl } from 'url'
import qs, { ParsedUrlQuery } from 'querystring'
import { fileToUrl } from './asset'
import { cleanUrl, injectQuery } from '../utils'
import Rollup from 'rollup'
import { ENV_PUBLIC_PATH } from '../constants'
function parseWorkerRequest(id: string): ParsedUrlQuery | null {
const { search } = parseUrl(id)
if (!search) {
return null
}
return qs.parse(search.slice(1))
}
const WorkerFileId = 'worker_file'
export function webWorkerPlugin(config: ResolvedConfig): Plugin {
const isBuild = config.command === 'build'
return {
name: 'vite:worker',
load(id) {
if (isBuild) {
const parsedQuery = parseWorkerRequest(id)
if (
parsedQuery &&
(parsedQuery.worker ?? parsedQuery.sharedworker) != null
) {
return ''
}
}
},
async transform(_, id) {
const query = parseWorkerRequest(id)
if (query && query[WorkerFileId] != null) {
return {
code: `import '${ENV_PUBLIC_PATH}'\n` + _
}
}
if (
query == null ||
(query && (query.worker ?? query.sharedworker) == null)
) {
return
}
let url: string
if (isBuild) {
if (query.inline != null) {
// bundle the file as entry to support imports and inline as blob
// data url
const rollup = require('rollup') as typeof Rollup
const bundle = await rollup.rollup({
input: cleanUrl(id),
plugins: config.plugins as Plugin[]
})
try {
const { output } = await bundle.generate({
format: 'es',
sourcemap: config.build.sourcemap
})
return `const blob = new Blob([atob(\"${Buffer.from(output[0].code).toString('base64')}\")], { type: 'text/javascript;charset=utf-8' });
export default function WorkerWrapper() {
const objURL = (window.URL || window.webkitURL).createObjectURL(blob);
try {
return new Worker(objURL);
} finally {
(window.URL || window.webkitURL).revokeObjectURL(objURL);
}
}`
} finally {
await bundle.close()
}
} else {
// emit as separate chunk
url = `__VITE_ASSET__${this.emitFile({
type: 'chunk',
id: cleanUrl(id)
})}__`
}
} else {
url = await fileToUrl(cleanUrl(id), config, this)
url = injectQuery(url, WorkerFileId)
}
const workerConstructor =
query.sharedworker != null ? 'SharedWorker' : 'Worker'
const workerOptions = { type: 'module' }
return `export default function WorkerWrapper() {
return new ${workerConstructor}(${JSON.stringify(
url
)}, ${JSON.stringify(workerOptions, null, 2)})
}`
}
}
}